diff --git a/.gitignore b/.gitignore
index 84a7ecdcd..9482d8f94 100644
--- a/.gitignore
+++ b/.gitignore
@@ -140,6 +140,7 @@ lib/tron/tron.dart
lib/wownero/wownero.dart
lib/zano/zano.dart
lib/decred/decred.dart
+lib/dogecoin/dogecoin.dart
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png
ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png
diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml
index 8283a7c8c..1bc56c1d5 100644
--- a/android/app/src/main/AndroidManifestBase.xml
+++ b/android/app/src/main/AndroidManifestBase.xml
@@ -103,6 +103,9 @@
+
+
+
diff --git a/assets/dogecoin_electrum_server_list.yml b/assets/dogecoin_electrum_server_list.yml
new file mode 100644
index 000000000..087b0af2b
--- /dev/null
+++ b/assets/dogecoin_electrum_server_list.yml
@@ -0,0 +1,12 @@
+-
+ uri: dogecoin.stackwallet.com:50022
+ is_default: true
+ useSSL: true
+ isEnabledForAutoSwitching: true
+-
+ uri: doge.aftrek.org:50002
+ useSSL: true
+ isEnabledForAutoSwitching: true
+-
+ uri: electrum1.cipig.net:20060
+ useSSL: true
\ No newline at end of file
diff --git a/cakewallet.bat b/cakewallet.bat
index 1904c5710..b9da8762f 100644
--- a/cakewallet.bat
+++ b/cakewallet.bat
@@ -1,5 +1,5 @@
@echo off
-set cw_win_app_config=--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron
+set cw_win_app_config=--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --dogecoin
set cw_root=%cd%
set cw_archive_name=Cake Wallet.zip
set cw_archive_path=%cw_root%\%cw_archive_name%
diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 73911469f..b92f4c872 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -130,6 +130,8 @@ abstract class ElectrumWalletBase
as Bip32Slip10Secp256k1;
case CryptoCurrency.bch:
return bitcoinCashHDWallet(seedBytes);
+ case CryptoCurrency.doge:
+ return dogecoinHDWallet(seedBytes);
default:
throw Exception("Unsupported currency");
}
@@ -141,6 +143,9 @@ abstract class ElectrumWalletBase
static Bip32Slip10Secp256k1 bitcoinCashHDWallet(Uint8List seedBytes) =>
Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/145'/0'") as Bip32Slip10Secp256k1;
+ static Bip32Slip10Secp256k1 dogecoinHDWallet(Uint8List seedBytes) =>
+ Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/3'/0'") as Bip32Slip10Secp256k1;
+
static int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
inputsCount * 68 + outputsCounts * 34 + 10;
@@ -629,9 +634,9 @@ abstract class ElectrumWalletBase
}
}
- int get _dustAmount => 546;
+ int get networkDustAmount => 546;
- bool _isBelowDust(int amount) => amount <= _dustAmount && network != BitcoinNetwork.testnet;
+ bool _isBelowDust(int amount) => amount <= networkDustAmount && network != BitcoinNetwork.testnet;
UtxoDetails _createUTXOS({
required bool sendAll,
@@ -1685,7 +1690,7 @@ abstract class ElectrumWalletBase
var currentFee = allInputsAmount - totalOutAmount;
int remainingFee = (newFee - currentFee > 0) ? newFee - currentFee : newFee;
- return totalBalance - receiverAmount - remainingFee >= _dustAmount;
+ return totalBalance - receiverAmount - remainingFee >= networkDustAmount;
}
Future replaceByFee(String hash, int newFee) async {
@@ -1773,10 +1778,10 @@ abstract class ElectrumWalletBase
if (isChange) {
int outputAmount = output.value.toInt();
- if (outputAmount > _dustAmount) {
- int deduction = (outputAmount - _dustAmount >= remainingFee)
+ if (outputAmount > networkDustAmount) {
+ int deduction = (outputAmount - networkDustAmount >= remainingFee)
? remainingFee
- : outputAmount - _dustAmount;
+ : outputAmount - networkDustAmount;
outputs[i] = BitcoinOutput(
address: output.address, value: BigInt.from(outputAmount - deduction));
remainingFee -= deduction;
@@ -1845,10 +1850,10 @@ abstract class ElectrumWalletBase
final output = outputs[i];
int outputAmount = output.value.toInt();
- if (outputAmount > _dustAmount) {
- int deduction = (outputAmount - _dustAmount >= remainingFee)
+ if (outputAmount > networkDustAmount) {
+ int deduction = (outputAmount - networkDustAmount >= remainingFee)
? remainingFee
- : outputAmount - _dustAmount;
+ : outputAmount - networkDustAmount;
outputs[i] = BitcoinOutput(
address: output.address, value: BigInt.from(outputAmount - deduction));
@@ -2051,6 +2056,9 @@ abstract class ElectrumWalletBase
await Future.wait(LITECOIN_ADDRESS_TYPES
.where((type) => type != SegwitAddresType.mweb)
.map((type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
+ } else if (type == WalletType.dogecoin) {
+ await Future.wait(DOGECOIN_ADDRESS_TYPES.map(
+ (type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
}
transactionHistory.transactions.values.forEach((tx) async {
diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart
index 614a06a3b..a6ab2180d 100644
--- a/cw_bitcoin/lib/electrum_wallet_addresses.dart
+++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart
@@ -3,7 +3,6 @@ import 'dart:io' show Platform;
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:blockchain_utils/blockchain_utils.dart';
import 'package:cw_bitcoin/bitcoin_address_record.dart';
-import 'package:cw_bitcoin/electrum_wallet.dart';
import 'package:cw_core/unspent_coin_type.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_bitcoin/bitcoin_unspent.dart';
@@ -33,6 +32,10 @@ const List BITCOIN_CASH_ADDRESS_TYPES = [
P2pkhAddressType.p2pkh,
];
+const List DOGECOIN_ADDRESS_TYPES = [
+ P2pkhAddressType.p2pkh,
+];
+
abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
ElectrumWalletAddressesBase(
WalletInfo walletInfo, {
@@ -253,6 +256,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
if ((Platform.isAndroid || Platform.isIOS) && !isHardwareWallet) {
await _generateInitialAddresses(type: SegwitAddresType.mweb);
}
+ } else if (walletInfo.type == WalletType.dogecoin) {
+ await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
} else if (walletInfo.type == WalletType.bitcoin) {
await _generateInitialAddresses();
if (!isHardwareWallet) {
@@ -458,7 +463,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
}
}
- void addBitcoinCashAddressTypes() {
+ void addP2PKHAddressTypes() {
final lastP2pkh = _addresses.firstWhere(
(addressRecord) => _isUnusedReceiveAddressByType(addressRecord, P2pkhAddressType.p2pkh));
if (lastP2pkh.address != address) {
@@ -487,7 +492,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
addLitecoinAddressTypes();
break;
case WalletType.bitcoinCash:
- addBitcoinCashAddressTypes();
+ addP2PKHAddressTypes();
+ break;
+ case WalletType.dogecoin:
+ addP2PKHAddressTypes();
break;
default:
break;
diff --git a/cw_bitcoin/lib/pending_bitcoin_transaction.dart b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
index 82bcbd79e..0712a35f8 100644
--- a/cw_bitcoin/lib/pending_bitcoin_transaction.dart
+++ b/cw_bitcoin/lib/pending_bitcoin_transaction.dart
@@ -81,12 +81,15 @@ class PendingBitcoinTransaction with PendingTransaction {
return "LTC";
case WalletType.bitcoinCash:
return "BCH";
+ case WalletType.dogecoin:
+ return "DOGE";
default:
return type.name;
}
}
+
@override
String get feeFormattedValue => bitcoinAmountToString(amount: fee);
@@ -104,8 +107,7 @@ class PendingBitcoinTransaction with PendingTransaction {
return PendingChange(
changeAddressOverride!, BtcUtils.fromSatoshi(change.amount));
}
- return PendingChange(
- change.scriptPubKey.toAddress(), BtcUtils.fromSatoshi(change.amount));
+ return PendingChange(change.scriptPubKey.toAddress(network: network), BtcUtils.fromSatoshi(change.amount));
} catch (_) {
return null;
}
diff --git a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart
index d55914dcd..527774049 100644
--- a/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart
+++ b/cw_bitcoin_cash/lib/src/bitcoin_cash_wallet.dart
@@ -142,6 +142,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
addr.address,
index: addr.index,
isHidden: addr.isHidden,
+ name: addr.name,
type: P2pkhAddressType.p2pkh,
network: BitcoinCashNetwork.mainnet,
);
@@ -150,6 +151,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
AddressUtils.getCashAddrFormat(addr.address),
index: addr.index,
isHidden: addr.isHidden,
+ name: addr.name,
type: P2pkhAddressType.p2pkh,
network: BitcoinCashNetwork.mainnet,
);
diff --git a/cw_core/lib/amount_converter.dart b/cw_core/lib/amount_converter.dart
index e01c3834a..8a095dffa 100644
--- a/cw_core/lib/amount_converter.dart
+++ b/cw_core/lib/amount_converter.dart
@@ -30,6 +30,7 @@ class AmountConverter {
case CryptoCurrency.bch:
case CryptoCurrency.ltc:
case CryptoCurrency.dcr:
+ case CryptoCurrency.doge:
return _bitcoinAmountToString(amount);
case CryptoCurrency.xhv:
case CryptoCurrency.xag:
diff --git a/cw_core/lib/currency_for_wallet_type.dart b/cw_core/lib/currency_for_wallet_type.dart
index 0f913cb79..495731aa9 100644
--- a/cw_core/lib/currency_for_wallet_type.dart
+++ b/cw_core/lib/currency_for_wallet_type.dart
@@ -34,6 +34,8 @@ CryptoCurrency currencyForWalletType(WalletType type, {bool? isTestnet}) {
return CryptoCurrency.zano;
case WalletType.decred:
return CryptoCurrency.dcr;
+ case WalletType.dogecoin:
+ return CryptoCurrency.doge;
case WalletType.none:
throw Exception(
'Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType');
diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart
index ff94001f2..7f691f955 100644
--- a/cw_core/lib/node.dart
+++ b/cw_core/lib/node.dart
@@ -100,6 +100,7 @@ class Node extends HiveObject with Keyable {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
return createUriFromElectrumAddress(uriRaw, path!);
case WalletType.nano:
case WalletType.banano:
@@ -170,6 +171,7 @@ class Node extends HiveObject with Keyable {
case WalletType.polygon:
case WalletType.solana:
case WalletType.tron:
+ case WalletType.dogecoin:
return requestElectrumServer();
case WalletType.zano:
return requestZanoNode();
diff --git a/cw_core/lib/wallet_type.dart b/cw_core/lib/wallet_type.dart
index 40a2b31d5..3f4fa37fa 100644
--- a/cw_core/lib/wallet_type.dart
+++ b/cw_core/lib/wallet_type.dart
@@ -18,6 +18,7 @@ const walletTypes = [
WalletType.tron,
WalletType.zano,
WalletType.decred,
+ WalletType.dogecoin,
];
@HiveType(typeId: WALLET_TYPE_TYPE_ID)
@@ -65,7 +66,10 @@ enum WalletType {
zano,
@HiveField(14)
- decred
+ decred,
+
+ @HiveField(15)
+ dogecoin
}
int serializeToInt(WalletType type) {
@@ -98,6 +102,8 @@ int serializeToInt(WalletType type) {
return 12;
case WalletType.decred:
return 13;
+ case WalletType.dogecoin:
+ return 14;
case WalletType.none:
return -1;
}
@@ -133,6 +139,8 @@ WalletType deserializeFromInt(int raw) {
return WalletType.zano;
case 13:
return WalletType.decred;
+ case 14:
+ return WalletType.dogecoin;
default:
throw Exception(
'Unexpected token: $raw for WalletType deserializeFromInt');
@@ -169,6 +177,8 @@ String walletTypeToString(WalletType type) {
return 'Zano';
case WalletType.decred:
return 'Decred';
+ case WalletType.dogecoin:
+ return 'Dogecoin';
case WalletType.none:
return '';
}
@@ -204,6 +214,8 @@ String walletTypeToDisplayName(WalletType type) {
return 'Zano (ZANO)';
case WalletType.decred:
return 'Decred (DCR)';
+ case WalletType.dogecoin:
+ return 'Dogecoin (DOGE)';
case WalletType.none:
return '';
}
@@ -242,6 +254,8 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type, {bool isTestnet = fal
return CryptoCurrency.zano;
case WalletType.decred:
return CryptoCurrency.dcr;
+ case WalletType.dogecoin:
+ return CryptoCurrency.doge;
case WalletType.none:
throw Exception(
'Unexpected wallet type: ${type.toString()} for CryptoCurrency walletTypeToCryptoCurrency');
@@ -278,6 +292,8 @@ WalletType? cryptoCurrencyToWalletType(CryptoCurrency type) {
return WalletType.zano;
case CryptoCurrency.dcr:
return WalletType.decred;
+ case CryptoCurrency.doge:
+ return WalletType.dogecoin;
default:
return null;
}
diff --git a/cw_dogecoin/.gitignore b/cw_dogecoin/.gitignore
new file mode 100644
index 000000000..eb6c05cd3
--- /dev/null
+++ b/cw_dogecoin/.gitignore
@@ -0,0 +1,31 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+build/
diff --git a/cw_dogecoin/.metadata b/cw_dogecoin/.metadata
new file mode 100644
index 000000000..69723fa27
--- /dev/null
+++ b/cw_dogecoin/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: "c23637390482d4cf9598c3ce3f2be31aa7332daf"
+ channel: "stable"
+
+project_type: package
diff --git a/cw_dogecoin/CHANGELOG.md b/cw_dogecoin/CHANGELOG.md
new file mode 100644
index 000000000..41cc7d819
--- /dev/null
+++ b/cw_dogecoin/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.0.1
+
+* TODO: Describe initial release.
diff --git a/cw_dogecoin/LICENSE b/cw_dogecoin/LICENSE
new file mode 100644
index 000000000..ba75c69f7
--- /dev/null
+++ b/cw_dogecoin/LICENSE
@@ -0,0 +1 @@
+TODO: Add your license here.
diff --git a/cw_dogecoin/README.md b/cw_dogecoin/README.md
new file mode 100644
index 000000000..4a260d8d2
--- /dev/null
+++ b/cw_dogecoin/README.md
@@ -0,0 +1,39 @@
+
+
+TODO: Put a short description of the package here that helps potential users
+know whether this package might be useful for them.
+
+## Features
+
+TODO: List what your package can do. Maybe include images, gifs, or videos.
+
+## Getting started
+
+TODO: List prerequisites and provide or point to information on how to
+start using the package.
+
+## Usage
+
+TODO: Include short and useful examples for package users. Add longer examples
+to `/example` folder.
+
+```dart
+const like = 'sample';
+```
+
+## Additional information
+
+TODO: Tell users more about the package: where to find more information, how to
+contribute to the package, how to file issues, what response they can expect
+from the package authors, and more.
diff --git a/cw_dogecoin/analysis_options.yaml b/cw_dogecoin/analysis_options.yaml
new file mode 100644
index 000000000..a5744c1cf
--- /dev/null
+++ b/cw_dogecoin/analysis_options.yaml
@@ -0,0 +1,4 @@
+include: package:flutter_lints/flutter.yaml
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/cw_dogecoin/lib/cw_dogecoin.dart b/cw_dogecoin/lib/cw_dogecoin.dart
new file mode 100644
index 000000000..3884dae59
--- /dev/null
+++ b/cw_dogecoin/lib/cw_dogecoin.dart
@@ -0,0 +1,6 @@
+export 'src/dogecoin_wallet.dart';
+export 'src/dogecoin_wallet_addresses.dart';
+export 'src/dogecoin_wallet_creation_credentials.dart';
+export 'src/dogecoin_wallet_service.dart';
+export 'src/dogecoin_transaction_priority.dart';
+
diff --git a/cw_dogecoin/lib/src/dogecoin_transaction_priority.dart b/cw_dogecoin/lib/src/dogecoin_transaction_priority.dart
new file mode 100644
index 000000000..b692cc570
--- /dev/null
+++ b/cw_dogecoin/lib/src/dogecoin_transaction_priority.dart
@@ -0,0 +1,52 @@
+import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
+
+class DogecoinTransactionPriority extends BitcoinTransactionPriority {
+ const DogecoinTransactionPriority({required String title, required int raw})
+ : super(title: title, raw: raw);
+
+ static const List all = [fast, medium, slow];
+ static const DogecoinTransactionPriority slow =
+ DogecoinTransactionPriority(title: 'Slow', raw: 0);
+ static const DogecoinTransactionPriority medium =
+ DogecoinTransactionPriority(title: 'Medium', raw: 1);
+ static const DogecoinTransactionPriority fast =
+ DogecoinTransactionPriority(title: 'Fast', raw: 2);
+
+ static DogecoinTransactionPriority deserialize({required int raw}) {
+ switch (raw) {
+ case 0:
+ return slow;
+ case 1:
+ return medium;
+ case 2:
+ return fast;
+ default:
+ throw Exception('Unexpected token: $raw for DogecoinTransactionPriority deserialize');
+ }
+ }
+
+ @override
+ String get units => 'koinu';
+
+ @override
+ String toString() {
+ var label = '';
+
+ switch (this) {
+ case DogecoinTransactionPriority.slow:
+ label = 'Slow'; // S.current.transaction_priority_slow;
+ break;
+ case DogecoinTransactionPriority.medium:
+ label = 'Medium'; // S.current.transaction_priority_medium;
+ break;
+ case DogecoinTransactionPriority.fast:
+ label = 'Fast'; // S.current.transaction_priority_fast;
+ break;
+ default:
+ break;
+ }
+
+ return label;
+ }
+}
+
diff --git a/cw_dogecoin/lib/src/dogecoin_wallet.dart b/cw_dogecoin/lib/src/dogecoin_wallet.dart
new file mode 100644
index 000000000..bd7fe0699
--- /dev/null
+++ b/cw_dogecoin/lib/src/dogecoin_wallet.dart
@@ -0,0 +1,164 @@
+import 'package:bitcoin_base/bitcoin_base.dart';
+import 'package:blockchain_utils/blockchain_utils.dart';
+import 'package:cw_bitcoin/bitcoin_address_record.dart';
+import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
+import 'package:cw_bitcoin/electrum_balance.dart';
+import 'package:cw_bitcoin/electrum_wallet.dart';
+import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
+import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/encryption_file_utils.dart';
+import 'package:cw_core/unspent_coins_info.dart';
+import 'package:cw_core/wallet_info.dart';
+import 'package:cw_core/wallet_keys_file.dart';
+import 'package:flutter/foundation.dart';
+import 'package:hive/hive.dart';
+import 'package:mobx/mobx.dart';
+
+import 'dogecoin_wallet_addresses.dart';
+
+part 'dogecoin_wallet.g.dart';
+
+class DogeCoinWallet = DogeCoinWalletBase with _$DogeCoinWallet;
+
+abstract class DogeCoinWalletBase extends ElectrumWallet with Store {
+ DogeCoinWalletBase({
+ required String mnemonic,
+ required String password,
+ required WalletInfo walletInfo,
+ required Box unspentCoinsInfo,
+ required Uint8List seedBytes,
+ required EncryptionFileUtils encryptionFileUtils,
+ String? passphrase,
+ BitcoinAddressType? addressPageType,
+ List? initialAddresses,
+ ElectrumBalance? initialBalance,
+ Map? initialRegularAddressIndex,
+ Map? initialChangeAddressIndex,
+ }) : super(
+ mnemonic: mnemonic,
+ password: password,
+ walletInfo: walletInfo,
+ unspentCoinsInfo: unspentCoinsInfo,
+ network: DogecoinNetwork.mainnet,
+ initialAddresses: initialAddresses,
+ initialBalance: initialBalance,
+ seedBytes: seedBytes,
+ currency: CryptoCurrency.doge,
+ encryptionFileUtils: encryptionFileUtils,
+ passphrase: passphrase) {
+ walletAddresses = DogeCoinWalletAddresses(
+ walletInfo,
+ initialAddresses: initialAddresses,
+ initialRegularAddressIndex: initialRegularAddressIndex,
+ initialChangeAddressIndex: initialChangeAddressIndex,
+ mainHd: hd,
+ sideHd: accountHD.childKey(Bip32KeyIndex(1)),
+ network: network,
+ initialAddressPageType: addressPageType,
+ isHardwareWallet: walletInfo.isHardwareWallet,
+ );
+ autorun((_) {
+ this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
+ });
+ }
+
+ @override
+ int get networkDustAmount => 100000000; // 1 DOGE = 1e8 koinu
+
+ static Future create(
+ {required String mnemonic,
+ required String password,
+ required WalletInfo walletInfo,
+ required Box unspentCoinsInfo,
+ required EncryptionFileUtils encryptionFileUtils,
+ String? passphrase,
+ String? addressPageType,
+ List? initialAddresses,
+ ElectrumBalance? initialBalance,
+ Map? initialRegularAddressIndex,
+ Map? initialChangeAddressIndex}) async {
+ return DogeCoinWallet(
+ mnemonic: mnemonic,
+ password: password,
+ walletInfo: walletInfo,
+ unspentCoinsInfo: unspentCoinsInfo,
+ initialAddresses: initialAddresses,
+ initialBalance: initialBalance,
+ seedBytes: MnemonicBip39.toSeed(mnemonic, passphrase: passphrase),
+ encryptionFileUtils: encryptionFileUtils,
+ initialRegularAddressIndex: initialRegularAddressIndex,
+ initialChangeAddressIndex: initialChangeAddressIndex,
+ addressPageType: P2pkhAddressType.p2pkh,
+ passphrase: passphrase,
+ );
+ }
+
+ static Future open({
+ required String name,
+ required WalletInfo walletInfo,
+ required Box unspentCoinsInfo,
+ required String password,
+ required EncryptionFileUtils encryptionFileUtils,
+ }) async {
+ final hasKeysFile = await WalletKeysFile.hasKeysFile(name, walletInfo.type);
+
+ ElectrumWalletSnapshot? snp = null;
+
+ try {
+ snp = await ElectrumWalletSnapshot.load(
+ encryptionFileUtils,
+ name,
+ walletInfo.type,
+ password,
+ DogecoinNetwork.mainnet,
+ );
+ } catch (e) {
+ if (!hasKeysFile) rethrow;
+ }
+
+ final WalletKeysData keysData;
+ // Migrate wallet from the old scheme to then new .keys file scheme
+ if (!hasKeysFile) {
+ keysData =
+ WalletKeysData(mnemonic: snp!.mnemonic, xPub: snp.xpub, passphrase: snp.passphrase);
+ } else {
+ keysData = await WalletKeysFile.readKeysFile(
+ name,
+ walletInfo.type,
+ password,
+ encryptionFileUtils,
+ );
+ }
+
+ return DogeCoinWallet(
+ mnemonic: keysData.mnemonic!,
+ password: password,
+ walletInfo: walletInfo,
+ unspentCoinsInfo: unspentCoinsInfo,
+ initialAddresses: snp?.addresses,
+ initialBalance: snp?.balance,
+ seedBytes: await MnemonicBip39.toSeed(keysData.mnemonic!, passphrase: keysData.passphrase),
+ encryptionFileUtils: encryptionFileUtils,
+ initialRegularAddressIndex: snp?.regularAddressIndex,
+ initialChangeAddressIndex: snp?.changeAddressIndex,
+ addressPageType: P2pkhAddressType.p2pkh,
+ passphrase: keysData.passphrase,
+ );
+ }
+
+ @override
+ Future signMessage(String message, {String? address = null}) async {
+ int? index;
+ try {
+ index = address != null
+ ? walletAddresses.allAddresses.firstWhere((element) => element.address == address).index
+ : null;
+ } catch (_) {}
+ final HD = index == null ? hd : hd.childKey(Bip32KeyIndex(index));
+ final priv = ECPrivate.fromWif(
+ WifEncoder.encode(HD.privateKey.raw, netVer: network.wifNetVer),
+ netVersion: network.wifNetVer,
+ );
+ return priv.signMessage(StringUtils.encode(message));
+ }
+}
diff --git a/cw_dogecoin/lib/src/dogecoin_wallet_addresses.dart b/cw_dogecoin/lib/src/dogecoin_wallet_addresses.dart
new file mode 100644
index 000000000..75d06c148
--- /dev/null
+++ b/cw_dogecoin/lib/src/dogecoin_wallet_addresses.dart
@@ -0,0 +1,29 @@
+import 'package:bitcoin_base/bitcoin_base.dart';
+import 'package:blockchain_utils/blockchain_utils.dart';
+import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
+import 'package:cw_bitcoin/utils.dart';
+import 'package:cw_core/wallet_info.dart';
+import 'package:mobx/mobx.dart';
+
+part 'dogecoin_wallet_addresses.g.dart';
+
+class DogeCoinWalletAddresses = DogeCoinWalletAddressesBase with _$DogeCoinWalletAddresses;
+
+abstract class DogeCoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
+ DogeCoinWalletAddressesBase(WalletInfo walletInfo, {
+ required super.mainHd,
+ required super.sideHd,
+ required super.network,
+ required super.isHardwareWallet,
+ super.initialAddresses,
+ super.initialRegularAddressIndex,
+ super.initialChangeAddressIndex,
+ super.initialAddressPageType
+ }) : super(walletInfo);
+
+ @override
+ String getAddress({required int index,
+ required Bip32Slip10Secp256k1 hd,
+ BitcoinAddressType? addressType}) =>
+ generateP2PKHAddress(hd: hd, index: index, network: network);
+}
diff --git a/cw_dogecoin/lib/src/dogecoin_wallet_creation_credentials.dart b/cw_dogecoin/lib/src/dogecoin_wallet_creation_credentials.dart
new file mode 100644
index 000000000..3dfe242e2
--- /dev/null
+++ b/cw_dogecoin/lib/src/dogecoin_wallet_creation_credentials.dart
@@ -0,0 +1,38 @@
+import 'package:cw_core/wallet_credentials.dart';
+import 'package:cw_core/wallet_info.dart';
+
+class DogeCoinNewWalletCredentials extends WalletCredentials {
+ DogeCoinNewWalletCredentials({
+ required String name,
+ WalletInfo? walletInfo,
+ String? password,
+ String? passphrase,
+ this.mnemonic,
+ }) : super(
+ name: name,
+ walletInfo: walletInfo,
+ password: password,
+ passphrase: passphrase,
+ );
+ final String? mnemonic;
+}
+
+class DogeCoinRestoreWalletFromSeedCredentials extends WalletCredentials {
+ DogeCoinRestoreWalletFromSeedCredentials({
+ required String name,
+ required String password,
+ required this.mnemonic,
+ WalletInfo? walletInfo,
+ String? passphrase,
+ }) : super(name: name, password: password, walletInfo: walletInfo, passphrase: passphrase);
+
+ final String mnemonic;
+}
+
+class DogeCoinRestoreWalletFromWIFCredentials extends WalletCredentials {
+ DogeCoinRestoreWalletFromWIFCredentials(
+ {required String name, required String password, required this.wif, WalletInfo? walletInfo})
+ : super(name: name, password: password, walletInfo: walletInfo);
+
+ final String wif;
+}
diff --git a/cw_dogecoin/lib/src/dogecoin_wallet_service.dart b/cw_dogecoin/lib/src/dogecoin_wallet_service.dart
new file mode 100644
index 000000000..d0e3b2969
--- /dev/null
+++ b/cw_dogecoin/lib/src/dogecoin_wallet_service.dart
@@ -0,0 +1,151 @@
+import 'dart:io';
+
+import 'package:bip39/bip39.dart';
+import 'package:collection/collection.dart';
+import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
+import 'package:cw_core/encryption_file_utils.dart';
+import 'package:cw_core/pathForWallet.dart';
+import 'package:cw_core/unspent_coins_info.dart';
+import 'package:cw_core/wallet_base.dart';
+import 'package:cw_core/wallet_info.dart';
+import 'package:cw_core/wallet_service.dart';
+import 'package:cw_core/wallet_type.dart';
+import 'package:cw_dogecoin/cw_dogecoin.dart';
+import 'package:hive/hive.dart';
+
+class DogeCoinWalletService extends WalletService<
+ DogeCoinNewWalletCredentials,
+ DogeCoinRestoreWalletFromSeedCredentials,
+ DogeCoinRestoreWalletFromWIFCredentials,
+ DogeCoinNewWalletCredentials> {
+ DogeCoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.isDirect);
+
+ final Box walletInfoSource;
+ final Box unspentCoinsInfoSource;
+ final bool isDirect;
+
+ @override
+ WalletType getType() => WalletType.dogecoin;
+
+ @override
+ Future isWalletExit(String name) async =>
+ File(await pathForWallet(name: name, type: getType())).existsSync();
+
+ @override
+ Future create(credentials, {bool? isTestnet}) async {
+ final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
+
+ final wallet = await DogeCoinWalletBase.create(
+ mnemonic: credentials.mnemonic ?? MnemonicBip39.generate(strength: strength),
+ password: credentials.password!,
+ walletInfo: credentials.walletInfo!,
+ unspentCoinsInfo: unspentCoinsInfoSource,
+ encryptionFileUtils: encryptionFileUtilsFor(isDirect),
+ passphrase: credentials.passphrase,
+ );
+ await wallet.save();
+ await wallet.init();
+
+ return wallet;
+ }
+
+ @override
+ Future openWallet(String name, String password) async {
+ final walletInfo = walletInfoSource.values
+ .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
+
+ try {
+ final wallet = await DogeCoinWalletBase.open(
+ password: password,
+ name: name,
+ walletInfo: walletInfo,
+ unspentCoinsInfo: unspentCoinsInfoSource,
+ encryptionFileUtils: encryptionFileUtilsFor(isDirect),
+ );
+ await wallet.init();
+ saveBackup(name);
+ return wallet;
+ } catch (_) {
+ await restoreWalletFilesFromBackup(name);
+ final wallet = await DogeCoinWalletBase.open(
+ password: password,
+ name: name,
+ walletInfo: walletInfo,
+ unspentCoinsInfo: unspentCoinsInfoSource,
+ encryptionFileUtils: encryptionFileUtilsFor(isDirect),
+ );
+ await wallet.init();
+ return wallet;
+ }
+ }
+
+ @override
+ Future remove(String wallet) async {
+ File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
+ final walletInfo = walletInfoSource.values
+ .firstWhereOrNull((info) => info.id == WalletBase.idFor(wallet, getType()))!;
+ await walletInfoSource.delete(walletInfo.key);
+
+ final unspentCoinsToDelete = unspentCoinsInfoSource.values
+ .where((unspentCoin) => unspentCoin.walletId == walletInfo.id)
+ .toList();
+
+ final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
+
+ if (keysToDelete.isNotEmpty) {
+ await unspentCoinsInfoSource.deleteAll(keysToDelete);
+ }
+ }
+
+ @override
+ Future rename(String currentName, String password, String newName) async {
+ final currentWalletInfo = walletInfoSource.values
+ .firstWhereOrNull((info) => info.id == WalletBase.idFor(currentName, getType()))!;
+ final currentWallet = await DogeCoinWalletBase.open(
+ password: password,
+ name: currentName,
+ walletInfo: currentWalletInfo,
+ unspentCoinsInfo: unspentCoinsInfoSource,
+ encryptionFileUtils: encryptionFileUtilsFor(isDirect));
+
+ await currentWallet.renameWalletFiles(newName);
+ await saveBackup(newName);
+
+ final newWalletInfo = currentWalletInfo;
+ newWalletInfo.id = WalletBase.idFor(newName, getType());
+ newWalletInfo.name = newName;
+
+ await walletInfoSource.put(currentWalletInfo.key, newWalletInfo);
+ }
+
+ @override
+ Future restoreFromHardwareWallet(DogeCoinNewWalletCredentials credentials) {
+ throw UnimplementedError(
+ "Restoring a Bitcoin Cash wallet from a hardware wallet is not yet supported!");
+ }
+
+ @override
+ Future restoreFromKeys(credentials, {bool? isTestnet}) {
+ // TODO: implement restoreFromKeys
+ throw UnimplementedError('restoreFromKeys() is not implemented');
+ }
+
+ @override
+ Future restoreFromSeed(DogeCoinRestoreWalletFromSeedCredentials credentials,
+ {bool? isTestnet}) async {
+ if (!validateMnemonic(credentials.mnemonic)) {
+ throw Exception('Invalid mnemonic: ${credentials.mnemonic}');
+ }
+
+ final wallet = await DogeCoinWalletBase.create(
+ password: credentials.password!,
+ mnemonic: credentials.mnemonic,
+ walletInfo: credentials.walletInfo!,
+ unspentCoinsInfo: unspentCoinsInfoSource,
+ encryptionFileUtils: encryptionFileUtilsFor(isDirect),
+ passphrase: credentials.passphrase);
+ await wallet.save();
+ await wallet.init();
+ return wallet;
+ }
+}
diff --git a/cw_dogecoin/pubspec.yaml b/cw_dogecoin/pubspec.yaml
new file mode 100644
index 000000000..599a76429
--- /dev/null
+++ b/cw_dogecoin/pubspec.yaml
@@ -0,0 +1,81 @@
+name: cw_dogecoin
+description: "A new Flutter package project."
+version: 0.0.1
+publish_to: none
+author: Cake Wallet
+homepage: https://cakewallet.com
+
+environment:
+ sdk: '>=2.19.0 <3.0.0'
+ flutter: ">=1.20.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+ bip39: ^1.0.6
+ bip32: ^2.0.0
+ path_provider: ^2.0.11
+ mobx: ^2.0.7+4
+ flutter_mobx: ^2.0.6+1
+ cw_core:
+ path: ../cw_core
+ cw_bitcoin:
+ path: ../cw_bitcoin
+
+ blockchain_utils:
+ git:
+ url: https://github.com/cake-tech/blockchain_utils
+ ref: cake-update-v2
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+ build_runner: ^2.4.15
+ mobx_codegen: ^2.0.7
+ hive_generator: ^2.0.1
+
+dependency_overrides:
+ watcher: ^1.1.0
+ bitcoin_base:
+ git:
+ url: https://github.com/cake-tech/bitcoin_base
+ ref: cake-update-v10
+
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+ uses-material-design: true
+
+ # To add assets to your package, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+ #
+ # For details regarding assets in packages, see
+ # https://flutter.dev/to/asset-from-package
+ #
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/to/resolution-aware-images
+
+ # To add custom fonts to your package, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts in packages, see
+ # https://flutter.dev/to/font-from-package
diff --git a/cw_dogecoin/test/cw_dogecoin_test.dart b/cw_dogecoin/test/cw_dogecoin_test.dart
new file mode 100644
index 000000000..1c5f77ec9
--- /dev/null
+++ b/cw_dogecoin/test/cw_dogecoin_test.dart
@@ -0,0 +1,8 @@
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:cw_dogecoin/cw_dogecoin.dart';
+
+void main() {
+ test('adds one to input values', () {
+ });
+}
diff --git a/ios/Runner/InfoBase.plist b/ios/Runner/InfoBase.plist
index 40868aa9f..5eefa786c 100644
--- a/ios/Runner/InfoBase.plist
+++ b/ios/Runner/InfoBase.plist
@@ -282,6 +282,25 @@
decred-wallet
+
+ CFBundleTypeRole
+ Viewer
+ CFBundleURLName
+ dogecoin
+ CFBundleURLSchemes
+
+ dash
+
+
+
+ CFBundleTypeRole
+ Viewer
+ CFBundleURLName
+ dogecoin-wallet
+ CFBundleURLSchemes
+
+ dogecoin-wallet
+
CFBundleVersion
$(CURRENT_PROJECT_VERSION)
diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart
index bd6e03002..c0abaa2be 100644
--- a/lib/bitcoin/cw_bitcoin.dart
+++ b/lib/bitcoin/cw_bitcoin.dart
@@ -184,6 +184,18 @@ class CWBitcoin extends Bitcoin {
return estimatedTx.amount;
}
+
+ if (wallet.type == WalletType.dogecoin) {
+ final dogeAddr =
+ sk.getPublic().toP2pkhAddress();
+ final estimatedTx = await electrumWallet.estimateSendAllTx(
+ [BitcoinOutput(address: dogeAddr, value: BigInt.zero)],
+ getFeeRate(wallet, priority as BitcoinTransactionPriority),
+ coinTypeToSpendFrom: coinTypeToSpendFrom,
+ );
+ return estimatedTx.amount;
+ }
+
final p2shAddr = sk.getPublic().toP2pkhInP2sh();
final estimatedTx = await electrumWallet.estimateSendAllTx(
[BitcoinOutput(address: p2shAddr, value: BigInt.zero)],
diff --git a/lib/core/seed_validator.dart b/lib/core/seed_validator.dart
index 344b5391d..2e35e7f5a 100644
--- a/lib/core/seed_validator.dart
+++ b/lib/core/seed_validator.dart
@@ -29,6 +29,8 @@ class SeedValidator extends Validator {
return getBitcoinWordList(language);
case WalletType.litecoin:
return getBitcoinWordList(language);
+ case WalletType.dogecoin:
+ return getBitcoinWordList(language);
case WalletType.monero:
return monero!.getMoneroWordList(language);
case WalletType.ethereum:
diff --git a/lib/core/wallet_creation_service.dart b/lib/core/wallet_creation_service.dart
index b44e56a98..2cf7a7c63 100644
--- a/lib/core/wallet_creation_service.dart
+++ b/lib/core/wallet_creation_service.dart
@@ -82,6 +82,7 @@ class WalletCreationService {
case WalletType.polygon:
case WalletType.solana:
case WalletType.tron:
+ case WalletType.dogecoin:
return true;
case WalletType.monero:
case WalletType.wownero:
diff --git a/lib/di.dart b/lib/di.dart
index cec6331d6..f913478c5 100644
--- a/lib/di.dart
+++ b/lib/di.dart
@@ -274,6 +274,7 @@ import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'buy/kryptonim/kryptonim.dart';
import 'buy/meld/meld_buy_provider.dart';
+import 'dogecoin/dogecoin.dart';
import 'src/screens/buy/buy_sell_page.dart';
import 'package:cake_wallet/view_model/dev/background_sync_logs_view_model.dart';
import 'package:cake_wallet/src/screens/dev/background_sync_logs_page.dart';
@@ -1147,6 +1148,9 @@ Future setup({
case WalletType.bitcoinCash:
return bitcoinCash!.createBitcoinCashWalletService(_walletInfoSource,
_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
+ case WalletType.dogecoin:
+ return dogecoin!.createDogeCoinWalletService(_walletInfoSource,
+ _unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
case WalletType.nano:
case WalletType.banano:
return nano!.createNanoWalletService(_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
diff --git a/lib/dogecoin/cw_dogecoin.dart b/lib/dogecoin/cw_dogecoin.dart
new file mode 100644
index 000000000..e78119306
--- /dev/null
+++ b/lib/dogecoin/cw_dogecoin.dart
@@ -0,0 +1,48 @@
+part of 'dogecoin.dart';
+
+
+class CWDogeCoin extends DogeCoin {
+
+ @override
+ WalletService createDogeCoinWalletService(
+ Box walletInfoSource, Box unspentCoinSource, bool isDirect) {
+ return DogeCoinWalletService(walletInfoSource, unspentCoinSource, isDirect);
+ }
+
+ @override
+ WalletCredentials createDogeCoinNewWalletCredentials({
+ required String name,
+ WalletInfo? walletInfo,
+ String? password,
+ String? passphrase,
+ String? mnemonic,
+ }) =>
+ DogeCoinNewWalletCredentials(
+ name: name,
+ walletInfo: walletInfo,
+ password: password,
+ passphrase: passphrase,
+ mnemonic: mnemonic,
+ );
+
+ @override
+ WalletCredentials createDogeCoinRestoreWalletFromSeedCredentials({
+ required String name,
+ required String mnemonic,
+ required String password,
+ String? passphrase,
+ }) =>
+ DogeCoinRestoreWalletFromSeedCredentials(
+ name: name, mnemonic: mnemonic, password: password, passphrase: passphrase);
+
+ @override
+ TransactionPriority deserializeDogeCoinTransactionPriority(int raw) =>
+ DogecoinTransactionPriority.deserialize(raw: raw);
+
+ @override
+ TransactionPriority getDefaultTransactionPriority() => DogecoinTransactionPriority.medium;
+ @override
+ List getTransactionPriorities() => DogecoinTransactionPriority.all;
+ @override
+ TransactionPriority getDogeCoinTransactionPrioritySlow() => DogecoinTransactionPriority.slow;
+}
diff --git a/lib/dogecoin/dogecoin.dart b/lib/dogecoin/dogecoin.dart
new file mode 100644
index 000000000..252333628
--- /dev/null
+++ b/lib/dogecoin/dogecoin.dart
@@ -0,0 +1,32 @@
+import 'package:cw_core/transaction_priority.dart';
+import 'package:cw_core/unspent_coins_info.dart';
+import 'package:cw_core/wallet_credentials.dart';
+import 'package:cw_core/wallet_info.dart';
+import 'package:cw_core/wallet_service.dart';
+import 'package:hive/hive.dart';
+
+import 'package:cw_dogecoin/cw_dogecoin.dart';
+
+part 'cw_dogecoin.dart';
+
+DogeCoin? dogecoin = CWDogeCoin();
+
+abstract class DogeCoin {
+
+ WalletService createDogeCoinWalletService(
+ Box walletInfoSource, Box unspentCoinSource, bool isDirect);
+
+ WalletCredentials createDogeCoinNewWalletCredentials(
+ {required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic});
+
+ WalletCredentials createDogeCoinRestoreWalletFromSeedCredentials(
+ {required String name, required String mnemonic, required String password, String? passphrase});
+
+ TransactionPriority deserializeDogeCoinTransactionPriority(int raw);
+
+ TransactionPriority getDefaultTransactionPriority();
+
+ List getTransactionPriorities();
+
+ TransactionPriority getDogeCoinTransactionPrioritySlow();
+}
diff --git a/lib/entities/default_settings_migration.dart b/lib/entities/default_settings_migration.dart
index 35634c391..0d573195f 100644
--- a/lib/entities/default_settings_migration.dart
+++ b/lib/entities/default_settings_migration.dart
@@ -46,6 +46,7 @@ const wowneroDefaultNodeUri = 'node3.monerodevs.org:34568';
const zanoDefaultNodeUri = 'zano.cakewallet.com:11211';
const moneroWorldNodeUri = '.moneroworld.com';
const decredDefaultUri = "default-spv-nodes";
+const dogecoinDefaultNodeUri = 'dogecoin.stackwallet.com:50022';
Future defaultSettingsMigration(
{required int version,
@@ -514,6 +515,15 @@ Future defaultSettingsMigration(
case 50:
migrateExistingNodesToUseAutoSwitching(nodes: nodes, powNodes: powNodes);
break;
+ case 51:
+ await addWalletNodeList(nodes: nodes, type: WalletType.dogecoin);
+ await _changeDefaultNode(
+ nodes: nodes,
+ sharedPreferences: sharedPreferences,
+ type: WalletType.dogecoin,
+ currentNodePreferenceKey: PreferencesKey.currentDogecoinNodeIdKey,
+ );
+ break;
default:
break;
}
@@ -620,6 +630,8 @@ String _getDefaultNodeUri(WalletType type) {
return zanoDefaultNodeUri;
case WalletType.decred:
return decredDefaultUri;
+ case WalletType.dogecoin:
+ return dogecoinDefaultNodeUri;
case WalletType.banano:
case WalletType.none:
return '';
@@ -1050,6 +1062,8 @@ Future checkCurrentNodes(
final currentDecredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey);
final currentBitcoinCashNodeId =
sharedPreferences.getInt(PreferencesKey.currentBitcoinCashNodeIdKey);
+ final currentDogecoinNodeId =
+ sharedPreferences.getInt(PreferencesKey.currentDogecoinNodeIdKey);
final currentSolanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
final currentTronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey);
final currentWowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey);
@@ -1074,6 +1088,8 @@ Future checkCurrentNodes(
powNodeSource.values.firstWhereOrNull((node) => node.key == currentNanoPowNodeId);
final currentBitcoinCashNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentBitcoinCashNodeId);
+ final currentDogecoinNodeServer =
+ nodeSource.values.firstWhereOrNull((node) => node.key == currentDogecoinNodeId);
final currentSolanaNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentSolanaNodeId);
final currentTronNodeServer =
@@ -1143,6 +1159,12 @@ Future checkCurrentNodes(
await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
}
+ if (currentDogecoinNodeServer == null) {
+ final node = Node(uri: dogecoinDefaultNodeUri, type: WalletType.dogecoin, useSSL: true);
+ await nodeSource.add(node);
+ await sharedPreferences.setInt(PreferencesKey.currentDogecoinNodeIdKey, node.key as int);
+ }
+
if (currentPolygonNodeServer == null) {
final node = Node(uri: polygonDefaultNodeUri, type: WalletType.polygon);
await nodeSource.add(node);
diff --git a/lib/entities/node_list.dart b/lib/entities/node_list.dart
index bb489e715..40843becf 100644
--- a/lib/entities/node_list.dart
+++ b/lib/entities/node_list.dart
@@ -46,6 +46,9 @@ Future> loadDefaultNodes(WalletType type) async {
case WalletType.decred:
path = 'assets/decred_node_list.yml';
break;
+ case WalletType.dogecoin:
+ path = 'assets/dogecoin_electrum_server_list.yml';
+ break;
case WalletType.banano:
case WalletType.none:
path = '';
@@ -96,6 +99,7 @@ Future resetToDefault(Box nodeSource) async {
final tronNodes = await loadDefaultNodes(WalletType.tron);
final decredNodes = await loadDefaultNodes(WalletType.decred);
final zanoNodes = await loadDefaultNodes(WalletType.zano);
+ final dogecoinElectrumServerList = await loadDefaultNodes(WalletType.dogecoin);
final nodes = moneroNodes +
bitcoinElectrumServerList +
@@ -108,7 +112,8 @@ Future resetToDefault(Box nodeSource) async {
solanaNodes +
tronNodes +
zanoNodes +
- decredNodes;
+ decredNodes +
+ dogecoinElectrumServerList;
await nodeSource.clear();
await nodeSource.addAll(nodes);
diff --git a/lib/entities/preferences_key.dart b/lib/entities/preferences_key.dart
index d0e6a56fc..65e4a67d7 100644
--- a/lib/entities/preferences_key.dart
+++ b/lib/entities/preferences_key.dart
@@ -11,6 +11,7 @@ class PreferencesKey {
static const currentNanoNodeIdKey = 'current_node_id_nano';
static const currentNanoPowNodeIdKey = 'current_node_id_nano_pow';
static const currentDecredNodeIdKey = 'current_node_id_decred';
+ static const currentDogecoinNodeIdKey = 'current_node_id_doge';
static const currentBananoNodeIdKey = 'current_node_id_banano';
static const currentBananoPowNodeIdKey = 'current_node_id_banano_pow';
static const currentFiatCurrencyKey = 'current_fiat_currency';
diff --git a/lib/entities/priority_for_wallet_type.dart b/lib/entities/priority_for_wallet_type.dart
index 5307250d5..c85e98597 100644
--- a/lib/entities/priority_for_wallet_type.dart
+++ b/lib/entities/priority_for_wallet_type.dart
@@ -1,5 +1,6 @@
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
+import 'package:cake_wallet/dogecoin/dogecoin.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/polygon/polygon.dart';
@@ -23,6 +24,8 @@ List priorityForWalletType(WalletType type) {
return ethereum!.getTransactionPriorities();
case WalletType.bitcoinCash:
return bitcoinCash!.getTransactionPriorities();
+ case WalletType.dogecoin:
+ return dogecoin!.getTransactionPriorities();
case WalletType.polygon:
return polygon!.getTransactionPriorities();
// no such thing for nano/banano/solana/tron:
diff --git a/lib/main.dart b/lib/main.dart
index 0b9f1b323..f37c69705 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -250,7 +250,7 @@ Future initializeAppConfigs({bool loadWallet = true}) async {
payjoinSessionSource: payjoinSessionSource,
anonpayInvoiceInfo: anonpayInvoiceInfo,
havenSeedStore: havenSeedStore,
- initialMigrationVersion: 50,
+ initialMigrationVersion: 51,
);
}
diff --git a/lib/reactions/on_current_wallet_change.dart b/lib/reactions/on_current_wallet_change.dart
index 7b7199b14..53a12b10c 100644
--- a/lib/reactions/on_current_wallet_change.dart
+++ b/lib/reactions/on_current_wallet_change.dart
@@ -76,6 +76,7 @@ void startCurrentWalletChangeReaction(
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.litecoin ||
wallet.type == WalletType.bitcoinCash ||
+ wallet.type == WalletType.dogecoin ||
wallet.type == WalletType.decred) {
_setAutoGenerateSubaddressStatus(wallet, settingsStore);
}
diff --git a/lib/reactions/wallet_utils.dart b/lib/reactions/wallet_utils.dart
index d560f01bb..dde43e002 100644
--- a/lib/reactions/wallet_utils.dart
+++ b/lib/reactions/wallet_utils.dart
@@ -12,6 +12,7 @@ bool isBIP39Wallet(WalletType walletType) {
case WalletType.nano:
case WalletType.banano:
case WalletType.monero:
+ case WalletType.dogecoin:
return true;
case WalletType.wownero:
case WalletType.haven:
diff --git a/lib/src/screens/dashboard/widgets/menu_widget.dart b/lib/src/screens/dashboard/widgets/menu_widget.dart
index b394e96ad..b96f0e4cc 100644
--- a/lib/src/screens/dashboard/widgets/menu_widget.dart
+++ b/lib/src/screens/dashboard/widgets/menu_widget.dart
@@ -37,7 +37,8 @@ class MenuWidgetState extends State {
this.tronIcon = Image.asset('assets/images/trx_icon.png'),
this.wowneroIcon = Image.asset('assets/images/wownero_icon.png'),
this.zanoIcon = Image.asset('assets/images/zano_icon.png'),
- this.decredIcon = Image.asset('assets/images/decred_menu.png');
+ this.decredIcon = Image.asset('assets/images/decred_menu.png'),
+ this.dogecoinIcon = Image.asset('assets/images/doge_icon.png');
final largeScreen = 731;
@@ -64,6 +65,7 @@ class MenuWidgetState extends State {
Image wowneroIcon;
Image zanoIcon;
Image decredIcon;
+ Image dogecoinIcon;
@override
void initState() {
@@ -255,6 +257,8 @@ class MenuWidgetState extends State {
return zanoIcon;
case WalletType.decred:
return decredIcon;
+ case WalletType.dogecoin:
+ return dogecoinIcon;
default:
throw Exception('No icon for ${type.toString()}');
}
diff --git a/lib/store/settings_store.dart b/lib/store/settings_store.dart
index 37e118b4e..6f78addaa 100644
--- a/lib/store/settings_store.dart
+++ b/lib/store/settings_store.dart
@@ -1070,6 +1070,7 @@ abstract class SettingsStoreBase with Store {
final wowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey);
final zanoNodeId = sharedPreferences.getInt(PreferencesKey.currentZanoNodeIdKey);
final decredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey);
+ final dogecoinNodeId = sharedPreferences.getInt(PreferencesKey.currentDogecoinNodeIdKey);
/// get the selected node, if null, then use the default
final moneroNode = nodeSource.get(nodeId) ??
@@ -1098,6 +1099,8 @@ abstract class SettingsStoreBase with Store {
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == wowneroDefaultNodeUri);
final zanoNode = nodeSource.get(zanoNodeId) ??
nodeSource.values.firstWhereOrNull((e) => e.uriRaw == zanoDefaultNodeUri);
+ final dogecoinNode = nodeSource.get(dogecoinNodeId) ??
+ nodeSource.values.firstWhereOrNull((e) => e.uriRaw == dogecoinDefaultNodeUri);
final packageInfo = await PackageInfo.fromPlatform();
final deviceName = await _getDeviceName() ?? '';
@@ -1185,6 +1188,10 @@ abstract class SettingsStoreBase with Store {
nodes[WalletType.decred] = decredNode;
}
+ if (dogecoinNode != null) {
+ nodes[WalletType.dogecoin] = dogecoinNode;
+ }
+
final savedSyncMode = SyncMode.all.firstWhere((element) {
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 2); // default to 2 - daily sync
});
@@ -1549,6 +1556,7 @@ abstract class SettingsStoreBase with Store {
final wowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey);
final zanoNodeId = sharedPreferences.getInt(PreferencesKey.currentZanoNodeIdKey);
final decredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey);
+ final dogecoinNodeId = sharedPreferences.getInt(PreferencesKey.currentDogecoinNodeIdKey);
final moneroNode = nodeSource.get(nodeId);
final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId);
final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId);
@@ -1562,6 +1570,7 @@ abstract class SettingsStoreBase with Store {
final wowneroNode = nodeSource.get(wowneroNodeId);
final zanoNode = nodeSource.get(zanoNodeId);
final decredNode = nodeSource.get(decredNodeId);
+ final dogecoinNode = nodeSource.get(dogecoinNodeId);
if (moneroNode != null) {
nodes[WalletType.monero] = moneroNode;
@@ -1616,6 +1625,10 @@ abstract class SettingsStoreBase with Store {
nodes[WalletType.decred] = decredNode;
}
+ if (dogecoinNode != null) {
+ nodes[WalletType.dogecoin] = dogecoinNode;
+ }
+
// MIGRATED:
useTOTP2FA = await SecureKey.getBool(
@@ -1757,6 +1770,10 @@ abstract class SettingsStoreBase with Store {
break;
case WalletType.zano:
await _sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, node.key as int);
+ break;
+ case WalletType.dogecoin:
+ await _sharedPreferences.setInt(PreferencesKey.currentDogecoinNodeIdKey, node.key as int);
+ break;
default:
break;
}
diff --git a/lib/view_model/advanced_privacy_settings_view_model.dart b/lib/view_model/advanced_privacy_settings_view_model.dart
index 803744590..620e18681 100644
--- a/lib/view_model/advanced_privacy_settings_view_model.dart
+++ b/lib/view_model/advanced_privacy_settings_view_model.dart
@@ -37,6 +37,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
switch (type) {
case WalletType.ethereum:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
case WalletType.polygon:
case WalletType.solana:
case WalletType.tron:
@@ -83,6 +84,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
WalletType.monero,
WalletType.wownero,
WalletType.zano,
+ WalletType.dogecoin,
].contains(type);
@computed
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index e1ef832e7..3ecfedb2c 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -865,6 +865,7 @@ abstract class DashboardViewModelBase with Store {
case WalletType.tron:
case WalletType.wownero:
case WalletType.decred:
+ case WalletType.dogecoin:
return true;
case WalletType.zano:
case WalletType.haven:
diff --git a/lib/view_model/dashboard/home_settings_view_model.dart b/lib/view_model/dashboard/home_settings_view_model.dart
index fdf4d75a5..8d1a5f8fd 100644
--- a/lib/view_model/dashboard/home_settings_view_model.dart
+++ b/lib/view_model/dashboard/home_settings_view_model.dart
@@ -242,6 +242,7 @@ abstract class HomeSettingsViewModelBase with Store {
case WalletType.wownero:
case WalletType.bitcoinCash:
case WalletType.decred:
+ case WalletType.dogecoin:
return false;
}
diff --git a/lib/view_model/dashboard/sign_view_model.dart b/lib/view_model/dashboard/sign_view_model.dart
index 5b1b4fc00..a175822c8 100644
--- a/lib/view_model/dashboard/sign_view_model.dart
+++ b/lib/view_model/dashboard/sign_view_model.dart
@@ -24,6 +24,7 @@ abstract class SignViewModelBase with Store {
WalletType.bitcoin,
WalletType.bitcoinCash,
WalletType.litecoin,
+ WalletType.dogecoin,
WalletType.haven,
].contains(wallet.type);
diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart
index 808ccabea..b59011c01 100644
--- a/lib/view_model/dashboard/transaction_list_item.dart
+++ b/lib/view_model/dashboard/transaction_list_item.dart
@@ -167,6 +167,7 @@ class TransactionListItem extends ActionListItem with Keyable {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
amount = calculateFiatAmountRaw(
cryptoAmount: bitcoin!.formatterBitcoinAmountToDouble(amount: transaction.amount),
price: price);
diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart
index 2c7e1bbab..757da5910 100644
--- a/lib/view_model/exchange/exchange_view_model.dart
+++ b/lib/view_model/exchange/exchange_view_model.dart
@@ -166,7 +166,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
}
bool get isElectrumWallet =>
- [WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type);
+ [WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash,WalletType.dogecoin ].contains(wallet.type);
bool get hideAddressAfterExchange =>
[WalletType.monero, WalletType.wownero].contains(wallet.type);
@@ -314,6 +314,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
WalletType.bitcoin,
WalletType.litecoin,
WalletType.bitcoinCash,
+ WalletType.dogecoin,
].contains(wallet.type) &&
depositCurrency == wallet.currency;
@@ -673,6 +674,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
WalletType.litecoin,
WalletType.bitcoin,
WalletType.bitcoinCash,
+ WalletType.dogecoin,
].contains(wallet.type)) {
final priority = _settingsStore.priority[wallet.type]!;
@@ -751,6 +753,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
depositCurrency = CryptoCurrency.bch;
receiveCurrency = CryptoCurrency.xmr;
break;
+ case WalletType.dogecoin:
+ depositCurrency = CryptoCurrency.doge;
+ receiveCurrency = CryptoCurrency.xmr;
+ break;
case WalletType.haven:
depositCurrency = CryptoCurrency.xhv;
receiveCurrency = CryptoCurrency.btc;
diff --git a/lib/view_model/node_list/node_create_or_edit_view_model.dart b/lib/view_model/node_list/node_create_or_edit_view_model.dart
index 715f7e05f..85c52b27b 100644
--- a/lib/view_model/node_list/node_create_or_edit_view_model.dart
+++ b/lib/view_model/node_list/node_create_or_edit_view_model.dart
@@ -93,6 +93,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
case WalletType.litecoin:
case WalletType.bitcoinCash:
case WalletType.bitcoin:
+ case WalletType.dogecoin:
case WalletType.zano:
case WalletType.decred:
return false;
diff --git a/lib/view_model/restore/wallet_restore_from_qr_code.dart b/lib/view_model/restore/wallet_restore_from_qr_code.dart
index e522a20b2..94b1072ab 100644
--- a/lib/view_model/restore/wallet_restore_from_qr_code.dart
+++ b/lib/view_model/restore/wallet_restore_from_qr_code.dart
@@ -47,6 +47,9 @@ class WalletRestoreFromQRCode {
'decred': WalletType.decred,
'decred-wallet': WalletType.decred,
'decred_wallet': WalletType.decred,
+ 'dogecoin': WalletType.dogecoin,
+ 'dogecoin-wallet': WalletType.dogecoin,
+ 'dogecoin_wallet': WalletType.dogecoin
};
static WalletType? _extractWalletType(String code) {
diff --git a/lib/view_model/send/fees_view_model.dart b/lib/view_model/send/fees_view_model.dart
index f6dd0f201..f56212d4d 100644
--- a/lib/view_model/send/fees_view_model.dart
+++ b/lib/view_model/send/fees_view_model.dart
@@ -1,5 +1,6 @@
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/decred/decred.dart';
+import 'package:cake_wallet/dogecoin/dogecoin.dart';
import 'package:cake_wallet/entities/priority_for_wallet_type.dart';
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
@@ -91,6 +92,8 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor
return transactionPriority == polygon!.getPolygonTransactionPrioritySlow();
case WalletType.decred:
return transactionPriority == decred!.getDecredTransactionPrioritySlow();
+ case WalletType.dogecoin:
+ return transactionPriority == dogecoin!.getDogeCoinTransactionPrioritySlow();
case WalletType.none:
case WalletType.nano:
case WalletType.banano:
@@ -119,7 +122,8 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor
bool get isElectrumWallet =>
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.litecoin ||
- wallet.type == WalletType.bitcoinCash;
+ wallet.type == WalletType.bitcoinCash ||
+ wallet.type == WalletType.dogecoin;
String? get walletCurrencyName => wallet.currency.fullName?.toLowerCase() ?? wallet.currency.name;
@@ -188,6 +192,9 @@ abstract class FeesViewModelBase extends WalletChangeListenerViewModel with Stor
case WalletType.bitcoinCash:
_settingsStore.priority[wallet.type] = bitcoinCash!.getDefaultTransactionPriority();
break;
+ case WalletType.dogecoin:
+ _settingsStore.priority[wallet.type] = dogecoin!.getDefaultTransactionPriority();
+ break;
case WalletType.polygon:
_settingsStore.priority[wallet.type] = polygon!.getDefaultTransactionPriority();
break;
diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart
index f4925a766..9350038de 100644
--- a/lib/view_model/send/output.dart
+++ b/lib/view_model/send/output.dart
@@ -99,6 +99,7 @@ abstract class OutputBase with Store {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
_amount = bitcoin!.formatterStringDoubleToBitcoinAmount(_cryptoAmount);
break;
case WalletType.decred:
@@ -166,7 +167,8 @@ abstract class OutputBase with Store {
return bitcoin!.formatterBitcoinAmountToDouble(amount: fee);
}
- if (_wallet.type == WalletType.litecoin || _wallet.type == WalletType.bitcoinCash) {
+ if (_wallet.type == WalletType.litecoin || _wallet.type == WalletType.bitcoinCash ||
+ _wallet.type == WalletType.dogecoin) {
return bitcoin!.formatterBitcoinAmountToDouble(amount: fee);
}
@@ -316,6 +318,7 @@ abstract class OutputBase with Store {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
maximumFractionDigits = 8;
break;
case WalletType.wownero:
diff --git a/lib/view_model/send/send_view_model.dart b/lib/view_model/send/send_view_model.dart
index fdb863866..3813c65d6 100644
--- a/lib/view_model/send/send_view_model.dart
+++ b/lib/view_model/send/send_view_model.dart
@@ -269,6 +269,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
case WalletType.monero:
case WalletType.wownero:
case WalletType.decred:
@@ -317,12 +318,13 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
WalletType.monero,
WalletType.wownero,
WalletType.decred,
- WalletType.bitcoinCash
+ WalletType.bitcoinCash,
+ WalletType.dogecoin
].contains(wallet.type);
@computed
bool get isElectrumWallet =>
- [WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type);
+ [WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, WalletType.dogecoin].contains(wallet.type);
@observable
CryptoCurrency selectedCryptoCurrency;
@@ -652,6 +654,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
switch (wallet.type) {
case WalletType.bitcoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
return bitcoin!.createBitcoinTransactionCredentials(
outputs,
priority: priority!,
diff --git a/lib/view_model/settings/other_settings_view_model.dart b/lib/view_model/settings/other_settings_view_model.dart
index 3036e8ae9..64265a09d 100644
--- a/lib/view_model/settings/other_settings_view_model.dart
+++ b/lib/view_model/settings/other_settings_view_model.dart
@@ -70,7 +70,8 @@ abstract class OtherSettingsViewModelBase with Store {
if (_wallet.type == WalletType.bitcoin ||
_wallet.type == WalletType.litecoin ||
- _wallet.type == WalletType.bitcoinCash) {
+ _wallet.type == WalletType.bitcoinCash ||
+ _wallet.type == WalletType.dogecoin) {
final rate = bitcoin!.getFeeRate(_wallet, _priority);
return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate);
}
@@ -83,7 +84,8 @@ abstract class OtherSettingsViewModelBase with Store {
if (_wallet.type == WalletType.bitcoin ||
_wallet.type == WalletType.litecoin ||
- _wallet.type == WalletType.bitcoinCash) {
+ _wallet.type == WalletType.bitcoinCash ||
+ _wallet.type == WalletType.dogecoin) {
final rate = bitcoin!.getFeeRate(_wallet, _priority);
return bitcoin!.bitcoinTransactionPriorityWithLabel(_priority, rate,
customRate: customValue);
diff --git a/lib/view_model/settings/privacy_settings_view_model.dart b/lib/view_model/settings/privacy_settings_view_model.dart
index e78f61ec4..e70383c6e 100644
--- a/lib/view_model/settings/privacy_settings_view_model.dart
+++ b/lib/view_model/settings/privacy_settings_view_model.dart
@@ -43,6 +43,7 @@ abstract class PrivacySettingsViewModelBase with Store {
WalletType.bitcoin,
WalletType.litecoin,
WalletType.bitcoinCash,
+ WalletType.dogecoin,
WalletType.decred
].contains(_wallet.type);
diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart
index bdb29e1c0..eec24a031 100644
--- a/lib/view_model/transaction_details_view_model.dart
+++ b/lib/view_model/transaction_details_view_model.dart
@@ -88,6 +88,9 @@ abstract class TransactionDetailsViewModelBase with Store {
case WalletType.decred:
_addDecredListItems(tx, dateFormat);
break;
+ case WalletType.dogecoin:
+ _addDogecoinListItems(tx, dateFormat);
+ break;
case WalletType.none:
case WalletType.banano:
break;
@@ -193,6 +196,8 @@ abstract class TransactionDetailsViewModelBase with Store {
return 'https://explorer.zano.org/transaction/${txId}';
case WalletType.decred:
return 'https://${wallet.isTestnet ? "testnet" : "dcrdata"}.decred.org/tx/${txId.split(':')[0]}';
+ case WalletType.dogecoin:
+ return 'https://blockchair.com/dogecoin/transaction/${txId}';
case WalletType.none:
return '';
}
@@ -206,6 +211,7 @@ abstract class TransactionDetailsViewModelBase with Store {
return S.current.view_transaction_on + 'mempool.space';
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
return S.current.view_transaction_on + 'Blockchair.com';
case WalletType.haven:
return S.current.view_transaction_on + 'explorer.havenprotocol.org';
@@ -750,6 +756,51 @@ abstract class TransactionDetailsViewModelBase with Store {
items.addAll(_items);
}
+ void _addDogecoinListItems(TransactionInfo tx, DateFormat dateFormat) {
+ final _items = [
+ StandartListItem(
+ title: S.current.transaction_details_transaction_id,
+ value: tx.txHash,
+ key: ValueKey('standard_list_item_transaction_details_id_key'),
+ ),
+ StandartListItem(
+ title: S.current.transaction_details_date,
+ value: dateFormat.format(tx.date),
+ key: ValueKey('standard_list_item_transaction_details_date_key'),
+ ),
+ StandartListItem(
+ title: S.current.transaction_details_height,
+ value: '${tx.height}',
+ key: ValueKey('standard_list_item_transaction_details_height_key'),
+ ),
+ StandartListItem(
+ title: S.current.transaction_details_amount,
+ value: tx.amountFormatted(),
+ key: ValueKey('standard_list_item_transaction_details_amount_key'),
+ ),
+ if (tx.feeFormatted()?.isNotEmpty ?? false)
+ StandartListItem(
+ title: S.current.transaction_details_fee,
+ value: tx.feeFormatted()!,
+ key: ValueKey('standard_list_item_transaction_details_fee_key'),
+ ),
+ if (showRecipientAddress && tx.to != null)
+ StandartListItem(
+ title: S.current.transaction_details_recipient_address,
+ value: tx.to!,
+ key: ValueKey('standard_list_item_transaction_details_recipient_address_key'),
+ ),
+ if (tx.from != null)
+ StandartListItem(
+ title: S.current.transaction_details_source_address,
+ value: tx.from!,
+ key: ValueKey('standard_list_item_transaction_details_source_address_key'),
+ ),
+ ];
+
+ items.addAll(_items);
+ }
+
@action
Future _checkForRBF(TransactionInfo tx) async {
if (wallet.type == WalletType.bitcoin &&
diff --git a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart
index 16f59aeb9..9cf6ed4bf 100644
--- a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart
+++ b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart
@@ -49,7 +49,7 @@ abstract class UnspentCoinsDetailsViewModelBase with Store {
})
];
- if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(_type)) {
+ if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, WalletType.dogecoin].contains(_type)) {
items.add(BlockExplorerListItem(
title: S.current.view_in_block_explorer,
value: _explorerDescription(_type),
@@ -71,6 +71,8 @@ abstract class UnspentCoinsDetailsViewModelBase with Store {
return 'https://litecoin.earlyordies.com/tx/${txId}';
case WalletType.bitcoinCash:
return 'https://blockchair.com/bitcoin-cash/transaction/${txId}';
+ case WalletType.dogecoin:
+ return 'https://dogechain.info/tx/${txId}';
default:
return '';
}
@@ -84,6 +86,8 @@ abstract class UnspentCoinsDetailsViewModelBase with Store {
return S.current.view_transaction_on + 'Earlyordies.com';
case WalletType.bitcoinCash:
return S.current.view_transaction_on + 'Blockchair.com';
+ case WalletType.dogecoin:
+ return S.current.view_transaction_on + 'Dogechain.info';
default:
return '';
}
diff --git a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart
index bae4677cf..5799cb58d 100644
--- a/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart
+++ b/lib/view_model/unspent_coins/unspent_coins_list_view_model.dart
@@ -91,7 +91,7 @@ abstract class UnspentCoinsListViewModelBase with Store {
return monero!.formatterMoneroAmountToString(amount: fullBalance);
if (wallet.type == WalletType.wownero)
return wownero!.formatterWowneroAmountToString(amount: fullBalance);
- if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type))
+ if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, WalletType.dogecoin].contains(wallet.type))
return bitcoin!.formatterBitcoinAmountToString(amount: fullBalance);
if (wallet.type == WalletType.decred)
return decred!.formatterDecredAmountToString(amount: fullBalance);
@@ -105,7 +105,7 @@ abstract class UnspentCoinsListViewModelBase with Store {
if (wallet.type == WalletType.wownero) {
await wownero!.updateUnspents(wallet);
}
- if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type)) {
+ if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, WalletType.dogecoin].contains(wallet.type)) {
await bitcoin!.updateUnspents(wallet);
}
if (wallet.type == WalletType.decred) {
@@ -123,6 +123,7 @@ abstract class UnspentCoinsListViewModelBase with Store {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
return bitcoin!.getUnspents(wallet, coinTypeToSpendFrom: coinTypeToSpendFrom);
case WalletType.decred:
return decred!.getUnspents(wallet);
@@ -140,6 +141,7 @@ abstract class UnspentCoinsListViewModelBase with Store {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
return bitcoin!.getUnspents(wallet, coinTypeToSpendFrom: overrideCoinTypeToSpendFrom);
case WalletType.decred:
return decred!.getUnspents(wallet);
diff --git a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart
index c417f6f4e..269b93241 100644
--- a/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart
+++ b/lib/view_model/wallet_address_list/wallet_address_edit_or_create_view_model.dart
@@ -48,7 +48,8 @@ abstract class WalletAddressEditOrCreateViewModelBase with Store {
bool get isElectrum =>
_wallet.type == WalletType.bitcoin ||
_wallet.type == WalletType.bitcoinCash ||
- _wallet.type == WalletType.litecoin;
+ _wallet.type == WalletType.litecoin ||
+ _wallet.type == WalletType.dogecoin;
Future save() async {
try {
diff --git a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
index 4cae799b1..1e02b0fba 100644
--- a/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
+++ b/lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
@@ -242,6 +242,22 @@ class DecredURI extends PaymentURI {
}
}
+class DogeURI extends PaymentURI {
+ DogeURI({required String amount, required String address})
+ : super(amount: amount, address: address);
+
+ @override
+ String toString() {
+ var base = 'doge:' + address;
+
+ if (amount.isNotEmpty) {
+ base += '?amount=${amount.replaceAll(',', '.')}';
+ }
+
+ return base;
+ }
+}
+
abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewModel with Store {
WalletAddressListViewModelBase({
required AppStore appStore,
@@ -350,6 +366,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
return ZanoURI(amount: amount, address: address.address);
case WalletType.decred:
return DecredURI(amount: amount, address: address.address);
+ case WalletType.dogecoin:
+ return DogeURI(amount: amount, address: address.address);
case WalletType.none:
throw Exception('Unexpected type: ${type.toString()}');
}
@@ -586,12 +604,13 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
WalletType.bitcoinCash,
WalletType.bitcoin,
WalletType.litecoin,
- WalletType.decred
+ WalletType.decred,
+ WalletType.dogecoin,
].contains(wallet.type);
@computed
bool get isElectrumWallet =>
- [WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash].contains(wallet.type);
+ [WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, WalletType.dogecoin].contains(wallet.type);
@computed
bool get isBalanceAvailable => isElectrumWallet;
diff --git a/lib/view_model/wallet_keys_view_model.dart b/lib/view_model/wallet_keys_view_model.dart
index 2e7eb8144..1f7620452 100644
--- a/lib/view_model/wallet_keys_view_model.dart
+++ b/lib/view_model/wallet_keys_view_model.dart
@@ -164,6 +164,7 @@ abstract class WalletKeysViewModelBase with Store {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
+ case WalletType.dogecoin:
if (_wallet.type == WalletType.bitcoin) {
keys = bitcoin!.getSilentPaymentKeys(_appStore.wallet!);
}
@@ -261,6 +262,8 @@ abstract class WalletKeysViewModelBase with Store {
return 'zano-wallet';
case WalletType.decred:
return 'decred-wallet';
+ case WalletType.dogecoin:
+ return 'dogecoin-wallet';
default:
throw Exception('Unexpected wallet type: ${_wallet.type.toString()}');
}
diff --git a/lib/view_model/wallet_new_vm.dart b/lib/view_model/wallet_new_vm.dart
index 86d1be65f..6e7a4cb96 100644
--- a/lib/view_model/wallet_new_vm.dart
+++ b/lib/view_model/wallet_new_vm.dart
@@ -1,4 +1,5 @@
import 'package:cake_wallet/core/new_wallet_arguments.dart';
+import 'package:cake_wallet/dogecoin/dogecoin.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
@@ -96,6 +97,13 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
passphrase: passphrase,
mnemonic: newWalletArguments!.mnemonic,
);
+ case WalletType.dogecoin:
+ return dogecoin!.createDogeCoinNewWalletCredentials(
+ name: name,
+ password: walletPassword,
+ passphrase: passphrase,
+ mnemonic: newWalletArguments!.mnemonic,
+ );
case WalletType.nano:
case WalletType.banano:
return nano!.createNanoNewWalletCredentials(
diff --git a/lib/view_model/wallet_restore_view_model.dart b/lib/view_model/wallet_restore_view_model.dart
index 3a7485c80..7e73cb83b 100644
--- a/lib/view_model/wallet_restore_view_model.dart
+++ b/lib/view_model/wallet_restore_view_model.dart
@@ -3,6 +3,7 @@ import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/core/generate_wallet_password.dart';
import 'package:cake_wallet/core/wallet_creation_service.dart';
import 'package:cake_wallet/di.dart';
+import 'package:cake_wallet/dogecoin/dogecoin.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/nano/nano.dart';
@@ -58,6 +59,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
case WalletType.bitcoinCash:
case WalletType.zano:
case WalletType.none:
+ case WalletType.dogecoin:
availableModes = [WalletRestoreMode.seed];
break;
}
@@ -148,6 +150,13 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
password: password,
passphrase: passphrase,
);
+ case WalletType.dogecoin:
+ return dogecoin!.createDogeCoinRestoreWalletFromSeedCredentials(
+ name: name,
+ mnemonic: seed,
+ password: password,
+ passphrase: passphrase,
+ );
case WalletType.nano:
case WalletType.banano:
return nano!.createNanoRestoreWalletFromSeedCredentials(
diff --git a/model_generator.sh b/model_generator.sh
index 7a5e3bfd7..4493e62f9 100755
--- a/model_generator.sh
+++ b/model_generator.sh
@@ -1,7 +1,7 @@
#!/bin/bash
set -x -e
-for cwcoin in cw_{core,evm,monero,bitcoin,nano,bitcoin_cash,solana,tron,wownero,zano,decred}
+for cwcoin in cw_{core,evm,monero,bitcoin,nano,bitcoin_cash,solana,tron,wownero,zano,decred,dogecoin}
do
if [[ "x$1" == "xasync" ]];
then
diff --git a/pubspec_base.yaml b/pubspec_base.yaml
index af1e67df3..ce2cbc3bc 100644
--- a/pubspec_base.yaml
+++ b/pubspec_base.yaml
@@ -177,7 +177,7 @@ dependency_overrides:
bitcoin_base:
git:
url: https://github.com/cake-tech/bitcoin_base
- ref: cake-update-v10
+ ref: cake-update-v11
ffi: 2.1.0
ledger_flutter_plus:
git:
@@ -223,6 +223,7 @@ flutter:
- assets/wownero_node_list.yml
- assets/zano_node_list.yml
- assets/decred_node_list.yml
+ - assets/dogecoin_electrum_server_list.yml
- assets/text/
- assets/faq/
- assets/animation/
diff --git a/scripts/android/pubspec_gen.sh b/scripts/android/pubspec_gen.sh
index b980f877d..8170b7ff4 100755
--- a/scripts/android/pubspec_gen.sh
+++ b/scripts/android/pubspec_gen.sh
@@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in
CONFIG_ARGS="--monero"
;;
$CAKEWALLET)
- CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred"
+ CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred --dogecoin"
;;
esac
diff --git a/scripts/ios/app_config.sh b/scripts/ios/app_config.sh
index b642d67e4..78a8f7d82 100755
--- a/scripts/ios/app_config.sh
+++ b/scripts/ios/app_config.sh
@@ -31,7 +31,7 @@ case $APP_IOS_TYPE in
;;
$CAKEWALLET)
- CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred"
+ CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --zano --decred --dogecoin"
;;
esac
diff --git a/scripts/linux/app_config.sh b/scripts/linux/app_config.sh
index 5d9d8597b..77bb6c272 100755
--- a/scripts/linux/app_config.sh
+++ b/scripts/linux/app_config.sh
@@ -13,7 +13,7 @@ CONFIG_ARGS=""
case $APP_LINUX_TYPE in
$CAKEWALLET)
- CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --excludeFlutterSecureStorage";;
+ CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --dogecoin --excludeFlutterSecureStorage";;
esac
cp -rf pubspec_description.yaml pubspec.yaml
diff --git a/scripts/macos/app_config.sh b/scripts/macos/app_config.sh
index 1c53ef1f2..dfea3dee2 100755
--- a/scripts/macos/app_config.sh
+++ b/scripts/macos/app_config.sh
@@ -36,7 +36,7 @@ case $APP_MACOS_TYPE in
$MONERO_COM)
CONFIG_ARGS="--monero";;
$CAKEWALLET)
- CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero";;
+ CONFIG_ARGS="--monero --bitcoin --ethereum --polygon --nano --bitcoinCash --solana --tron --wownero --dogecoin";;
esac
cp -rf pubspec_description.yaml pubspec.yaml
diff --git a/tool/configure.dart b/tool/configure.dart
index d91c1154b..ee44fba4f 100644
--- a/tool/configure.dart
+++ b/tool/configure.dart
@@ -11,6 +11,7 @@ const tronOutputPath = 'lib/tron/tron.dart';
const wowneroOutputPath = 'lib/wownero/wownero.dart';
const zanoOutputPath = 'lib/zano/zano.dart';
const decredOutputPath = 'lib/decred/decred.dart';
+const dogecoinOutputPath = 'lib/dogecoin/dogecoin.dart';
const walletTypesPath = 'lib/wallet_types.g.dart';
const secureStoragePath = 'lib/core/secure_storage.dart';
const pubspecDefaultPath = 'pubspec_default.yaml';
@@ -30,6 +31,7 @@ Future main(List args) async {
final hasWownero = args.contains('${prefix}wownero');
final hasZano = args.contains('${prefix}zano');
final hasDecred = args.contains('${prefix}decred');
+ final hasDogecoin = args.contains('${prefix}dogecoin');
final excludeFlutterSecureStorage = args.contains('${prefix}excludeFlutterSecureStorage');
await generateBitcoin(hasBitcoin);
@@ -44,6 +46,7 @@ Future main(List args) async {
await generateZano(hasZano);
// await generateBanano(hasEthereum);
await generateDecred(hasDecred);
+ await generateDogecoin(hasDogecoin);
await generatePubspec(
hasMonero: hasMonero,
@@ -59,6 +62,7 @@ Future main(List args) async {
hasWownero: hasWownero,
hasZano: hasZano,
hasDecred: hasDecred,
+ hasDogecoin: hasDogecoin,
);
await generateWalletTypes(
hasMonero: hasMonero,
@@ -73,6 +77,7 @@ Future main(List args) async {
hasWownero: hasWownero,
hasZano: hasZano,
hasDecred: hasDecred,
+ hasDogecoin: hasDogecoin,
);
await injectSecureStorage(!excludeFlutterSecureStorage);
}
@@ -1414,6 +1419,61 @@ abstract class Decred {
await outputFile.writeAsString(output);
}
+Future generateDogecoin(bool hasImplementation) async {
+ final outputFile = File(dogecoinOutputPath);
+ const dogecoinCommonHeaders = """
+import 'package:cw_core/transaction_priority.dart';
+import 'package:cw_core/unspent_coins_info.dart';
+import 'package:cw_core/wallet_credentials.dart';
+import 'package:cw_core/wallet_info.dart';
+import 'package:cw_core/wallet_service.dart';
+import 'package:hive/hive.dart';
+""";
+ const dogecoinCWHeaders = """
+import 'package:cw_dogecoin/cw_dogecoin.dart';
+""";
+ const dogecoinCwPart = "part 'cw_dogecoin.dart';";
+ const dogecoinContent = """
+abstract class DogeCoin {
+
+ WalletService createDogeCoinWalletService(
+ Box walletInfoSource, Box unspentCoinSource, bool isDirect);
+
+ WalletCredentials createDogeCoinNewWalletCredentials(
+ {required String name, WalletInfo? walletInfo, String? password, String? passphrase, String? mnemonic});
+
+ WalletCredentials createDogeCoinRestoreWalletFromSeedCredentials(
+ {required String name, required String mnemonic, required String password, String? passphrase});
+
+ TransactionPriority deserializeDogeCoinTransactionPriority(int raw);
+
+ TransactionPriority getDefaultTransactionPriority();
+
+ List getTransactionPriorities();
+
+ TransactionPriority getDogeCoinTransactionPrioritySlow();
+}
+""";
+
+ const dogecoinEmptyDefinition = 'DogeCoin? dogecoin;\n';
+ const dogecoinCWDefinition = 'DogeCoin? dogecoin = CWDogeCoin();\n';
+
+ final output = '$dogecoinCommonHeaders\n' +
+ (hasImplementation ? '$dogecoinCWHeaders\n' : '\n') +
+ (hasImplementation ? '$dogecoinCwPart\n\n' : '\n') +
+ (hasImplementation
+ ? dogecoinCWDefinition
+ : dogecoinEmptyDefinition) +
+ '\n' +
+ dogecoinContent;
+
+ if (outputFile.existsSync()) {
+ await outputFile.delete();
+ }
+
+ await outputFile.writeAsString(output);
+}
+
Future generatePubspec({
required bool hasMonero,
required bool hasBitcoin,
@@ -1428,6 +1488,7 @@ Future generatePubspec({
required bool hasWownero,
required bool hasZano,
required bool hasDecred,
+ required bool hasDogecoin,
}) async {
const cwCore = """
cw_core:
@@ -1492,6 +1553,10 @@ Future generatePubspec({
cw_decred:
path: ./cw_decred
""";
+ const cwDogecoin = """
+ cw_dogecoin:
+ path: ./cw_dogecoin
+ """;
final inputFile = File(pubspecOutputPath);
final inputText = await inputFile.readAsString();
final inputLines = inputText.split('\n');
@@ -1557,6 +1622,10 @@ Future generatePubspec({
output += '\n$cwZano';
}
+ if (hasDogecoin) {
+ output += '\n$cwDogecoin';
+ }
+
final outputLines = output.split('\n');
inputLines.insertAll(dependenciesIndex + 1, outputLines);
final outputContent = inputLines.join('\n');
@@ -1582,6 +1651,7 @@ Future generateWalletTypes({
required bool hasWownero,
required bool hasZano,
required bool hasDecred,
+ required bool hasDogecoin,
}) async {
final walletTypesFile = File(walletTypesPath);
@@ -1609,6 +1679,10 @@ Future generateWalletTypes({
outputContent += '\tWalletType.litecoin,\n';
}
+ if (hasDogecoin) {
+ outputContent += '\tWalletType.dogecoin,\n';
+ }
+
if (hasBitcoinCash) {
outputContent += '\tWalletType.bitcoinCash,\n';
}