multi: Add initial decred screens. (#1165)
Use a mock libwallet for now.
1
.gitignore
vendored
|
@ -137,6 +137,7 @@ lib/polygon/polygon.dart
|
|||
lib/solana/solana.dart
|
||||
lib/tron/tron.dart
|
||||
lib/wownero/wownero.dart
|
||||
lib/decred/decred.dart
|
||||
|
||||
ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_180.png
|
||||
ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_120.png
|
||||
|
|
BIN
assets/images/2.0x/decred.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/images/2.0x/decred_menu.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/images/3.0x/decred.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
assets/images/3.0x/decred_menu.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/decred.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/images/decred_icon.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/images/decred_menu.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
|
@ -27,6 +27,7 @@ class AmountConverter {
|
|||
case CryptoCurrency.btc:
|
||||
case CryptoCurrency.bch:
|
||||
case CryptoCurrency.ltc:
|
||||
case CryptoCurrency.dcr:
|
||||
return _bitcoinAmountToString(amount);
|
||||
case CryptoCurrency.xhv:
|
||||
case CryptoCurrency.xag:
|
||||
|
|
|
@ -30,6 +30,8 @@ CryptoCurrency currencyForWalletType(WalletType type, {bool? isTestnet}) {
|
|||
return CryptoCurrency.trx;
|
||||
case WalletType.wownero:
|
||||
return CryptoCurrency.wow;
|
||||
case WalletType.decred:
|
||||
return CryptoCurrency.dcr;
|
||||
case WalletType.none:
|
||||
throw Exception(
|
||||
'Unexpected wallet type: ${type.toString()} for CryptoCurrency currencyForWalletType');
|
||||
|
|
|
@ -101,6 +101,8 @@ class Node extends HiveObject with Keyable {
|
|||
case WalletType.tron:
|
||||
return Uri.parse(
|
||||
"http${isSSL ? "s" : ""}://$uriRaw${path!.startsWith("/") ? path : "/$path"}");
|
||||
case WalletType.decred:
|
||||
return Uri.http(uriRaw, '');
|
||||
case WalletType.none:
|
||||
throw Exception('Unexpected type ${type.toString()} for Node uri');
|
||||
}
|
||||
|
@ -160,6 +162,8 @@ class Node extends HiveObject with Keyable {
|
|||
case WalletType.solana:
|
||||
case WalletType.tron:
|
||||
return requestElectrumServer();
|
||||
case WalletType.decred:
|
||||
return requestDecredNode();
|
||||
case WalletType.none:
|
||||
return false;
|
||||
}
|
||||
|
@ -284,3 +288,7 @@ class Node extends HiveObject with Keyable {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> requestDecredNode() async {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ const walletTypes = [
|
|||
WalletType.polygon,
|
||||
WalletType.solana,
|
||||
WalletType.tron,
|
||||
WalletType.decred,
|
||||
];
|
||||
|
||||
@HiveType(typeId: WALLET_TYPE_TYPE_ID)
|
||||
|
@ -58,6 +59,9 @@ enum WalletType {
|
|||
|
||||
@HiveField(12)
|
||||
wownero,
|
||||
|
||||
@HiveField(13)
|
||||
decred
|
||||
}
|
||||
|
||||
int serializeToInt(WalletType type) {
|
||||
|
@ -86,6 +90,8 @@ int serializeToInt(WalletType type) {
|
|||
return 10;
|
||||
case WalletType.wownero:
|
||||
return 11;
|
||||
case WalletType.decred:
|
||||
return 12;
|
||||
case WalletType.none:
|
||||
return -1;
|
||||
}
|
||||
|
@ -117,6 +123,8 @@ WalletType deserializeFromInt(int raw) {
|
|||
return WalletType.tron;
|
||||
case 11:
|
||||
return WalletType.wownero;
|
||||
case 12:
|
||||
return WalletType.decred;
|
||||
default:
|
||||
throw Exception('Unexpected token: $raw for WalletType deserializeFromInt');
|
||||
}
|
||||
|
@ -148,6 +156,8 @@ String walletTypeToString(WalletType type) {
|
|||
return 'Tron';
|
||||
case WalletType.wownero:
|
||||
return 'Wownero';
|
||||
case WalletType.decred:
|
||||
return 'Decred';
|
||||
case WalletType.none:
|
||||
return '';
|
||||
}
|
||||
|
@ -179,6 +189,8 @@ String walletTypeToDisplayName(WalletType type) {
|
|||
return 'Tron (TRX)';
|
||||
case WalletType.wownero:
|
||||
return 'Wownero (WOW)';
|
||||
case WalletType.decred:
|
||||
return 'Decred (DCR)';
|
||||
case WalletType.none:
|
||||
return '';
|
||||
}
|
||||
|
@ -213,6 +225,8 @@ CryptoCurrency walletTypeToCryptoCurrency(WalletType type, {bool isTestnet = fal
|
|||
return CryptoCurrency.trx;
|
||||
case WalletType.wownero:
|
||||
return CryptoCurrency.wow;
|
||||
case WalletType.decred:
|
||||
return CryptoCurrency.dcr;
|
||||
case WalletType.none:
|
||||
throw Exception(
|
||||
'Unexpected wallet type: ${type.toString()} for CryptoCurrency walletTypeToCryptoCurrency');
|
||||
|
|
0
cw_decred/.gitignore
vendored
Normal file
10
cw_decred/.metadata
Normal file
|
@ -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: b1395592de68cc8ac4522094ae59956dd21a91db
|
||||
channel: stable
|
||||
|
||||
project_type: package
|
3
cw_decred/CHANGELOG.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
## [0.0.1] - TODO: Add release date.
|
||||
|
||||
* TODO: Describe initial release.
|
1
cw_decred/LICENSE
Normal file
|
@ -0,0 +1 @@
|
|||
TODO: Add your license here.
|
3
cw_decred/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# cw_decred
|
||||
|
||||
TODO: Fill this out.
|
26
cw_decred/lib/amount_format.dart
Normal file
|
@ -0,0 +1,26 @@
|
|||
import 'package:intl/intl.dart';
|
||||
import 'package:cw_core/crypto_amount_format.dart';
|
||||
|
||||
const decredAmountLength = 8;
|
||||
const decredAmountDivider = 100000000;
|
||||
final decredAmountFormat = NumberFormat()
|
||||
..maximumFractionDigits = decredAmountLength
|
||||
..minimumFractionDigits = 1;
|
||||
|
||||
String decredAmountToString({required int amount}) => decredAmountFormat
|
||||
.format(cryptoAmountToDouble(amount: amount, divider: decredAmountDivider));
|
||||
|
||||
double decredAmountToDouble({required int amount}) =>
|
||||
cryptoAmountToDouble(amount: amount, divider: decredAmountDivider);
|
||||
|
||||
int stringDoubleToDecredAmount(String amount) {
|
||||
int result = 0;
|
||||
|
||||
try {
|
||||
result = (double.parse(amount) * decredAmountDivider).round();
|
||||
} catch (e) {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
127
cw_decred/lib/api/dcrlibwallet.dart
Normal file
|
@ -0,0 +1,127 @@
|
|||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
import 'package:cw_core/unspent_transaction_output.dart';
|
||||
import 'package:cw_decred/balance.dart';
|
||||
import 'package:cw_decred/pending_transaction.dart';
|
||||
import 'package:cw_decred/transaction_info.dart';
|
||||
import 'package:cw_core/transaction_direction.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:io';
|
||||
|
||||
// Will it work if none of these are async functions?
|
||||
class SPVWallet {
|
||||
SPVWallet();
|
||||
|
||||
SPVWallet create(Uint8List seed, String password, WalletInfo walletInfo) {
|
||||
return SPVWallet();
|
||||
}
|
||||
|
||||
SPVWallet load(String password, String name, WalletInfo walletInfo) {
|
||||
return SPVWallet();
|
||||
}
|
||||
|
||||
DecredBalance balance() {
|
||||
return DecredBalance(
|
||||
confirmed: 777,
|
||||
unconfirmed: 111,
|
||||
);
|
||||
}
|
||||
|
||||
int feeRate(int priority) {
|
||||
return 1000;
|
||||
}
|
||||
|
||||
int calculateEstimatedFeeWithFeeRate(int feeRate, int amount) {
|
||||
// Ideally we create a tx with wallet going to this amount and just return
|
||||
// the fee we get back.
|
||||
return 123000;
|
||||
}
|
||||
|
||||
void close() {}
|
||||
|
||||
DecredPendingTransaction createTransaction(Object credentials) {
|
||||
return DecredPendingTransaction(
|
||||
spv: this,
|
||||
txid:
|
||||
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
|
||||
amount: 12345678,
|
||||
fee: 1234,
|
||||
rawHex: "baadbeef");
|
||||
}
|
||||
|
||||
void rescan(int height) {
|
||||
sleep(Duration(seconds: 10));
|
||||
}
|
||||
|
||||
void startSync() {
|
||||
sleep(Duration(seconds: 5));
|
||||
}
|
||||
|
||||
SyncStatus syncStatus() {
|
||||
return SyncedSyncStatus();
|
||||
}
|
||||
|
||||
int height() {
|
||||
return 400;
|
||||
}
|
||||
|
||||
Map<String, DecredTransactionInfo> transactions() {
|
||||
final txInfo = DecredTransactionInfo(
|
||||
id: "3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
|
||||
amount: 1234567,
|
||||
fee: 123,
|
||||
direction: TransactionDirection.outgoing,
|
||||
isPending: true,
|
||||
date: DateTime.now(),
|
||||
height: 0,
|
||||
confirmations: 0,
|
||||
to: "DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt",
|
||||
);
|
||||
return {
|
||||
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02": txInfo
|
||||
};
|
||||
}
|
||||
|
||||
String newAddress() {
|
||||
// external
|
||||
return "DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt";
|
||||
}
|
||||
|
||||
List<String> addresses() {
|
||||
return [
|
||||
"DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt",
|
||||
"DsVZGfGpd7WVffBZ5wbFZEHLV3FHNmXs9Az"
|
||||
];
|
||||
}
|
||||
|
||||
List<Unspent> unspents() {
|
||||
return [
|
||||
Unspent(
|
||||
"DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt",
|
||||
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
|
||||
1234567,
|
||||
0,
|
||||
null)
|
||||
];
|
||||
}
|
||||
|
||||
void changePassword(String newPW) {}
|
||||
|
||||
void sendRawTransaction(String rawHex) {}
|
||||
|
||||
String signMessage(String message, String? address) {
|
||||
return "abababababababab";
|
||||
}
|
||||
}
|
||||
|
||||
Uint8List mnemonicToSeedBytes(String mnemonic) {
|
||||
return Uint8List(32);
|
||||
}
|
||||
|
||||
String generateMnemonic() {
|
||||
return "maid upper strategy dove theory dream material cruel season best napkin ethics biology top episode rough hotel flight video target organ six disagree verify maid upper strategy dove theory dream material cruel season best napkin ethics biology top episode rough hotel flight video target organ six disagree verify";
|
||||
}
|
||||
|
||||
bool validateMnemonic(String mnemonic) {
|
||||
return true;
|
||||
}
|
18
cw_decred/lib/balance.dart
Normal file
|
@ -0,0 +1,18 @@
|
|||
import 'package:cw_decred/amount_format.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
|
||||
class DecredBalance extends Balance {
|
||||
const DecredBalance({required this.confirmed, required this.unconfirmed})
|
||||
: super(confirmed, unconfirmed);
|
||||
|
||||
final int confirmed;
|
||||
final int unconfirmed;
|
||||
|
||||
@override
|
||||
String get formattedAvailableBalance =>
|
||||
decredAmountToString(amount: confirmed);
|
||||
|
||||
@override
|
||||
String get formattedAdditionalBalance =>
|
||||
decredAmountToString(amount: unconfirmed);
|
||||
}
|
28
cw_decred/lib/mnemonic.dart
Normal file
|
@ -0,0 +1,28 @@
|
|||
List<String> wordList() {
|
||||
return [
|
||||
"maid",
|
||||
"upper",
|
||||
"strategy",
|
||||
"dove",
|
||||
"theory",
|
||||
"dream",
|
||||
"material",
|
||||
"cruel",
|
||||
"season",
|
||||
"best",
|
||||
"napkin",
|
||||
"ethics",
|
||||
"biology",
|
||||
"top",
|
||||
"episode",
|
||||
"rough",
|
||||
"hotel",
|
||||
"flight",
|
||||
"video",
|
||||
"target",
|
||||
"organ",
|
||||
"six",
|
||||
"disagree",
|
||||
"verify"
|
||||
];
|
||||
}
|
5
cw_decred/lib/mnemonic_is_incorrect_exception.dart
Normal file
|
@ -0,0 +1,5 @@
|
|||
class DecredMnemonicIsIncorrectException implements Exception {
|
||||
@override
|
||||
String toString() =>
|
||||
'Decred mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.';
|
||||
}
|
35
cw_decred/lib/pending_transaction.dart
Normal file
|
@ -0,0 +1,35 @@
|
|||
import 'package:cw_core/pending_transaction.dart';
|
||||
import 'package:cw_decred/amount_format.dart';
|
||||
import 'package:cw_decred/api/dcrlibwallet.dart';
|
||||
|
||||
class DecredPendingTransaction with PendingTransaction {
|
||||
DecredPendingTransaction(
|
||||
{required this.spv,
|
||||
required this.txid,
|
||||
required this.amount,
|
||||
required this.fee,
|
||||
required this.rawHex});
|
||||
|
||||
final SPVWallet spv;
|
||||
final int amount;
|
||||
final int fee;
|
||||
final String txid;
|
||||
final String rawHex;
|
||||
|
||||
@override
|
||||
String get id => txid;
|
||||
|
||||
@override
|
||||
String get amountFormatted => decredAmountToString(amount: amount);
|
||||
|
||||
@override
|
||||
String get feeFormatted => decredAmountToString(amount: fee);
|
||||
|
||||
@override
|
||||
String get hex => rawHex;
|
||||
|
||||
@override
|
||||
Future<void> commit() async {
|
||||
this.spv.sendRawTransaction(this.rawHex);
|
||||
}
|
||||
}
|
11
cw_decred/lib/transaction_credentials.dart
Normal file
|
@ -0,0 +1,11 @@
|
|||
import 'package:cw_decred/transaction_priority.dart';
|
||||
import 'package:cw_core/output_info.dart';
|
||||
|
||||
class DecredTransactionCredentials {
|
||||
DecredTransactionCredentials(this.outputs,
|
||||
{required this.priority, this.feeRate});
|
||||
|
||||
final List<OutputInfo> outputs;
|
||||
final DecredTransactionPriority? priority;
|
||||
final int? feeRate;
|
||||
}
|
28
cw_decred/lib/transaction_history.dart
Normal file
|
@ -0,0 +1,28 @@
|
|||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
|
||||
// NOTE: Methods currently not used.
|
||||
class DecredTransactionHistory extends TransactionHistoryBase<TransactionInfo> {
|
||||
DecredTransactionHistory() {
|
||||
transactions = ObservableMap<String, TransactionInfo>();
|
||||
}
|
||||
|
||||
Future<void> init() async {}
|
||||
|
||||
@override
|
||||
void addOne(TransactionInfo transaction) =>
|
||||
transactions[transaction.id] = transaction;
|
||||
|
||||
@override
|
||||
void addMany(Map<String, TransactionInfo> transactions) =>
|
||||
this.transactions.addAll(transactions);
|
||||
|
||||
@override
|
||||
Future<void> save() async {}
|
||||
|
||||
Future<void> changePassword(String password) async {}
|
||||
|
||||
void _update(TransactionInfo transaction) =>
|
||||
transactions[transaction.id] = transaction;
|
||||
}
|
45
cw_decred/lib/transaction_info.dart
Normal file
|
@ -0,0 +1,45 @@
|
|||
import 'package:cw_core/transaction_direction.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/format_amount.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_decred/amount_format.dart';
|
||||
|
||||
class DecredTransactionInfo extends TransactionInfo {
|
||||
DecredTransactionInfo({
|
||||
required String id,
|
||||
required int amount,
|
||||
required int fee,
|
||||
required TransactionDirection direction,
|
||||
required bool isPending,
|
||||
required DateTime date,
|
||||
required int height,
|
||||
required int confirmations,
|
||||
required String to,
|
||||
}) {
|
||||
this.id = id;
|
||||
this.amount = amount;
|
||||
this.fee = fee;
|
||||
this.height = height;
|
||||
this.direction = direction;
|
||||
this.date = date;
|
||||
this.isPending = isPending;
|
||||
this.confirmations = confirmations;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
String? _fiatAmount;
|
||||
|
||||
@override
|
||||
String amountFormatted() =>
|
||||
'${formatAmount(decredAmountToString(amount: amount))} ${walletTypeToCryptoCurrency(WalletType.decred).title}';
|
||||
|
||||
@override
|
||||
String? feeFormatted() =>
|
||||
'${formatAmount(decredAmountToString(amount: amount))} ${walletTypeToCryptoCurrency(WalletType.decred).title}';
|
||||
|
||||
@override
|
||||
String fiatAmount() => _fiatAmount ?? '';
|
||||
|
||||
@override
|
||||
void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount);
|
||||
}
|
54
cw_decred/lib/transaction_priority.dart
Normal file
|
@ -0,0 +1,54 @@
|
|||
import 'package:cw_core/transaction_priority.dart';
|
||||
|
||||
class DecredTransactionPriority extends TransactionPriority {
|
||||
const DecredTransactionPriority({required String title, required int raw})
|
||||
: super(title: title, raw: raw);
|
||||
|
||||
static const List<DecredTransactionPriority> all = [fast, medium, slow];
|
||||
static const DecredTransactionPriority slow =
|
||||
DecredTransactionPriority(title: 'Slow', raw: 0);
|
||||
static const DecredTransactionPriority medium =
|
||||
DecredTransactionPriority(title: 'Medium', raw: 1);
|
||||
static const DecredTransactionPriority fast =
|
||||
DecredTransactionPriority(title: 'Fast', raw: 2);
|
||||
|
||||
static DecredTransactionPriority 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 DecredTransactionPriority deserialize');
|
||||
}
|
||||
}
|
||||
|
||||
String get units => 'atom';
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
var label = '';
|
||||
|
||||
switch (this) {
|
||||
case DecredTransactionPriority.slow:
|
||||
label =
|
||||
'Slow ~24hrs'; // '${S.current.transaction_priority_slow} ~24hrs';
|
||||
break;
|
||||
case DecredTransactionPriority.medium:
|
||||
label = 'Medium'; // S.current.transaction_priority_medium;
|
||||
break;
|
||||
case DecredTransactionPriority.fast:
|
||||
label = 'Fast'; // S.current.transaction_priority_fast;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
String labelWithRate(int rate) => '${toString()} ($rate ${units}/byte)';
|
||||
}
|
212
cw_decred/lib/wallet.dart
Normal file
|
@ -0,0 +1,212 @@
|
|||
import 'package:cw_decred/transaction_history.dart';
|
||||
import 'package:cw_decred/wallet_addresses.dart';
|
||||
import 'package:cw_decred/transaction_priority.dart';
|
||||
import 'package:cw_decred/api/dcrlibwallet.dart';
|
||||
import 'package:cw_decred/balance.dart';
|
||||
import 'package:cw_decred/transaction_info.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/pending_transaction.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/sync_status.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/unspent_transaction_output.dart';
|
||||
|
||||
part 'wallet.g.dart';
|
||||
|
||||
class DecredWallet = DecredWalletBase with _$DecredWallet;
|
||||
|
||||
abstract class DecredWalletBase extends WalletBase<DecredBalance,
|
||||
DecredTransactionHistory, DecredTransactionInfo> with Store {
|
||||
DecredWalletBase(SPVWallet spv, WalletInfo walletInfo)
|
||||
: this.spv = spv,
|
||||
balance = ObservableMap<CryptoCurrency, DecredBalance>.of(
|
||||
{CryptoCurrency.dcr: spv.balance()}),
|
||||
syncStatus = NotConnectedSyncStatus(),
|
||||
super(walletInfo) {
|
||||
transactionHistory = DecredTransactionHistory();
|
||||
walletAddresses = DecredWalletAddresses(walletInfo, spv);
|
||||
}
|
||||
|
||||
final SPVWallet spv;
|
||||
|
||||
static Future<DecredWallet> create(
|
||||
{required String mnemonic,
|
||||
required String password,
|
||||
required WalletInfo walletInfo}) async {
|
||||
final seed = mnemonicToSeedBytes(mnemonic);
|
||||
final spv = SPVWallet().create(seed, password, walletInfo);
|
||||
final wallet = DecredWallet(spv, walletInfo);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
static Future<DecredWallet> open(
|
||||
{required String password,
|
||||
required String name,
|
||||
required WalletInfo walletInfo}) async {
|
||||
final spv = SPVWallet().load(name, password, walletInfo);
|
||||
final wallet = DecredWallet(spv, walletInfo);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
// TODO: Set up a way to change the balance and sync status when dcrlibwallet
|
||||
// changes. Long polling probably?
|
||||
@override
|
||||
@observable
|
||||
late ObservableMap<CryptoCurrency, DecredBalance> balance;
|
||||
|
||||
@override
|
||||
@observable
|
||||
SyncStatus syncStatus;
|
||||
|
||||
// @override
|
||||
// set syncStatus(SyncStatus status);
|
||||
|
||||
@override
|
||||
String? get seed {
|
||||
// throw UnimplementedError();
|
||||
return "";
|
||||
}
|
||||
|
||||
// @override
|
||||
// String? get privateKey => null;
|
||||
|
||||
@override
|
||||
Object get keys {
|
||||
// throw UnimplementedError();
|
||||
return {};
|
||||
}
|
||||
|
||||
@override
|
||||
late DecredWalletAddresses walletAddresses;
|
||||
|
||||
// @override
|
||||
// set isEnabledAutoGenerateSubaddress(bool value) {}
|
||||
|
||||
// @override
|
||||
// bool get isEnabledAutoGenerateSubaddress => false;
|
||||
|
||||
@override
|
||||
Future<void> connectToNode({required Node node}) async {
|
||||
//throw UnimplementedError();
|
||||
}
|
||||
|
||||
@action
|
||||
@override
|
||||
Future<void> startSync() async {
|
||||
try {
|
||||
this.spv.startSync();
|
||||
syncStatus = this.spv.syncStatus();
|
||||
} catch (e, stacktrace) {
|
||||
print(stacktrace);
|
||||
print(e.toString());
|
||||
syncStatus = FailedSyncStatus();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||
return this.spv.createTransaction(credentials);
|
||||
}
|
||||
|
||||
int feeRate(TransactionPriority priority) {
|
||||
try {
|
||||
return this.spv.feeRate(priority.raw);
|
||||
} catch (_) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
|
||||
if (priority is DecredTransactionPriority) {
|
||||
return this.spv.calculateEstimatedFeeWithFeeRate(
|
||||
this.spv.feeRate(priority.raw), amount ?? 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, DecredTransactionInfo>> fetchTransactions() async {
|
||||
return this.spv.transactions();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save() async {}
|
||||
|
||||
@override
|
||||
Future<void> rescan({required int height}) async {
|
||||
return spv.rescan(height);
|
||||
}
|
||||
|
||||
@override
|
||||
void close() {
|
||||
this.spv.close();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> changePassword(String password) async {
|
||||
return this.spv.changePassword(password);
|
||||
}
|
||||
|
||||
@override
|
||||
String get password {
|
||||
// throw UnimplementedError();
|
||||
return "";
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void>? updateBalance() async {
|
||||
balance[CryptoCurrency.dcr] = this.spv.balance();
|
||||
}
|
||||
|
||||
@override
|
||||
void setExceptionHandler(void Function(FlutterErrorDetails) onError) =>
|
||||
onError;
|
||||
|
||||
Future<void> renameWalletFiles(String newWalletName) async {
|
||||
final currentWalletPath =
|
||||
await pathForWallet(name: walletInfo.name, type: type);
|
||||
final currentWalletFile = File(currentWalletPath);
|
||||
|
||||
final currentDirPath =
|
||||
await pathForWalletDir(name: walletInfo.name, type: type);
|
||||
|
||||
// TODO: Stop the wallet, wait, and restart after.
|
||||
|
||||
// Copies current wallet files into new wallet name's dir and files
|
||||
if (currentWalletFile.existsSync()) {
|
||||
final newWalletPath =
|
||||
await pathForWallet(name: newWalletName, type: type);
|
||||
await currentWalletFile.copy(newWalletPath);
|
||||
}
|
||||
|
||||
// Delete old name's dir and files
|
||||
await Directory(currentDirPath).delete(recursive: true);
|
||||
}
|
||||
|
||||
@override
|
||||
String signMessage(String message, {String? address = null}) {
|
||||
return this.spv.signMessage(message, address);
|
||||
}
|
||||
|
||||
List<Unspent> unspents() {
|
||||
return this.spv.unspents();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> verifyMessage(String message, String signature, {String? address = null}) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
String get password {
|
||||
return "";
|
||||
}
|
||||
}
|
36
cw_decred/lib/wallet_addresses.dart
Normal file
|
@ -0,0 +1,36 @@
|
|||
import 'package:cw_core/wallet_addresses.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_decred/api/dcrlibwallet.dart';
|
||||
|
||||
class DecredWalletAddresses extends WalletAddresses {
|
||||
DecredWalletAddresses(WalletInfo walletInfo, SPVWallet spv)
|
||||
: this.spv = spv,
|
||||
super(walletInfo);
|
||||
|
||||
final SPVWallet spv;
|
||||
|
||||
@override
|
||||
String get address {
|
||||
return this.spv.newAddress();
|
||||
}
|
||||
|
||||
String generateNewAddress() {
|
||||
return this.spv.newAddress();
|
||||
}
|
||||
|
||||
List<String> addresses() {
|
||||
return this.spv.addresses();
|
||||
}
|
||||
|
||||
@override
|
||||
set address(String addr) {}
|
||||
|
||||
@override
|
||||
Future<void> init() async {}
|
||||
|
||||
@override
|
||||
Future<void> updateAddressesInBox() async {}
|
||||
|
||||
@override
|
||||
Future<void> saveAddressesInBox() async {}
|
||||
}
|
44
cw_decred/lib/wallet_creation_credentials.dart
Normal file
|
@ -0,0 +1,44 @@
|
|||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/hardware/hardware_account_data.dart';
|
||||
|
||||
class DecredNewWalletCredentials extends WalletCredentials {
|
||||
DecredNewWalletCredentials({required String name, WalletInfo? walletInfo})
|
||||
: super(name: name, walletInfo: walletInfo);
|
||||
}
|
||||
|
||||
class DecredRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||
DecredRestoreWalletFromSeedCredentials(
|
||||
{required String name,
|
||||
required String password,
|
||||
required this.mnemonic,
|
||||
WalletInfo? walletInfo})
|
||||
: super(name: name, password: password, walletInfo: walletInfo);
|
||||
|
||||
final String mnemonic;
|
||||
}
|
||||
|
||||
class DecredRestoreWalletFromWIFCredentials extends WalletCredentials {
|
||||
DecredRestoreWalletFromWIFCredentials(
|
||||
{required String name,
|
||||
required String password,
|
||||
required this.wif,
|
||||
WalletInfo? walletInfo})
|
||||
: t = throw UnimplementedError(), // TODO: Maybe can be used to create watching only wallets?
|
||||
super(name: name, password: password, walletInfo: walletInfo);
|
||||
|
||||
final String wif;
|
||||
final void t;
|
||||
}
|
||||
|
||||
class DecredRestoreWalletFromHardwareCredentials extends WalletCredentials {
|
||||
DecredRestoreWalletFromHardwareCredentials(
|
||||
{required String name,
|
||||
required this.hwAccountData,
|
||||
WalletInfo? walletInfo})
|
||||
: t = throw UnimplementedError(),
|
||||
super(name: name, walletInfo: walletInfo);
|
||||
|
||||
final HardwareAccountData hwAccountData;
|
||||
final void t;
|
||||
}
|
99
cw_decred/lib/wallet_service.dart
Normal file
|
@ -0,0 +1,99 @@
|
|||
import 'dart:io';
|
||||
import 'package:cw_decred/mnemonic_is_incorrect_exception.dart';
|
||||
import 'package:cw_decred/wallet_creation_credentials.dart';
|
||||
import 'package:cw_decred/wallet.dart';
|
||||
import 'package:cw_decred/api/dcrlibwallet.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
class DecredWalletService extends WalletService<
|
||||
DecredNewWalletCredentials,
|
||||
DecredRestoreWalletFromSeedCredentials,
|
||||
DecredRestoreWalletFromPubkeyCredentials,
|
||||
DecredRestoreWalletFromHardwareCredentials> {
|
||||
DecredWalletService(this.walletInfoSource);
|
||||
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
@override
|
||||
WalletType getType() => WalletType.decred;
|
||||
|
||||
@override
|
||||
Future<DecredWallet> create(DecredNewWalletCredentials credentials,
|
||||
{bool? isTestnet}) async {
|
||||
return await DecredWalletBase.create(
|
||||
mnemonic: generateMnemonic(),
|
||||
password: credentials.password!,
|
||||
walletInfo: credentials.walletInfo!);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> isWalletExit(String name) async =>
|
||||
File(await pathForWallet(name: name, type: getType())).existsSync();
|
||||
|
||||
@override
|
||||
Future<DecredWallet> openWallet(String name, String password) async {
|
||||
final walletInfo = walletInfoSource.values.firstWhereOrNull(
|
||||
(info) => info.id == WalletBase.idFor(name, getType()))!;
|
||||
final wallet = await DecredWalletBase.open(
|
||||
password: password, name: name, walletInfo: walletInfo);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> 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);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> rename(
|
||||
String currentName, String password, String newName) async {
|
||||
final currentWalletInfo = walletInfoSource.values.firstWhereOrNull(
|
||||
(info) => info.id == WalletBase.idFor(currentName, getType()))!;
|
||||
final currentWallet = await DecredWalletBase.open(
|
||||
password: password, name: currentName, walletInfo: currentWalletInfo);
|
||||
|
||||
await currentWallet.renameWalletFiles(newName);
|
||||
|
||||
final newWalletInfo = currentWalletInfo;
|
||||
newWalletInfo.id = WalletBase.idFor(newName, getType());
|
||||
newWalletInfo.name = newName;
|
||||
|
||||
await walletInfoSource.put(currentWalletInfo.key, newWalletInfo);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DecredWallet> restoreFromSeed(
|
||||
DecredRestoreWalletFromSeedCredentials credentials,
|
||||
{bool? isTestnet}) async {
|
||||
if (!validateMnemonic(credentials.mnemonic)) {
|
||||
throw DecredMnemonicIsIncorrectException();
|
||||
}
|
||||
|
||||
final wallet = await DecredWalletBase.create(
|
||||
password: credentials.password!,
|
||||
mnemonic: credentials.mnemonic,
|
||||
walletInfo: credentials.walletInfo!);
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<DecredWallet> restoreFromKeys(
|
||||
DecredRestoreWalletFromWIFCredentials credentials,
|
||||
{bool? isTestnet}) async =>
|
||||
throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future<DecredWallet> restoreFromHardwareWallet(
|
||||
DecredRestoreWalletFromHardwareCredentials credentials) async =>
|
||||
throw UnimplementedError();
|
||||
}
|
724
cw_decred/pubspec.lock
Normal file
|
@ -0,0 +1,724 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: "4897882604d919befd350648c7f91926a9d5de99e67b455bf0917cc2362f4bb8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "47.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "690e335554a8385bc9d787117d9eb52c0c03ee207a607e593de3c9d71b1cfe80"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.7.0"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
asn1lib:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: asn1lib
|
||||
sha256: "21afe4333076c02877d14f4a89df111e658a6d466cbfc802eb705eb91bd5adfd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
build:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build
|
||||
sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
build_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_config
|
||||
sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
build_daemon:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_daemon
|
||||
sha256: "5f02d73eb2ba16483e693f80bee4f088563a820e47d1027d4cdfe62b5bb43e65"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
build_resolvers:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_resolvers
|
||||
sha256: "687cf90a3951affac1bd5f9ecb5e3e90b60487f3d9cdc359bb310f8876bb02a6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.10"
|
||||
build_runner:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: "10c6bcdbf9d049a0b666702cf1cee4ddfdc38f02a19d35ae392863b47519848b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.6"
|
||||
build_runner_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: build_runner_core
|
||||
sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.10"
|
||||
built_collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_collection
|
||||
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
built_value:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: built_value
|
||||
sha256: "723b4021e903217dfc445ec4cf5b42e27975aece1fc4ebbc1ca6329c2d9fb54e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.7.0"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: characters
|
||||
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: code_builder
|
||||
sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.7.0"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
cw_core:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "../cw_core"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: "7a03456c3490394c8e7665890333e91ae8a49be43542b616e414449ac358acd4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.4"
|
||||
encrypt:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: encrypt
|
||||
sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.3"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fake_async
|
||||
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fixnum
|
||||
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_mobx:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_mobx
|
||||
sha256: "2ba0aa5a42811eaaeff2e35626689cf2b8a3869907d0e8889c914f2c95d8fd76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
graphs:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: graphs
|
||||
sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
hive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: hive
|
||||
sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
hive_generator:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: hive_generator
|
||||
sha256: "81fd20125cb2ce8fd23623d7744ffbaf653aae93706c9bd3bf7019ea0ace3938"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.1"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.7"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.8.1"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.0"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16+1"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
mobx:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mobx
|
||||
sha256: "42ae7277ec5c36fa5ce02aa14551065babce3c38a35947330144ff47bc775c75"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
mobx_codegen:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: mobx_codegen
|
||||
sha256: d4beb9cea4b7b014321235f8fdc7c2193ee0fe1d1198e9da7403f8bc85c4407c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.0"
|
||||
path_provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_linux
|
||||
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
path_provider_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_platform_interface
|
||||
sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
path_provider_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_windows
|
||||
sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.6"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.7.3"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: provider
|
||||
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.5"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
pubspec_parse:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pubspec_parse
|
||||
sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_gen:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_gen
|
||||
sha256: "2d79738b6bbf38a43920e2b8d189e9a3ce6cc201f4b8fc76be5e4fe377b1c38d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.6"
|
||||
source_helper:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_helper
|
||||
sha256: "3b67aade1d52416149c633ba1bb36df44d97c6b51830c2198e934e3fca87ca1f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_transform
|
||||
sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: timing
|
||||
sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
unorm_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: unorm_dart
|
||||
sha256: "23d8bf65605401a6a32cff99435fed66ef3dab3ddcad3454059165df46496a3b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "13.0.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.9"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.2.0-0 <4.0.0"
|
||||
flutter: ">=3.7.0"
|
24
cw_decred/pubspec.yaml
Normal file
|
@ -0,0 +1,24 @@
|
|||
name: cw_decred
|
||||
description: A new Flutter package project.
|
||||
version: 0.0.1
|
||||
publish_to: none
|
||||
author: Cake Wallet
|
||||
homepage: https://cakewallet.com
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.5 <3.0.0"
|
||||
flutter: ">=1.20.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
cw_core:
|
||||
path: ../cw_core
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
build_runner: ^2.1.11
|
||||
build_resolvers: ^2.0.9
|
||||
mobx_codegen: ^2.0.7
|
||||
hive_generator: ^1.1.3
|
|
@ -89,6 +89,7 @@ class WalletCreationService {
|
|||
case WalletType.haven:
|
||||
case WalletType.nano:
|
||||
case WalletType.banano:
|
||||
case WalletType.decred:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
105
lib/decred/cw_decred.dart
Normal file
|
@ -0,0 +1,105 @@
|
|||
part of 'decred.dart';
|
||||
|
||||
class CWDecred extends Decred {
|
||||
@override
|
||||
TransactionPriority getMediumTransactionPriority() =>
|
||||
DecredTransactionPriority.medium;
|
||||
|
||||
@override
|
||||
WalletCredentials createDecredRestoreWalletFromSeedCredentials(
|
||||
{required String name,
|
||||
required String mnemonic,
|
||||
required String password}) =>
|
||||
DecredRestoreWalletFromSeedCredentials(
|
||||
name: name, mnemonic: mnemonic, password: password);
|
||||
|
||||
@override
|
||||
WalletCredentials createDecredNewWalletCredentials(
|
||||
{required String name, WalletInfo? walletInfo}) =>
|
||||
DecredNewWalletCredentials(name: name, walletInfo: walletInfo);
|
||||
|
||||
@override
|
||||
List<String> getWordList() => wordList();
|
||||
|
||||
@override
|
||||
List<TransactionPriority> getTransactionPriorities() =>
|
||||
DecredTransactionPriority.all;
|
||||
|
||||
@override
|
||||
TransactionPriority deserializeDecredTransactionPriority(int raw) =>
|
||||
DecredTransactionPriority.deserialize(raw: raw);
|
||||
|
||||
@override
|
||||
int getFeeRate(Object wallet, TransactionPriority priority) {
|
||||
final decredWallet = wallet as DecredWallet;
|
||||
return decredWallet.feeRate(priority);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> generateNewAddress(Object wallet) async {
|
||||
final decredWallet = wallet as DecredWallet;
|
||||
await decredWallet.walletAddresses.generateNewAddress();
|
||||
}
|
||||
|
||||
@override
|
||||
Object createDecredTransactionCredentials(
|
||||
List<Output> outputs, TransactionPriority priority) =>
|
||||
DecredTransactionCredentials(
|
||||
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 != null ? priority as DecredTransactionPriority : null);
|
||||
|
||||
@override
|
||||
List<String> getAddresses(Object wallet) {
|
||||
final decredWallet = wallet as DecredWallet;
|
||||
return decredWallet.walletAddresses.addresses();
|
||||
}
|
||||
|
||||
@override
|
||||
String getAddress(Object wallet) {
|
||||
final decredWallet = wallet as DecredWallet;
|
||||
return decredWallet.walletAddresses.address;
|
||||
}
|
||||
|
||||
@override
|
||||
String formatterDecredAmountToString({required int amount}) =>
|
||||
decredAmountToString(amount: amount);
|
||||
|
||||
@override
|
||||
double formatterDecredAmountToDouble({required int amount}) =>
|
||||
decredAmountToDouble(amount: amount);
|
||||
|
||||
@override
|
||||
int formatterStringDoubleToDecredAmount(String amount) =>
|
||||
stringDoubleToDecredAmount(amount);
|
||||
|
||||
@override
|
||||
List<Unspent> getUnspents(Object wallet) {
|
||||
final decredWallet = wallet as DecredWallet;
|
||||
return decredWallet.unspents();
|
||||
}
|
||||
|
||||
void updateUnspents(Object wallet) async {}
|
||||
|
||||
WalletService createDecredWalletService(Box<WalletInfo> walletInfoSource) {
|
||||
return DecredWalletService(walletInfoSource);
|
||||
}
|
||||
|
||||
@override
|
||||
TransactionPriority getDecredTransactionPriorityMedium() =>
|
||||
DecredTransactionPriority.medium;
|
||||
|
||||
@override
|
||||
TransactionPriority getDecredTransactionPrioritySlow() =>
|
||||
DecredTransactionPriority.slow;
|
||||
}
|
|
@ -62,6 +62,7 @@ import 'package:cake_wallet/haven/haven.dart';
|
|||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/polygon/polygon.dart';
|
||||
import 'package:cake_wallet/decred/decred.dart';
|
||||
import 'package:cake_wallet/reactions/on_authentication_state_change.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/solana/solana.dart';
|
||||
|
@ -1093,6 +1094,8 @@ Future<void> setup({
|
|||
return tron!.createTronWalletService(_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
|
||||
case WalletType.wownero:
|
||||
return wownero!.createWowneroWalletService(_walletInfoSource, _unspentCoinsInfoSource);
|
||||
case WalletType.decred:
|
||||
return decred!.createDecredWalletService(_walletInfoSource);
|
||||
case WalletType.none:
|
||||
throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ class PreferencesKey {
|
|||
static const currentPolygonNodeIdKey = 'current_node_id_matic';
|
||||
static const currentNanoNodeIdKey = 'current_node_id_nano';
|
||||
static const currentNanoPowNodeIdKey = 'current_node_id_nano_pow';
|
||||
static const currentDecredNodeIdKey = 'current_node_id_decred';
|
||||
static const currentBananoNodeIdKey = 'current_node_id_banano';
|
||||
static const currentBananoPowNodeIdKey = 'current_node_id_banano_pow';
|
||||
static const currentFiatCurrencyKey = 'current_fiat_currency';
|
||||
|
|
|
@ -76,6 +76,7 @@ class ProvidersHelper {
|
|||
];
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
case WalletType.decred:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
@ -109,6 +110,7 @@ class ProvidersHelper {
|
|||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
case WalletType.wownero:
|
||||
case WalletType.decred:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
|
|||
final solanaIcon = Image.asset('assets/images/sol_icon.png', height: 24, width: 24);
|
||||
final tronIcon = Image.asset('assets/images/trx_icon.png', height: 24, width: 24);
|
||||
final wowneroIcon = Image.asset('assets/images/wownero_icon.png', height: 24, width: 24);
|
||||
final decredIcon = Image.asset('assets/images/decred_icon.png', height: 24, width: 24);
|
||||
final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24);
|
||||
|
||||
Image _newWalletImage(BuildContext context) => Image.asset(
|
||||
|
@ -178,6 +179,8 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
|
|||
return tronIcon;
|
||||
case WalletType.wownero:
|
||||
return wowneroIcon;
|
||||
case WalletType.decred:
|
||||
return decredIcon;
|
||||
default:
|
||||
return nonWalletTypeIcon;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,8 @@ class MenuWidgetState extends State<MenuWidget> {
|
|||
this.polygonIcon = Image.asset('assets/images/matic_icon.png'),
|
||||
this.solanaIcon = Image.asset('assets/images/sol_icon.png'),
|
||||
this.tronIcon = Image.asset('assets/images/trx_icon.png'),
|
||||
this.wowneroIcon = Image.asset('assets/images/wownero_icon.png');
|
||||
this.wowneroIcon = Image.asset('assets/images/wownero_icon.png'),
|
||||
this.decredIcon = Image.asset('assets/images/decred_menu.png');
|
||||
|
||||
final largeScreen = 731;
|
||||
|
||||
|
@ -62,6 +63,7 @@ class MenuWidgetState extends State<MenuWidget> {
|
|||
Image solanaIcon;
|
||||
Image tronIcon;
|
||||
Image wowneroIcon;
|
||||
Image decredIcon;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
@ -245,6 +247,8 @@ class MenuWidgetState extends State<MenuWidget> {
|
|||
return tronIcon;
|
||||
case WalletType.wownero:
|
||||
return wowneroIcon;
|
||||
case WalletType.decred:
|
||||
return decredIcon;
|
||||
default:
|
||||
throw Exception('No icon for ${type.toString()}');
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ class WalletListBodyState extends State<WalletListBody> {
|
|||
final bitcoinIcon = Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
|
||||
final tBitcoinIcon = Image.asset('assets/images/tbtc.png', height: 24, width: 24);
|
||||
final litecoinIcon = Image.asset('assets/images/litecoin_icon.png', height: 24, width: 24);
|
||||
final decredIcon = Image.asset('assets/images/decred_icon.png', height: 24, width: 24);
|
||||
final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24);
|
||||
final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24);
|
||||
final ethereumIcon = Image.asset('assets/images/eth_icon.png', height: 24, width: 24);
|
||||
|
@ -131,6 +132,7 @@ class WalletListBodyState extends State<WalletListBody> {
|
|||
final solanaIcon = Image.asset('assets/images/sol_icon.png', height: 24, width: 24);
|
||||
final tronIcon = Image.asset('assets/images/trx_icon.png', height: 24, width: 24);
|
||||
final wowneroIcon = Image.asset('assets/images/wownero_icon.png', height: 24, width: 24);
|
||||
final decredIcon = Image.asset('assets/images/decred_icon.png', height: 24, width: 24);
|
||||
final scrollController = ScrollController();
|
||||
final double tileHeight = 60;
|
||||
Flushbar<void>? _progressBar;
|
||||
|
|
|
@ -816,6 +816,11 @@ abstract class SettingsStoreBase with Store {
|
|||
Node getCurrentNode(WalletType walletType) {
|
||||
final node = nodes[walletType];
|
||||
|
||||
// TODO: Implement connecting to a user's preferred node.
|
||||
if (walletType == WalletType.decred) {
|
||||
return Node();
|
||||
}
|
||||
|
||||
if (node == null) {
|
||||
throw Exception('No node found for wallet type: ${walletType.toString()}');
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
|
|||
case WalletType.wownero:
|
||||
case WalletType.none:
|
||||
case WalletType.haven:
|
||||
case WalletType.decred:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -739,6 +739,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
|
|||
depositCurrency = CryptoCurrency.wow;
|
||||
receiveCurrency = CryptoCurrency.xmr;
|
||||
break;
|
||||
case WalletType.decred:
|
||||
depositCurrency = CryptoCurrency.dcr;
|
||||
receiveCurrency = CryptoCurrency.xmr;
|
||||
break;
|
||||
case WalletType.none:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
|
|||
case WalletType.litecoin:
|
||||
case WalletType.bitcoinCash:
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.decred:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:cake_wallet/ethereum/ethereum.dart';
|
|||
import 'package:cake_wallet/exchange/provider/exchange_provider.dart';
|
||||
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/decred/decred.dart';
|
||||
import 'package:cake_wallet/core/wallet_change_listener_view_model.dart';
|
||||
import 'package:cake_wallet/entities/contact_record.dart';
|
||||
import 'package:cake_wallet/entities/wallet_contact.dart';
|
||||
|
@ -569,6 +570,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
|
|||
.createSolanaTransactionCredentials(outputs, currency: selectedCryptoCurrency);
|
||||
case WalletType.tron:
|
||||
return tron!.createTronTransactionCredentials(outputs, currency: selectedCryptoCurrency);
|
||||
case WalletType.decred:
|
||||
return decred!.createDecredTransactionCredentials(outputs, priority!);
|
||||
default:
|
||||
throw Exception('Unexpected wallet type: ${wallet.type}');
|
||||
}
|
||||
|
|
|
@ -181,6 +181,8 @@ abstract class TransactionDetailsViewModelBase with Store {
|
|||
return 'https://tronscan.org/#/transaction/${txId}';
|
||||
case WalletType.wownero:
|
||||
return 'https://explore.wownero.com/tx/${txId}';
|
||||
case WalletType.decred:
|
||||
return 'https://dcrdata.decred.org/tx/${txId}';
|
||||
case WalletType.none:
|
||||
return '';
|
||||
}
|
||||
|
@ -211,6 +213,8 @@ abstract class TransactionDetailsViewModelBase with Store {
|
|||
return S.current.view_transaction_on + 'tronscan.org';
|
||||
case WalletType.wownero:
|
||||
return S.current.view_transaction_on + 'Wownero.com';
|
||||
case WalletType.decred:
|
||||
return S.current.view_transaction_on + 'dcrdata.decred.org';
|
||||
case WalletType.none:
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -205,6 +205,22 @@ class WowneroURI extends PaymentURI {
|
|||
}
|
||||
}
|
||||
|
||||
class DecredURI extends PaymentURI {
|
||||
DecredURI({required String amount, required String address})
|
||||
: super(amount: amount, address: address);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
var base = 'decred:' + address;
|
||||
|
||||
if (amount.isNotEmpty) {
|
||||
base += '?amount=${amount.replaceAll(',', '.')}';
|
||||
}
|
||||
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
||||
abstract class WalletAddressListViewModelBase
|
||||
extends WalletChangeListenerViewModel with Store {
|
||||
WalletAddressListViewModelBase({
|
||||
|
@ -298,9 +314,57 @@ abstract class WalletAddressListViewModelBase
|
|||
return TronURI(amount: amount, address: address.address);
|
||||
case WalletType.wownero:
|
||||
return WowneroURI(amount: amount, address: address.address);
|
||||
case WalletType.decred:
|
||||
return DecredURI(amount: amount, address: address.address);
|
||||
case WalletType.none:
|
||||
throw Exception('Unexpected type: ${type.toString()}');
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.haven) {
|
||||
return HavenURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.bitcoin) {
|
||||
return BitcoinURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.litecoin) {
|
||||
return LitecoinURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.ethereum) {
|
||||
return EthereumURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.bitcoinCash) {
|
||||
return BitcoinCashURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.nano) {
|
||||
return NanoURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.polygon) {
|
||||
return PolygonURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.solana) {
|
||||
return SolanaURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.tron) {
|
||||
return TronURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.wownero) {
|
||||
return WowneroURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
if (wallet.type == WalletType.decred) {
|
||||
return DecredURI(amount: amount, address: address.address);
|
||||
}
|
||||
|
||||
throw Exception('Unexpected type: ${type.toString()}');
|
||||
}
|
||||
|
||||
@computed
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'package:cake_wallet/tron/tron.dart';
|
|||
import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
|
||||
import 'package:cake_wallet/wownero/wownero.dart';
|
||||
import 'package:cake_wallet/decred/decred.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
|
@ -156,6 +157,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
|||
language: options!.first as String,
|
||||
isPolyseed: options.last as bool,
|
||||
);
|
||||
case WalletType.decred:
|
||||
return decred!.createDecredNewWalletCredentials(name: name);
|
||||
case WalletType.none:
|
||||
throw Exception('Unexpected type: ${type.toString()}');
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:cake_wallet/polygon/polygon.dart';
|
|||
import 'package:cake_wallet/solana/solana.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/tron/tron.dart';
|
||||
import 'package:cake_wallet/decred/decred.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||
import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
|
||||
|
@ -162,6 +163,12 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
|||
password: password,
|
||||
height: height,
|
||||
);
|
||||
case WalletType.decred:
|
||||
return decred!.createDecredRestoreWalletFromSeedCredentials(
|
||||
name: name,
|
||||
mnemonic: seed,
|
||||
password: password,
|
||||
);
|
||||
case WalletType.none:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ cd cw_bitcoin_cash; flutter pub get; dart run build_runner build --delete-confli
|
|||
cd cw_solana; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
|
||||
cd cw_tron; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
|
||||
cd cw_wownero; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
|
||||
cd cw_decred; flutter pub get; dart run build_runner build --delete-conflicting-outputs; cd ..
|
||||
cd cw_polygon; flutter pub get; cd ..
|
||||
cd cw_ethereum; flutter pub get; cd ..
|
||||
cd cw_mweb && flutter pub get && cd ..
|
||||
|
|
|
@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in
|
|||
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 --decred"
|
||||
if [ "$CW_WITH_HAVEN" = true ];then
|
||||
CONFIG_ARGS="$CONFIG_ARGS --haven"
|
||||
fi
|
||||
|
@ -26,4 +26,4 @@ flutter pub get
|
|||
dart run tool/generate_pubspec.dart
|
||||
flutter pub get
|
||||
dart run tool/configure.dart $CONFIG_ARGS
|
||||
cd scripts/android
|
||||
cd scripts/android
|
||||
|
|
|
@ -10,6 +10,7 @@ const polygonOutputPath = 'lib/polygon/polygon.dart';
|
|||
const solanaOutputPath = 'lib/solana/solana.dart';
|
||||
const tronOutputPath = 'lib/tron/tron.dart';
|
||||
const wowneroOutputPath = 'lib/wownero/wownero.dart';
|
||||
const decredOutputPath = 'lib/decred/decred.dart';
|
||||
const walletTypesPath = 'lib/wallet_types.g.dart';
|
||||
const secureStoragePath = 'lib/core/secure_storage.dart';
|
||||
const pubspecDefaultPath = 'pubspec_default.yaml';
|
||||
|
@ -28,6 +29,7 @@ Future<void> main(List<String> args) async {
|
|||
final hasSolana = args.contains('${prefix}solana');
|
||||
final hasTron = args.contains('${prefix}tron');
|
||||
final hasWownero = args.contains('${prefix}wownero');
|
||||
final hasDecred = args.contains('${prefix}decred');
|
||||
final excludeFlutterSecureStorage = args.contains('${prefix}excludeFlutterSecureStorage');
|
||||
|
||||
await generateBitcoin(hasBitcoin);
|
||||
|
@ -41,6 +43,7 @@ Future<void> main(List<String> args) async {
|
|||
await generateTron(hasTron);
|
||||
await generateWownero(hasWownero);
|
||||
// await generateBanano(hasEthereum);
|
||||
await generateDecred(hasDecred);
|
||||
|
||||
await generatePubspec(
|
||||
hasMonero: hasMonero,
|
||||
|
@ -55,6 +58,7 @@ Future<void> main(List<String> args) async {
|
|||
hasSolana: hasSolana,
|
||||
hasTron: hasTron,
|
||||
hasWownero: hasWownero,
|
||||
hasDecred: hasDecred,
|
||||
);
|
||||
await generateWalletTypes(
|
||||
hasMonero: hasMonero,
|
||||
|
@ -68,6 +72,7 @@ Future<void> main(List<String> args) async {
|
|||
hasSolana: hasSolana,
|
||||
hasTron: hasTron,
|
||||
hasWownero: hasWownero,
|
||||
hasDecred: hasDecred,
|
||||
);
|
||||
await injectSecureStorage(!excludeFlutterSecureStorage);
|
||||
}
|
||||
|
@ -1398,6 +1403,74 @@ abstract class Tron {
|
|||
await outputFile.writeAsString(output);
|
||||
}
|
||||
|
||||
Future<void> generateDecred(bool hasImplementation) async {
|
||||
final outputFile = File(decredOutputPath);
|
||||
const decredCommonHeaders = """
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/output_info.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cw_core/unspent_transaction_output.dart';
|
||||
import 'package:cake_wallet/view_model/send/output.dart';
|
||||
import 'package:hive/hive.dart';""";
|
||||
const decredCWHeaders = """
|
||||
import 'package:cw_decred/mnemonic.dart';
|
||||
import 'package:cw_decred/transaction_priority.dart';
|
||||
import 'package:cw_decred/wallet.dart';
|
||||
import 'package:cw_decred/wallet_service.dart';
|
||||
import 'package:cw_decred/wallet_creation_credentials.dart';
|
||||
import 'package:cw_decred/amount_format.dart';
|
||||
import 'package:cw_decred/transaction_credentials.dart';
|
||||
""";
|
||||
const decredCwPart = "part 'cw_decred.dart';";
|
||||
const decredContent = """
|
||||
|
||||
abstract class Decred {
|
||||
TransactionPriority getMediumTransactionPriority();
|
||||
|
||||
WalletCredentials createDecredRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password});
|
||||
WalletCredentials createDecredNewWalletCredentials({required String name, WalletInfo? walletInfo});
|
||||
List<String> getWordList();
|
||||
List<TransactionPriority> getTransactionPriorities();
|
||||
TransactionPriority deserializeDecredTransactionPriority(int raw);
|
||||
int getFeeRate(Object wallet, TransactionPriority priority);
|
||||
Future<void> generateNewAddress(Object wallet);
|
||||
Object createDecredTransactionCredentials(List<Output> outputs, TransactionPriority priority);
|
||||
|
||||
List<String> getAddresses(Object wallet);
|
||||
String getAddress(Object wallet);
|
||||
|
||||
String formatterDecredAmountToString({required int amount});
|
||||
double formatterDecredAmountToDouble({required int amount});
|
||||
int formatterStringDoubleToDecredAmount(String amount);
|
||||
|
||||
List<Unspent> getUnspents(Object wallet);
|
||||
void updateUnspents(Object wallet);
|
||||
WalletService createDecredWalletService(Box<WalletInfo> walletInfoSource);
|
||||
TransactionPriority getDecredTransactionPriorityMedium();
|
||||
TransactionPriority getDecredTransactionPrioritySlow();
|
||||
}
|
||||
""";
|
||||
|
||||
const decredEmptyDefinition = 'Decred? decred;\n';
|
||||
const decredCWDefinition = 'Decred? decred = CWDecred();\n';
|
||||
|
||||
final output = '$decredCommonHeaders\n'
|
||||
+ (hasImplementation ? '$decredCWHeaders\n' : '\n')
|
||||
+ (hasImplementation ? '$decredCwPart\n\n' : '\n')
|
||||
+ (hasImplementation ? decredCWDefinition : decredEmptyDefinition)
|
||||
+ '\n'
|
||||
+ decredContent;
|
||||
|
||||
if (outputFile.existsSync()) {
|
||||
await outputFile.delete();
|
||||
}
|
||||
|
||||
await outputFile.writeAsString(output);
|
||||
}
|
||||
|
||||
Future<void> generatePubspec({
|
||||
required bool hasMonero,
|
||||
required bool hasBitcoin,
|
||||
|
@ -1411,6 +1484,7 @@ Future<void> generatePubspec({
|
|||
required bool hasSolana,
|
||||
required bool hasTron,
|
||||
required bool hasWownero,
|
||||
required bool hasDecred,
|
||||
}) async {
|
||||
const cwCore = """
|
||||
cw_core:
|
||||
|
@ -1475,6 +1549,10 @@ Future<void> generatePubspec({
|
|||
cw_wownero:
|
||||
path: ./cw_wownero
|
||||
""";
|
||||
const cwDecred = """
|
||||
cw_decred:
|
||||
path: ./cw_decred
|
||||
""";
|
||||
final inputFile = File(pubspecOutputPath);
|
||||
final inputText = await inputFile.readAsString();
|
||||
final inputLines = inputText.split('\n');
|
||||
|
@ -1524,6 +1602,10 @@ Future<void> generatePubspec({
|
|||
output += '\n$cwSharedExternal\n$cwHaven';
|
||||
}
|
||||
|
||||
if (hasDecred) {
|
||||
output += '\n$cwDecred';
|
||||
}
|
||||
|
||||
if (hasFlutterSecureStorage) {
|
||||
output += '\n$flutterSecureStorage\n';
|
||||
}
|
||||
|
@ -1560,6 +1642,7 @@ Future<void> generateWalletTypes({
|
|||
required bool hasSolana,
|
||||
required bool hasTron,
|
||||
required bool hasWownero,
|
||||
required bool hasDecred,
|
||||
}) async {
|
||||
final walletTypesFile = File(walletTypesPath);
|
||||
|
||||
|
@ -1619,6 +1702,10 @@ Future<void> generateWalletTypes({
|
|||
outputContent += '\tWalletType.haven,\n';
|
||||
}
|
||||
|
||||
if (hasDecred) {
|
||||
outputContent += '\tWalletType.decred,\n';
|
||||
}
|
||||
|
||||
outputContent += '];\n';
|
||||
await walletTypesFile.writeAsString(outputContent);
|
||||
}
|
||||
|
|