2024-03-06 02:32:15 +00:00
|
|
|
import 'dart:io';
|
|
|
|
import 'package:cw_core/transaction_direction.dart';
|
|
|
|
import 'package:cw_decred/pending_transaction.dart';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
import 'package:mobx/mobx.dart';
|
|
|
|
|
|
|
|
import 'package:cw_decred/api/libdcrwallet.dart' as libdcrwallet;
|
2023-12-22 11:59:02 +00:00
|
|
|
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/balance.dart';
|
|
|
|
import 'package:cw_decred/transaction_info.dart';
|
|
|
|
import 'package:cw_core/crypto_currency.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 {
|
2024-03-06 02:32:15 +00:00
|
|
|
DecredWalletBase(WalletInfo walletInfo, String password)
|
|
|
|
: _password = password,
|
2023-12-22 11:59:02 +00:00
|
|
|
syncStatus = NotConnectedSyncStatus(),
|
2024-03-06 02:32:15 +00:00
|
|
|
balance = ObservableMap.of({CryptoCurrency.dcr: DecredBalance.zero()}),
|
2023-12-22 11:59:02 +00:00
|
|
|
super(walletInfo) {
|
2024-03-06 02:32:15 +00:00
|
|
|
walletAddresses = DecredWalletAddresses(walletInfo);
|
2023-12-22 11:59:02 +00:00
|
|
|
transactionHistory = DecredTransactionHistory();
|
|
|
|
}
|
|
|
|
|
2024-03-06 02:32:15 +00:00
|
|
|
// password is currently only used for seed display, but would likely also be
|
|
|
|
// required to sign inputs when creating transactions.
|
|
|
|
final String _password;
|
2023-12-22 11:59:02 +00:00
|
|
|
|
|
|
|
// TODO: Set up a way to change the balance and sync status when dcrlibwallet
|
|
|
|
// changes. Long polling probably?
|
|
|
|
@override
|
|
|
|
@observable
|
2024-03-06 02:32:15 +00:00
|
|
|
SyncStatus syncStatus;
|
2023-12-22 11:59:02 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
@observable
|
2024-03-06 02:32:15 +00:00
|
|
|
late ObservableMap<CryptoCurrency, DecredBalance> balance;
|
2023-12-22 11:59:02 +00:00
|
|
|
|
2024-03-06 02:32:15 +00:00
|
|
|
@override
|
|
|
|
late DecredWalletAddresses walletAddresses;
|
2023-12-22 11:59:02 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
String? get seed {
|
2024-03-06 02:32:15 +00:00
|
|
|
return libdcrwallet.walletSeed(walletInfo.name, _password);
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Object get keys {
|
|
|
|
// throw UnimplementedError();
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2024-03-06 02:32:15 +00:00
|
|
|
Future<void> init() async {
|
|
|
|
updateBalance();
|
|
|
|
// TODO: update other wallet properties such as syncStatus, walletAddresses
|
|
|
|
// and transactionHistory with data from libdcrwallet.
|
|
|
|
}
|
2023-12-22 11:59:02 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
Future<void> connectToNode({required Node node}) async {
|
|
|
|
//throw UnimplementedError();
|
|
|
|
}
|
|
|
|
|
|
|
|
@action
|
|
|
|
@override
|
|
|
|
Future<void> startSync() async {
|
2024-03-06 02:32:15 +00:00
|
|
|
// TODO: call libdcrwallet.spvSync() and update syncStatus.
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<PendingTransaction> createTransaction(Object credentials) async {
|
2024-03-06 02:32:15 +00:00
|
|
|
return DecredPendingTransaction(
|
|
|
|
txid:
|
|
|
|
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
|
|
|
|
amount: 12345678,
|
|
|
|
fee: 1234,
|
|
|
|
rawHex: "baadbeef");
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int feeRate(TransactionPriority priority) {
|
2024-03-06 02:32:15 +00:00
|
|
|
// TODO
|
|
|
|
return 1000;
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
|
|
|
|
if (priority is DecredTransactionPriority) {
|
2024-03-06 02:32:15 +00:00
|
|
|
return libdcrwallet.calculateEstimatedFeeWithFeeRate(
|
|
|
|
this.feeRate(priority), amount ?? 0);
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<Map<String, DecredTransactionInfo>> fetchTransactions() async {
|
2024-03-06 02:32:15 +00:00
|
|
|
// TODO: Read from libdcrwallet.
|
|
|
|
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
|
|
|
|
};
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<void> save() async {}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<void> rescan({required int height}) async {
|
2024-03-06 02:32:15 +00:00
|
|
|
// TODO.
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void close() {
|
2024-03-06 02:32:15 +00:00
|
|
|
libdcrwallet.closeWallet(walletInfo.name);
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<void> changePassword(String password) async {
|
2024-03-06 02:32:15 +00:00
|
|
|
await libdcrwallet.changeWalletPassword(
|
|
|
|
walletInfo.name, _password, password);
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<void>? updateBalance() async {
|
2024-03-06 02:32:15 +00:00
|
|
|
final balanceMap = libdcrwallet.balance(walletInfo.name);
|
|
|
|
balance[CryptoCurrency.dcr] = DecredBalance(
|
|
|
|
confirmed: balanceMap["confirmed"] ?? 0,
|
|
|
|
unconfirmed: balanceMap["unconfirmed"] ?? 0,
|
|
|
|
);
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void setExceptionHandler(void Function(FlutterErrorDetails) onError) =>
|
|
|
|
onError;
|
|
|
|
|
|
|
|
Future<void> renameWalletFiles(String newWalletName) async {
|
|
|
|
final currentDirPath =
|
|
|
|
await pathForWalletDir(name: walletInfo.name, type: type);
|
|
|
|
|
2024-03-06 02:32:15 +00:00
|
|
|
final newDirPath = await pathForWalletDir(name: newWalletName, type: type);
|
2023-12-22 11:59:02 +00:00
|
|
|
|
2024-03-06 02:32:15 +00:00
|
|
|
if (File(newDirPath).existsSync()) {
|
|
|
|
throw "wallet already exists at $newDirPath";
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
2024-03-06 02:32:15 +00:00
|
|
|
;
|
2023-12-22 11:59:02 +00:00
|
|
|
|
2024-03-06 02:32:15 +00:00
|
|
|
await Directory(currentDirPath).rename(newDirPath);
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
String signMessage(String message, {String? address = null}) {
|
2024-03-06 02:32:15 +00:00
|
|
|
return ""; // TODO
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
List<Unspent> unspents() {
|
2024-03-06 02:32:15 +00:00
|
|
|
return [
|
|
|
|
Unspent(
|
|
|
|
"DsT4qJPPaYEuQRimfgvSKxKH3paysn1x3Nt",
|
|
|
|
"3cbf3eb9523fd04e96dbaf98cdbd21779222cc8855ece8700494662ae7578e02",
|
|
|
|
1234567,
|
|
|
|
0,
|
|
|
|
null)
|
|
|
|
];
|
2023-12-22 11:59:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<bool> verifyMessage(String message, String signature, {String? address = null}) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
String get password {
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|