mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 12:09:43 +00:00
config changes
This commit is contained in:
parent
359c5e8a9a
commit
e3624880c5
35 changed files with 2108 additions and 344 deletions
83
cw_nano/lib/api/account_list.dart
Normal file
83
cw_nano/lib/api/account_list.dart
Normal file
|
@ -0,0 +1,83 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:cw_nano/api/signatures.dart';
|
||||
import 'package:cw_nano/api/types.dart';
|
||||
import 'package:cw_nano/api/monero_api.dart';
|
||||
import 'package:cw_nano/api/structs/account_row.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_nano/api/wallet.dart';
|
||||
|
||||
final accountSizeNative = moneroApi
|
||||
.lookup<NativeFunction<account_size>>('account_size')
|
||||
.asFunction<SubaddressSize>();
|
||||
|
||||
final accountRefreshNative = moneroApi
|
||||
.lookup<NativeFunction<account_refresh>>('account_refresh')
|
||||
.asFunction<AccountRefresh>();
|
||||
|
||||
final accountGetAllNative = moneroApi
|
||||
.lookup<NativeFunction<account_get_all>>('account_get_all')
|
||||
.asFunction<AccountGetAll>();
|
||||
|
||||
final accountAddNewNative = moneroApi
|
||||
.lookup<NativeFunction<account_add_new>>('account_add_row')
|
||||
.asFunction<AccountAddNew>();
|
||||
|
||||
final accountSetLabelNative = moneroApi
|
||||
.lookup<NativeFunction<account_set_label>>('account_set_label_row')
|
||||
.asFunction<AccountSetLabel>();
|
||||
|
||||
bool isUpdating = false;
|
||||
|
||||
void refreshAccounts() {
|
||||
try {
|
||||
isUpdating = true;
|
||||
accountRefreshNative();
|
||||
isUpdating = false;
|
||||
} catch (e) {
|
||||
isUpdating = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
List<AccountRow> getAllAccount() {
|
||||
final size = accountSizeNative();
|
||||
final accountAddressesPointer = accountGetAllNative();
|
||||
final accountAddresses = accountAddressesPointer.asTypedList(size);
|
||||
|
||||
return accountAddresses
|
||||
.map((addr) => Pointer<AccountRow>.fromAddress(addr).ref)
|
||||
.toList();
|
||||
}
|
||||
|
||||
void addAccountSync({required String label}) {
|
||||
final labelPointer = label.toNativeUtf8();
|
||||
accountAddNewNative(labelPointer);
|
||||
calloc.free(labelPointer);
|
||||
}
|
||||
|
||||
void setLabelForAccountSync({required int accountIndex, required String label}) {
|
||||
final labelPointer = label.toNativeUtf8();
|
||||
accountSetLabelNative(accountIndex, labelPointer);
|
||||
calloc.free(labelPointer);
|
||||
}
|
||||
|
||||
void _addAccount(String label) => addAccountSync(label: label);
|
||||
|
||||
void _setLabelForAccount(Map<String, dynamic> args) {
|
||||
final label = args['label'] as String;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
|
||||
setLabelForAccountSync(label: label, accountIndex: accountIndex);
|
||||
}
|
||||
|
||||
Future<void> addAccount({required String label}) async {
|
||||
await compute(_addAccount, label);
|
||||
await store();
|
||||
}
|
||||
|
||||
Future<void> setLabelForAccount({required int accountIndex, required String label}) async {
|
||||
await compute(
|
||||
_setLabelForAccount, {'accountIndex': accountIndex, 'label': label});
|
||||
await store();
|
||||
}
|
8
cw_nano/lib/api/convert_utf8_to_string.dart
Normal file
8
cw_nano/lib/api/convert_utf8_to_string.dart
Normal file
|
@ -0,0 +1,8 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
String convertUTF8ToString({required Pointer<Utf8> pointer}) {
|
||||
final str = pointer.toDartString();
|
||||
calloc.free(pointer);
|
||||
return str;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
class ConnectionToNodeException implements Exception {
|
||||
ConnectionToNodeException({required this.message});
|
||||
|
||||
final String message;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
class CreationTransactionException implements Exception {
|
||||
CreationTransactionException({required this.message});
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
5
cw_nano/lib/api/exceptions/setup_wallet_exception.dart
Normal file
5
cw_nano/lib/api/exceptions/setup_wallet_exception.dart
Normal file
|
@ -0,0 +1,5 @@
|
|||
class SetupWalletException implements Exception {
|
||||
SetupWalletException({required this.message});
|
||||
|
||||
final String message;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
class WalletCreationException implements Exception {
|
||||
WalletCreationException({required this.message});
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
8
cw_nano/lib/api/exceptions/wallet_opening_exception.dart
Normal file
8
cw_nano/lib/api/exceptions/wallet_opening_exception.dart
Normal file
|
@ -0,0 +1,8 @@
|
|||
class WalletOpeningException implements Exception {
|
||||
WalletOpeningException({required this.message});
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
class WalletRestoreFromKeysException implements Exception {
|
||||
WalletRestoreFromKeysException({required this.message});
|
||||
|
||||
final String message;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
class WalletRestoreFromSeedException implements Exception {
|
||||
WalletRestoreFromSeedException({required this.message});
|
||||
|
||||
final String message;
|
||||
}
|
6
cw_nano/lib/api/monero_api.dart
Normal file
6
cw_nano/lib/api/monero_api.dart
Normal file
|
@ -0,0 +1,6 @@
|
|||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
|
||||
final DynamicLibrary moneroApi = Platform.isAndroid
|
||||
? DynamicLibrary.open("libcw_monero.so")
|
||||
: DynamicLibrary.open("cw_monero.framework/cw_monero");
|
6
cw_nano/lib/api/monero_output.dart
Normal file
6
cw_nano/lib/api/monero_output.dart
Normal file
|
@ -0,0 +1,6 @@
|
|||
class MoneroOutput {
|
||||
MoneroOutput({required this.address, required this.amount});
|
||||
|
||||
final String address;
|
||||
final String amount;
|
||||
}
|
132
cw_nano/lib/api/signatures.dart
Normal file
132
cw_nano/lib/api/signatures.dart
Normal file
|
@ -0,0 +1,132 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
typedef create_wallet = Int8 Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Pointer<Utf8>);
|
||||
|
||||
typedef restore_wallet_from_seed = Int8 Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
|
||||
|
||||
typedef restore_wallet_from_keys = Int8 Function(Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
|
||||
|
||||
typedef is_wallet_exist = Int8 Function(Pointer<Utf8>);
|
||||
|
||||
typedef load_wallet = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Int8);
|
||||
|
||||
typedef error_string = Pointer<Utf8> Function();
|
||||
|
||||
typedef get_filename = Pointer<Utf8> Function();
|
||||
|
||||
typedef get_seed = Pointer<Utf8> Function();
|
||||
|
||||
typedef get_address = Pointer<Utf8> Function(Int32, Int32);
|
||||
|
||||
typedef get_full_balanace = Int64 Function(Int32);
|
||||
|
||||
typedef get_unlocked_balanace = Int64 Function(Int32);
|
||||
|
||||
typedef get_current_height = Int64 Function();
|
||||
|
||||
typedef get_node_height = Int64 Function();
|
||||
|
||||
typedef is_connected = Int8 Function();
|
||||
|
||||
typedef setup_node = Int8 Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, Int8, Int8, Pointer<Utf8>);
|
||||
|
||||
typedef start_refresh = Void Function();
|
||||
|
||||
typedef connect_to_node = Int8 Function();
|
||||
|
||||
typedef set_refresh_from_block_height = Void Function(Int64);
|
||||
|
||||
typedef set_recovering_from_seed = Void Function(Int8);
|
||||
|
||||
typedef store_c = Void Function(Pointer<Utf8>);
|
||||
|
||||
typedef set_password = Int8 Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
|
||||
|
||||
typedef set_listener = Void Function();
|
||||
|
||||
typedef get_syncing_height = Int64 Function();
|
||||
|
||||
typedef is_needed_to_refresh = Int8 Function();
|
||||
|
||||
typedef is_new_transaction_exist = Int8 Function();
|
||||
|
||||
typedef subaddrress_size = Int32 Function();
|
||||
|
||||
typedef subaddrress_refresh = Void Function(Int32);
|
||||
|
||||
typedef subaddress_get_all = Pointer<Int64> Function();
|
||||
|
||||
typedef subaddress_add_new = Void Function(
|
||||
Int32 accountIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef subaddress_set_label = Void Function(
|
||||
Int32 accountIndex, Int32 addressIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef account_size = Int32 Function();
|
||||
|
||||
typedef account_refresh = Void Function();
|
||||
|
||||
typedef account_get_all = Pointer<Int64> Function();
|
||||
|
||||
typedef account_add_new = Void Function(Pointer<Utf8> label);
|
||||
|
||||
typedef account_set_label = Void Function(
|
||||
Int32 accountIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef transactions_refresh = Void Function();
|
||||
|
||||
typedef get_tx_key = Pointer<Utf8>? Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef transactions_count = Int64 Function();
|
||||
|
||||
typedef transactions_get_all = Pointer<Int64> Function();
|
||||
|
||||
typedef transaction_create = Int8 Function(
|
||||
Pointer<Utf8> address,
|
||||
Pointer<Utf8> paymentId,
|
||||
Pointer<Utf8> amount,
|
||||
Int8 priorityRaw,
|
||||
Int32 subaddrAccount,
|
||||
Pointer<Utf8Box> error,
|
||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
||||
|
||||
typedef transaction_create_mult_dest = Int8 Function(
|
||||
Pointer<Pointer<Utf8>> addresses,
|
||||
Pointer<Utf8> paymentId,
|
||||
Pointer<Pointer<Utf8>> amounts,
|
||||
Int32 size,
|
||||
Int8 priorityRaw,
|
||||
Int32 subaddrAccount,
|
||||
Pointer<Utf8Box> error,
|
||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
||||
|
||||
typedef transaction_commit = Int8 Function(Pointer<PendingTransactionRaw>, Pointer<Utf8Box>);
|
||||
|
||||
typedef secret_view_key = Pointer<Utf8> Function();
|
||||
|
||||
typedef public_view_key = Pointer<Utf8> Function();
|
||||
|
||||
typedef secret_spend_key = Pointer<Utf8> Function();
|
||||
|
||||
typedef public_spend_key = Pointer<Utf8> Function();
|
||||
|
||||
typedef close_current_wallet = Void Function();
|
||||
|
||||
typedef on_startup = Void Function();
|
||||
|
||||
typedef rescan_blockchain = Void Function();
|
||||
|
||||
typedef get_subaddress_label = Pointer<Utf8> Function(
|
||||
Int32 accountIndex,
|
||||
Int32 addressIndex);
|
||||
|
||||
typedef set_trusted_daemon = Void Function(Int8 trusted);
|
||||
|
||||
typedef trusted_daemon = Int8 Function();
|
12
cw_nano/lib/api/structs/account_row.dart
Normal file
12
cw_nano/lib/api/structs/account_row.dart
Normal file
|
@ -0,0 +1,12 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class AccountRow extends Struct {
|
||||
@Int64()
|
||||
external int id;
|
||||
|
||||
external Pointer<Utf8> label;
|
||||
|
||||
String getLabel() => label.toDartString();
|
||||
int getId() => id;
|
||||
}
|
39
cw_nano/lib/api/structs/pending_transaction.dart
Normal file
39
cw_nano/lib/api/structs/pending_transaction.dart
Normal file
|
@ -0,0 +1,39 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class PendingTransactionRaw extends Struct {
|
||||
@Int64()
|
||||
external int amount;
|
||||
|
||||
@Int64()
|
||||
external int fee;
|
||||
|
||||
external Pointer<Utf8> hash;
|
||||
|
||||
external Pointer<Utf8> hex;
|
||||
|
||||
external Pointer<Utf8> txKey;
|
||||
|
||||
String getHash() => hash.toDartString();
|
||||
|
||||
String getHex() => hex.toDartString();
|
||||
|
||||
String getKey() => txKey.toDartString();
|
||||
}
|
||||
|
||||
class PendingTransactionDescription {
|
||||
PendingTransactionDescription({
|
||||
required this.amount,
|
||||
required this.fee,
|
||||
required this.hash,
|
||||
required this.hex,
|
||||
required this.txKey,
|
||||
required this.pointerAddress});
|
||||
|
||||
final int amount;
|
||||
final int fee;
|
||||
final String hash;
|
||||
final String hex;
|
||||
final String txKey;
|
||||
final int pointerAddress;
|
||||
}
|
15
cw_nano/lib/api/structs/subaddress_row.dart
Normal file
15
cw_nano/lib/api/structs/subaddress_row.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class SubaddressRow extends Struct {
|
||||
@Int64()
|
||||
external int id;
|
||||
|
||||
external Pointer<Utf8> address;
|
||||
|
||||
external Pointer<Utf8> label;
|
||||
|
||||
String getLabel() => label.toDartString();
|
||||
String getAddress() => address.toDartString();
|
||||
int getId() => id;
|
||||
}
|
41
cw_nano/lib/api/structs/transaction_info_row.dart
Normal file
41
cw_nano/lib/api/structs/transaction_info_row.dart
Normal file
|
@ -0,0 +1,41 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class TransactionInfoRow extends Struct {
|
||||
@Uint64()
|
||||
external int amount;
|
||||
|
||||
@Uint64()
|
||||
external int fee;
|
||||
|
||||
@Uint64()
|
||||
external int blockHeight;
|
||||
|
||||
@Uint64()
|
||||
external int confirmations;
|
||||
|
||||
@Uint32()
|
||||
external int subaddrAccount;
|
||||
|
||||
@Int8()
|
||||
external int direction;
|
||||
|
||||
@Int8()
|
||||
external int isPending;
|
||||
|
||||
@Uint32()
|
||||
external int subaddrIndex;
|
||||
|
||||
external Pointer<Utf8> hash;
|
||||
|
||||
external Pointer<Utf8> paymentId;
|
||||
|
||||
@Int64()
|
||||
external int datetime;
|
||||
|
||||
int getDatetime() => datetime;
|
||||
int getAmount() => amount >= 0 ? amount : amount * -1;
|
||||
bool getIsPending() => isPending != 0;
|
||||
String getHash() => hash.toDartString();
|
||||
String getPaymentId() => paymentId.toDartString();
|
||||
}
|
8
cw_nano/lib/api/structs/ut8_box.dart
Normal file
8
cw_nano/lib/api/structs/ut8_box.dart
Normal file
|
@ -0,0 +1,8 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
class Utf8Box extends Struct {
|
||||
external Pointer<Utf8> value;
|
||||
|
||||
String getValue() => value.toDartString();
|
||||
}
|
97
cw_nano/lib/api/subaddress_list.dart
Normal file
97
cw_nano/lib/api/subaddress_list.dart
Normal file
|
@ -0,0 +1,97 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_monero/api/signatures.dart';
|
||||
import 'package:cw_monero/api/types.dart';
|
||||
import 'package:cw_monero/api/monero_api.dart';
|
||||
import 'package:cw_monero/api/structs/subaddress_row.dart';
|
||||
import 'package:cw_monero/api/wallet.dart';
|
||||
|
||||
final subaddressSizeNative = moneroApi
|
||||
.lookup<NativeFunction<subaddrress_size>>('subaddrress_size')
|
||||
.asFunction<SubaddressSize>();
|
||||
|
||||
final subaddressRefreshNative = moneroApi
|
||||
.lookup<NativeFunction<subaddrress_refresh>>('subaddress_refresh')
|
||||
.asFunction<SubaddressRefresh>();
|
||||
|
||||
final subaddrressGetAllNative = moneroApi
|
||||
.lookup<NativeFunction<subaddress_get_all>>('subaddrress_get_all')
|
||||
.asFunction<SubaddressGetAll>();
|
||||
|
||||
final subaddrressAddNewNative = moneroApi
|
||||
.lookup<NativeFunction<subaddress_add_new>>('subaddress_add_row')
|
||||
.asFunction<SubaddressAddNew>();
|
||||
|
||||
final subaddrressSetLabelNative = moneroApi
|
||||
.lookup<NativeFunction<subaddress_set_label>>('subaddress_set_label')
|
||||
.asFunction<SubaddressSetLabel>();
|
||||
|
||||
bool isUpdating = false;
|
||||
|
||||
void refreshSubaddresses({required int accountIndex}) {
|
||||
try {
|
||||
isUpdating = true;
|
||||
subaddressRefreshNative(accountIndex);
|
||||
isUpdating = false;
|
||||
} catch (e) {
|
||||
isUpdating = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
List<SubaddressRow> getAllSubaddresses() {
|
||||
final size = subaddressSizeNative();
|
||||
final subaddressAddressesPointer = subaddrressGetAllNative();
|
||||
final subaddressAddresses = subaddressAddressesPointer.asTypedList(size);
|
||||
|
||||
return subaddressAddresses
|
||||
.map((addr) => Pointer<SubaddressRow>.fromAddress(addr).ref)
|
||||
.toList();
|
||||
}
|
||||
|
||||
void addSubaddressSync({required int accountIndex, required String label}) {
|
||||
final labelPointer = label.toNativeUtf8();
|
||||
subaddrressAddNewNative(accountIndex, labelPointer);
|
||||
calloc.free(labelPointer);
|
||||
}
|
||||
|
||||
void setLabelForSubaddressSync(
|
||||
{required int accountIndex, required int addressIndex, required String label}) {
|
||||
final labelPointer = label.toNativeUtf8();
|
||||
|
||||
subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer);
|
||||
calloc.free(labelPointer);
|
||||
}
|
||||
|
||||
void _addSubaddress(Map<String, dynamic> args) {
|
||||
final label = args['label'] as String;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
|
||||
addSubaddressSync(accountIndex: accountIndex, label: label);
|
||||
}
|
||||
|
||||
void _setLabelForSubaddress(Map<String, dynamic> args) {
|
||||
final label = args['label'] as String;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
final addressIndex = args['addressIndex'] as int;
|
||||
|
||||
setLabelForSubaddressSync(
|
||||
accountIndex: accountIndex, addressIndex: addressIndex, label: label);
|
||||
}
|
||||
|
||||
Future<void> addSubaddress({required int accountIndex, required String label}) async {
|
||||
await compute<Map<String, Object>, void>(
|
||||
_addSubaddress, {'accountIndex': accountIndex, 'label': label});
|
||||
await store();
|
||||
}
|
||||
|
||||
Future<void> setLabelForSubaddress(
|
||||
{required int accountIndex, required int addressIndex, required String label}) async {
|
||||
await compute<Map<String, Object>, void>(_setLabelForSubaddress, {
|
||||
'accountIndex': accountIndex,
|
||||
'addressIndex': addressIndex,
|
||||
'label': label
|
||||
});
|
||||
await store();
|
||||
}
|
234
cw_nano/lib/api/transaction_history.dart
Normal file
234
cw_nano/lib/api/transaction_history.dart
Normal file
|
@ -0,0 +1,234 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:cw_monero/api/convert_utf8_to_string.dart';
|
||||
import 'package:cw_monero/api/monero_output.dart';
|
||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_monero/api/signatures.dart';
|
||||
import 'package:cw_monero/api/types.dart';
|
||||
import 'package:cw_monero/api/monero_api.dart';
|
||||
import 'package:cw_monero/api/structs/transaction_info_row.dart';
|
||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart';
|
||||
|
||||
final transactionsRefreshNative = moneroApi
|
||||
.lookup<NativeFunction<transactions_refresh>>('transactions_refresh')
|
||||
.asFunction<TransactionsRefresh>();
|
||||
|
||||
final transactionsCountNative = moneroApi
|
||||
.lookup<NativeFunction<transactions_count>>('transactions_count')
|
||||
.asFunction<TransactionsCount>();
|
||||
|
||||
final transactionsGetAllNative = moneroApi
|
||||
.lookup<NativeFunction<transactions_get_all>>('transactions_get_all')
|
||||
.asFunction<TransactionsGetAll>();
|
||||
|
||||
final transactionCreateNative = moneroApi
|
||||
.lookup<NativeFunction<transaction_create>>('transaction_create')
|
||||
.asFunction<TransactionCreate>();
|
||||
|
||||
final transactionCreateMultDestNative = moneroApi
|
||||
.lookup<NativeFunction<transaction_create_mult_dest>>('transaction_create_mult_dest')
|
||||
.asFunction<TransactionCreateMultDest>();
|
||||
|
||||
final transactionCommitNative = moneroApi
|
||||
.lookup<NativeFunction<transaction_commit>>('transaction_commit')
|
||||
.asFunction<TransactionCommit>();
|
||||
|
||||
final getTxKeyNative = moneroApi
|
||||
.lookup<NativeFunction<get_tx_key>>('get_tx_key')
|
||||
.asFunction<GetTxKey>();
|
||||
|
||||
String getTxKey(String txId) {
|
||||
final txIdPointer = txId.toNativeUtf8();
|
||||
final keyPointer = getTxKeyNative(txIdPointer);
|
||||
|
||||
calloc.free(txIdPointer);
|
||||
|
||||
if (keyPointer != null) {
|
||||
return convertUTF8ToString(pointer: keyPointer);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
void refreshTransactions() => transactionsRefreshNative();
|
||||
|
||||
int countOfTransactions() => transactionsCountNative();
|
||||
|
||||
List<TransactionInfoRow> getAllTransations() {
|
||||
final size = transactionsCountNative();
|
||||
final transactionsPointer = transactionsGetAllNative();
|
||||
final transactionsAddresses = transactionsPointer.asTypedList(size);
|
||||
|
||||
return transactionsAddresses
|
||||
.map((addr) => Pointer<TransactionInfoRow>.fromAddress(addr).ref)
|
||||
.toList();
|
||||
}
|
||||
|
||||
PendingTransactionDescription createTransactionSync(
|
||||
{required String address,
|
||||
required String paymentId,
|
||||
required int priorityRaw,
|
||||
String? amount,
|
||||
int accountIndex = 0}) {
|
||||
final addressPointer = address.toNativeUtf8();
|
||||
final paymentIdPointer = paymentId.toNativeUtf8();
|
||||
final amountPointer = amount != null ? amount.toNativeUtf8() : nullptr;
|
||||
final errorMessagePointer = calloc<Utf8Box>();
|
||||
final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
|
||||
final created = transactionCreateNative(
|
||||
addressPointer,
|
||||
paymentIdPointer,
|
||||
amountPointer,
|
||||
priorityRaw,
|
||||
accountIndex,
|
||||
errorMessagePointer,
|
||||
pendingTransactionRawPointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(addressPointer);
|
||||
calloc.free(paymentIdPointer);
|
||||
|
||||
if (amountPointer != nullptr) {
|
||||
calloc.free(amountPointer);
|
||||
}
|
||||
|
||||
if (!created) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
calloc.free(errorMessagePointer);
|
||||
throw CreationTransactionException(message: message);
|
||||
}
|
||||
|
||||
return PendingTransactionDescription(
|
||||
amount: pendingTransactionRawPointer.ref.amount,
|
||||
fee: pendingTransactionRawPointer.ref.fee,
|
||||
hash: pendingTransactionRawPointer.ref.getHash(),
|
||||
hex: pendingTransactionRawPointer.ref.getHex(),
|
||||
txKey: pendingTransactionRawPointer.ref.getKey(),
|
||||
pointerAddress: pendingTransactionRawPointer.address);
|
||||
}
|
||||
|
||||
PendingTransactionDescription createTransactionMultDestSync(
|
||||
{required List<MoneroOutput> outputs,
|
||||
required String paymentId,
|
||||
required int priorityRaw,
|
||||
int accountIndex = 0}) {
|
||||
final int size = outputs.length;
|
||||
final List<Pointer<Utf8>> addressesPointers = outputs.map((output) =>
|
||||
output.address.toNativeUtf8()).toList();
|
||||
final Pointer<Pointer<Utf8>> addressesPointerPointer = calloc(size);
|
||||
final List<Pointer<Utf8>> amountsPointers = outputs.map((output) =>
|
||||
output.amount.toNativeUtf8()).toList();
|
||||
final Pointer<Pointer<Utf8>> amountsPointerPointer = calloc(size);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
addressesPointerPointer[i] = addressesPointers[i];
|
||||
amountsPointerPointer[i] = amountsPointers[i];
|
||||
}
|
||||
|
||||
final paymentIdPointer = paymentId.toNativeUtf8();
|
||||
final errorMessagePointer = calloc<Utf8Box>();
|
||||
final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
|
||||
final created = transactionCreateMultDestNative(
|
||||
addressesPointerPointer,
|
||||
paymentIdPointer,
|
||||
amountsPointerPointer,
|
||||
size,
|
||||
priorityRaw,
|
||||
accountIndex,
|
||||
errorMessagePointer,
|
||||
pendingTransactionRawPointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(addressesPointerPointer);
|
||||
calloc.free(amountsPointerPointer);
|
||||
|
||||
addressesPointers.forEach((element) => calloc.free(element));
|
||||
amountsPointers.forEach((element) => calloc.free(element));
|
||||
|
||||
calloc.free(paymentIdPointer);
|
||||
|
||||
if (!created) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
calloc.free(errorMessagePointer);
|
||||
throw CreationTransactionException(message: message);
|
||||
}
|
||||
|
||||
return PendingTransactionDescription(
|
||||
amount: pendingTransactionRawPointer.ref.amount,
|
||||
fee: pendingTransactionRawPointer.ref.fee,
|
||||
hash: pendingTransactionRawPointer.ref.getHash(),
|
||||
hex: pendingTransactionRawPointer.ref.getHex(),
|
||||
txKey: pendingTransactionRawPointer.ref.getKey(),
|
||||
pointerAddress: pendingTransactionRawPointer.address);
|
||||
}
|
||||
|
||||
void commitTransactionFromPointerAddress({required int address}) => commitTransaction(
|
||||
transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address));
|
||||
|
||||
void commitTransaction({required Pointer<PendingTransactionRaw> transactionPointer}) {
|
||||
final errorMessagePointer = calloc<Utf8Box>();
|
||||
final isCommited =
|
||||
transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
|
||||
|
||||
if (!isCommited) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
calloc.free(errorMessagePointer);
|
||||
throw CreationTransactionException(message: message);
|
||||
}
|
||||
}
|
||||
|
||||
PendingTransactionDescription _createTransactionSync(Map args) {
|
||||
final address = args['address'] as String;
|
||||
final paymentId = args['paymentId'] as String;
|
||||
final amount = args['amount'] as String?;
|
||||
final priorityRaw = args['priorityRaw'] as int;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
|
||||
return createTransactionSync(
|
||||
address: address,
|
||||
paymentId: paymentId,
|
||||
amount: amount,
|
||||
priorityRaw: priorityRaw,
|
||||
accountIndex: accountIndex);
|
||||
}
|
||||
|
||||
PendingTransactionDescription _createTransactionMultDestSync(Map args) {
|
||||
final outputs = args['outputs'] as List<MoneroOutput>;
|
||||
final paymentId = args['paymentId'] as String;
|
||||
final priorityRaw = args['priorityRaw'] as int;
|
||||
final accountIndex = args['accountIndex'] as int;
|
||||
|
||||
return createTransactionMultDestSync(
|
||||
outputs: outputs,
|
||||
paymentId: paymentId,
|
||||
priorityRaw: priorityRaw,
|
||||
accountIndex: accountIndex);
|
||||
}
|
||||
|
||||
Future<PendingTransactionDescription> createTransaction(
|
||||
{required String address,
|
||||
required int priorityRaw,
|
||||
String? amount,
|
||||
String paymentId = '',
|
||||
int accountIndex = 0}) =>
|
||||
compute(_createTransactionSync, {
|
||||
'address': address,
|
||||
'paymentId': paymentId,
|
||||
'amount': amount,
|
||||
'priorityRaw': priorityRaw,
|
||||
'accountIndex': accountIndex
|
||||
});
|
||||
|
||||
Future<PendingTransactionDescription> createTransactionMultDest(
|
||||
{required List<MoneroOutput> outputs,
|
||||
required int priorityRaw,
|
||||
String paymentId = '',
|
||||
int accountIndex = 0}) =>
|
||||
compute(_createTransactionMultDestSync, {
|
||||
'outputs': outputs,
|
||||
'paymentId': paymentId,
|
||||
'priorityRaw': priorityRaw,
|
||||
'accountIndex': accountIndex
|
||||
});
|
130
cw_nano/lib/api/types.dart
Normal file
130
cw_nano/lib/api/types.dart
Normal file
|
@ -0,0 +1,130 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
typedef CreateWallet = int Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, Pointer<Utf8>);
|
||||
|
||||
typedef RestoreWalletFromSeed = int Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
|
||||
|
||||
typedef RestoreWalletFromKeys = int Function(Pointer<Utf8>, Pointer<Utf8>,
|
||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
|
||||
|
||||
typedef IsWalletExist = int Function(Pointer<Utf8>);
|
||||
|
||||
typedef LoadWallet = int Function(Pointer<Utf8>, Pointer<Utf8>, int);
|
||||
|
||||
typedef ErrorString = Pointer<Utf8> Function();
|
||||
|
||||
typedef GetFilename = Pointer<Utf8> Function();
|
||||
|
||||
typedef GetSeed = Pointer<Utf8> Function();
|
||||
|
||||
typedef GetAddress = Pointer<Utf8> Function(int, int);
|
||||
|
||||
typedef GetFullBalance = int Function(int);
|
||||
|
||||
typedef GetUnlockedBalance = int Function(int);
|
||||
|
||||
typedef GetCurrentHeight = int Function();
|
||||
|
||||
typedef GetNodeHeight = int Function();
|
||||
|
||||
typedef IsConnected = int Function();
|
||||
|
||||
typedef SetupNode = int Function(
|
||||
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, int, int, Pointer<Utf8>);
|
||||
|
||||
typedef StartRefresh = void Function();
|
||||
|
||||
typedef ConnectToNode = int Function();
|
||||
|
||||
typedef SetRefreshFromBlockHeight = void Function(int);
|
||||
|
||||
typedef SetRecoveringFromSeed = void Function(int);
|
||||
|
||||
typedef Store = void Function(Pointer<Utf8>);
|
||||
|
||||
typedef SetPassword = int Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
|
||||
|
||||
typedef SetListener = void Function();
|
||||
|
||||
typedef GetSyncingHeight = int Function();
|
||||
|
||||
typedef IsNeededToRefresh = int Function();
|
||||
|
||||
typedef IsNewTransactionExist = int Function();
|
||||
|
||||
typedef SubaddressSize = int Function();
|
||||
|
||||
typedef SubaddressRefresh = void Function(int);
|
||||
|
||||
typedef SubaddressGetAll = Pointer<Int64> Function();
|
||||
|
||||
typedef SubaddressAddNew = void Function(int accountIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef SubaddressSetLabel = void Function(
|
||||
int accountIndex, int addressIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef AccountSize = int Function();
|
||||
|
||||
typedef AccountRefresh = void Function();
|
||||
|
||||
typedef AccountGetAll = Pointer<Int64> Function();
|
||||
|
||||
typedef AccountAddNew = void Function(Pointer<Utf8> label);
|
||||
|
||||
typedef AccountSetLabel = void Function(int accountIndex, Pointer<Utf8> label);
|
||||
|
||||
typedef TransactionsRefresh = void Function();
|
||||
|
||||
typedef GetTxKey = Pointer<Utf8>? Function(Pointer<Utf8> txId);
|
||||
|
||||
typedef TransactionsCount = int Function();
|
||||
|
||||
typedef TransactionsGetAll = Pointer<Int64> Function();
|
||||
|
||||
typedef TransactionCreate = int Function(
|
||||
Pointer<Utf8> address,
|
||||
Pointer<Utf8> paymentId,
|
||||
Pointer<Utf8> amount,
|
||||
int priorityRaw,
|
||||
int subaddrAccount,
|
||||
Pointer<Utf8Box> error,
|
||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
||||
|
||||
typedef TransactionCreateMultDest = int Function(
|
||||
Pointer<Pointer<Utf8>> addresses,
|
||||
Pointer<Utf8> paymentId,
|
||||
Pointer<Pointer<Utf8>> amounts,
|
||||
int size,
|
||||
int priorityRaw,
|
||||
int subaddrAccount,
|
||||
Pointer<Utf8Box> error,
|
||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
||||
|
||||
typedef TransactionCommit = int Function(Pointer<PendingTransactionRaw>, Pointer<Utf8Box>);
|
||||
|
||||
typedef SecretViewKey = Pointer<Utf8> Function();
|
||||
|
||||
typedef PublicViewKey = Pointer<Utf8> Function();
|
||||
|
||||
typedef SecretSpendKey = Pointer<Utf8> Function();
|
||||
|
||||
typedef PublicSpendKey = Pointer<Utf8> Function();
|
||||
|
||||
typedef CloseCurrentWallet = void Function();
|
||||
|
||||
typedef OnStartup = void Function();
|
||||
|
||||
typedef RescanBlockchainAsync = void Function();
|
||||
|
||||
typedef GetSubaddressLabel = Pointer<Utf8> Function(
|
||||
int accountIndex,
|
||||
int addressIndex);
|
||||
|
||||
typedef SetTrustedDaemon = void Function(int);
|
||||
|
||||
typedef TrustedDaemon = int Function();
|
374
cw_nano/lib/api/wallet.dart
Normal file
374
cw_nano/lib/api/wallet.dart
Normal file
|
@ -0,0 +1,374 @@
|
|||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
||||
import 'package:cw_monero/api/convert_utf8_to_string.dart';
|
||||
import 'package:cw_monero/api/signatures.dart';
|
||||
import 'package:cw_monero/api/types.dart';
|
||||
import 'package:cw_monero/api/monero_api.dart';
|
||||
import 'package:cw_monero/api/exceptions/setup_wallet_exception.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
int _boolToInt(bool value) => value ? 1 : 0;
|
||||
|
||||
final getFileNameNative = moneroApi
|
||||
.lookup<NativeFunction<get_filename>>('get_filename')
|
||||
.asFunction<GetFilename>();
|
||||
|
||||
final getSeedNative =
|
||||
moneroApi.lookup<NativeFunction<get_seed>>('seed').asFunction<GetSeed>();
|
||||
|
||||
final getAddressNative = moneroApi
|
||||
.lookup<NativeFunction<get_address>>('get_address')
|
||||
.asFunction<GetAddress>();
|
||||
|
||||
final getFullBalanceNative = moneroApi
|
||||
.lookup<NativeFunction<get_full_balanace>>('get_full_balance')
|
||||
.asFunction<GetFullBalance>();
|
||||
|
||||
final getUnlockedBalanceNative = moneroApi
|
||||
.lookup<NativeFunction<get_unlocked_balanace>>('get_unlocked_balance')
|
||||
.asFunction<GetUnlockedBalance>();
|
||||
|
||||
final getCurrentHeightNative = moneroApi
|
||||
.lookup<NativeFunction<get_current_height>>('get_current_height')
|
||||
.asFunction<GetCurrentHeight>();
|
||||
|
||||
final getNodeHeightNative = moneroApi
|
||||
.lookup<NativeFunction<get_node_height>>('get_node_height')
|
||||
.asFunction<GetNodeHeight>();
|
||||
|
||||
final isConnectedNative = moneroApi
|
||||
.lookup<NativeFunction<is_connected>>('is_connected')
|
||||
.asFunction<IsConnected>();
|
||||
|
||||
final setupNodeNative = moneroApi
|
||||
.lookup<NativeFunction<setup_node>>('setup_node')
|
||||
.asFunction<SetupNode>();
|
||||
|
||||
final startRefreshNative = moneroApi
|
||||
.lookup<NativeFunction<start_refresh>>('start_refresh')
|
||||
.asFunction<StartRefresh>();
|
||||
|
||||
final connecToNodeNative = moneroApi
|
||||
.lookup<NativeFunction<connect_to_node>>('connect_to_node')
|
||||
.asFunction<ConnectToNode>();
|
||||
|
||||
final setRefreshFromBlockHeightNative = moneroApi
|
||||
.lookup<NativeFunction<set_refresh_from_block_height>>(
|
||||
'set_refresh_from_block_height')
|
||||
.asFunction<SetRefreshFromBlockHeight>();
|
||||
|
||||
final setRecoveringFromSeedNative = moneroApi
|
||||
.lookup<NativeFunction<set_recovering_from_seed>>(
|
||||
'set_recovering_from_seed')
|
||||
.asFunction<SetRecoveringFromSeed>();
|
||||
|
||||
final storeNative =
|
||||
moneroApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
|
||||
|
||||
final setPasswordNative =
|
||||
moneroApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>();
|
||||
|
||||
final setListenerNative = moneroApi
|
||||
.lookup<NativeFunction<set_listener>>('set_listener')
|
||||
.asFunction<SetListener>();
|
||||
|
||||
final getSyncingHeightNative = moneroApi
|
||||
.lookup<NativeFunction<get_syncing_height>>('get_syncing_height')
|
||||
.asFunction<GetSyncingHeight>();
|
||||
|
||||
final isNeededToRefreshNative = moneroApi
|
||||
.lookup<NativeFunction<is_needed_to_refresh>>('is_needed_to_refresh')
|
||||
.asFunction<IsNeededToRefresh>();
|
||||
|
||||
final isNewTransactionExistNative = moneroApi
|
||||
.lookup<NativeFunction<is_new_transaction_exist>>(
|
||||
'is_new_transaction_exist')
|
||||
.asFunction<IsNewTransactionExist>();
|
||||
|
||||
final getSecretViewKeyNative = moneroApi
|
||||
.lookup<NativeFunction<secret_view_key>>('secret_view_key')
|
||||
.asFunction<SecretViewKey>();
|
||||
|
||||
final getPublicViewKeyNative = moneroApi
|
||||
.lookup<NativeFunction<public_view_key>>('public_view_key')
|
||||
.asFunction<PublicViewKey>();
|
||||
|
||||
final getSecretSpendKeyNative = moneroApi
|
||||
.lookup<NativeFunction<secret_spend_key>>('secret_spend_key')
|
||||
.asFunction<SecretSpendKey>();
|
||||
|
||||
final getPublicSpendKeyNative = moneroApi
|
||||
.lookup<NativeFunction<secret_view_key>>('public_spend_key')
|
||||
.asFunction<PublicSpendKey>();
|
||||
|
||||
final closeCurrentWalletNative = moneroApi
|
||||
.lookup<NativeFunction<close_current_wallet>>('close_current_wallet')
|
||||
.asFunction<CloseCurrentWallet>();
|
||||
|
||||
final onStartupNative = moneroApi
|
||||
.lookup<NativeFunction<on_startup>>('on_startup')
|
||||
.asFunction<OnStartup>();
|
||||
|
||||
final rescanBlockchainAsyncNative = moneroApi
|
||||
.lookup<NativeFunction<rescan_blockchain>>('rescan_blockchain')
|
||||
.asFunction<RescanBlockchainAsync>();
|
||||
|
||||
final getSubaddressLabelNative = moneroApi
|
||||
.lookup<NativeFunction<get_subaddress_label>>('get_subaddress_label')
|
||||
.asFunction<GetSubaddressLabel>();
|
||||
|
||||
final setTrustedDaemonNative = moneroApi
|
||||
.lookup<NativeFunction<set_trusted_daemon>>('set_trusted_daemon')
|
||||
.asFunction<SetTrustedDaemon>();
|
||||
|
||||
final trustedDaemonNative = moneroApi
|
||||
.lookup<NativeFunction<trusted_daemon>>('trusted_daemon')
|
||||
.asFunction<TrustedDaemon>();
|
||||
|
||||
int getSyncingHeight() => getSyncingHeightNative();
|
||||
|
||||
bool isNeededToRefresh() => isNeededToRefreshNative() != 0;
|
||||
|
||||
bool isNewTransactionExist() => isNewTransactionExistNative() != 0;
|
||||
|
||||
String getFilename() => convertUTF8ToString(pointer: getFileNameNative());
|
||||
|
||||
String getSeed() => convertUTF8ToString(pointer: getSeedNative());
|
||||
|
||||
String getAddress({int accountIndex = 0, int addressIndex = 0}) =>
|
||||
convertUTF8ToString(pointer: getAddressNative(accountIndex, addressIndex));
|
||||
|
||||
int getFullBalance({int accountIndex = 0}) =>
|
||||
getFullBalanceNative(accountIndex);
|
||||
|
||||
int getUnlockedBalance({int accountIndex = 0}) =>
|
||||
getUnlockedBalanceNative(accountIndex);
|
||||
|
||||
int getCurrentHeight() => getCurrentHeightNative();
|
||||
|
||||
int getNodeHeightSync() => getNodeHeightNative();
|
||||
|
||||
bool isConnectedSync() => isConnectedNative() != 0;
|
||||
|
||||
bool setupNodeSync(
|
||||
{required String address,
|
||||
String? login,
|
||||
String? password,
|
||||
bool useSSL = false,
|
||||
bool isLightWallet = false}) {
|
||||
final addressPointer = address.toNativeUtf8();
|
||||
Pointer<Utf8>? loginPointer;
|
||||
Pointer<Utf8>? passwordPointer;
|
||||
|
||||
if (login != null) {
|
||||
loginPointer = login.toNativeUtf8();
|
||||
}
|
||||
|
||||
if (password != null) {
|
||||
passwordPointer = password.toNativeUtf8();
|
||||
}
|
||||
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isSetupNode = setupNodeNative(
|
||||
addressPointer,
|
||||
loginPointer,
|
||||
passwordPointer,
|
||||
_boolToInt(useSSL),
|
||||
_boolToInt(isLightWallet),
|
||||
errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(addressPointer);
|
||||
|
||||
if (loginPointer != null) {
|
||||
calloc.free(loginPointer);
|
||||
}
|
||||
|
||||
if (passwordPointer != null) {
|
||||
calloc.free(passwordPointer);
|
||||
}
|
||||
|
||||
if (!isSetupNode) {
|
||||
throw SetupWalletException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
|
||||
return isSetupNode;
|
||||
}
|
||||
|
||||
void startRefreshSync() => startRefreshNative();
|
||||
|
||||
Future<bool> connectToNode() async => connecToNodeNative() != 0;
|
||||
|
||||
void setRefreshFromBlockHeight({required int height}) =>
|
||||
setRefreshFromBlockHeightNative(height);
|
||||
|
||||
void setRecoveringFromSeed({required bool isRecovery}) =>
|
||||
setRecoveringFromSeedNative(_boolToInt(isRecovery));
|
||||
|
||||
void storeSync() {
|
||||
final pathPointer = ''.toNativeUtf8();
|
||||
storeNative(pathPointer);
|
||||
calloc.free(pathPointer);
|
||||
}
|
||||
|
||||
void setPasswordSync(String password) {
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final errorMessagePointer = calloc<Utf8Box>();
|
||||
final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0;
|
||||
calloc.free(passwordPointer);
|
||||
|
||||
if (!changed) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
calloc.free(errorMessagePointer);
|
||||
throw Exception(message);
|
||||
}
|
||||
|
||||
calloc.free(errorMessagePointer);
|
||||
}
|
||||
|
||||
void closeCurrentWallet() => closeCurrentWalletNative();
|
||||
|
||||
String getSecretViewKey() =>
|
||||
convertUTF8ToString(pointer: getSecretViewKeyNative());
|
||||
|
||||
String getPublicViewKey() =>
|
||||
convertUTF8ToString(pointer: getPublicViewKeyNative());
|
||||
|
||||
String getSecretSpendKey() =>
|
||||
convertUTF8ToString(pointer: getSecretSpendKeyNative());
|
||||
|
||||
String getPublicSpendKey() =>
|
||||
convertUTF8ToString(pointer: getPublicSpendKeyNative());
|
||||
|
||||
class SyncListener {
|
||||
SyncListener(this.onNewBlock, this.onNewTransaction)
|
||||
: _cachedBlockchainHeight = 0,
|
||||
_lastKnownBlockHeight = 0,
|
||||
_initialSyncHeight = 0;
|
||||
|
||||
|
||||
void Function(int, int, double) onNewBlock;
|
||||
void Function() onNewTransaction;
|
||||
|
||||
Timer? _updateSyncInfoTimer;
|
||||
int _cachedBlockchainHeight;
|
||||
int _lastKnownBlockHeight;
|
||||
int _initialSyncHeight;
|
||||
|
||||
Future<int> getNodeHeightOrUpdate(int baseHeight) async {
|
||||
if (_cachedBlockchainHeight < baseHeight || _cachedBlockchainHeight == 0) {
|
||||
_cachedBlockchainHeight = await getNodeHeight();
|
||||
}
|
||||
|
||||
return _cachedBlockchainHeight;
|
||||
}
|
||||
|
||||
void start() {
|
||||
_cachedBlockchainHeight = 0;
|
||||
_lastKnownBlockHeight = 0;
|
||||
_initialSyncHeight = 0;
|
||||
_updateSyncInfoTimer ??=
|
||||
Timer.periodic(Duration(milliseconds: 1200), (_) async {
|
||||
if (isNewTransactionExist()) {
|
||||
onNewTransaction();
|
||||
}
|
||||
|
||||
var syncHeight = getSyncingHeight();
|
||||
|
||||
if (syncHeight <= 0) {
|
||||
syncHeight = getCurrentHeight();
|
||||
}
|
||||
|
||||
if (_initialSyncHeight <= 0) {
|
||||
_initialSyncHeight = syncHeight;
|
||||
}
|
||||
|
||||
final bchHeight = await getNodeHeightOrUpdate(syncHeight);
|
||||
|
||||
if (_lastKnownBlockHeight == syncHeight || syncHeight == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
_lastKnownBlockHeight = syncHeight;
|
||||
final track = bchHeight - _initialSyncHeight;
|
||||
final diff = track - (bchHeight - syncHeight);
|
||||
final ptc = diff <= 0 ? 0.0 : diff / track;
|
||||
final left = bchHeight - syncHeight;
|
||||
|
||||
if (syncHeight < 0 || left < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Actual new height; 2. Blocks left to finish; 3. Progress in percents;
|
||||
onNewBlock?.call(syncHeight, left, ptc);
|
||||
});
|
||||
}
|
||||
|
||||
void stop() => _updateSyncInfoTimer?.cancel();
|
||||
}
|
||||
|
||||
SyncListener setListeners(void Function(int, int, double) onNewBlock,
|
||||
void Function() onNewTransaction) {
|
||||
final listener = SyncListener(onNewBlock, onNewTransaction);
|
||||
setListenerNative();
|
||||
return listener;
|
||||
}
|
||||
|
||||
void onStartup() => onStartupNative();
|
||||
|
||||
void _storeSync(Object _) => storeSync();
|
||||
|
||||
bool _setupNodeSync(Map<String, Object?> args) {
|
||||
final address = args['address'] as String;
|
||||
final login = (args['login'] ?? '') as String;
|
||||
final password = (args['password'] ?? '') as String;
|
||||
final useSSL = args['useSSL'] as bool;
|
||||
final isLightWallet = args['isLightWallet'] as bool;
|
||||
|
||||
return setupNodeSync(
|
||||
address: address,
|
||||
login: login,
|
||||
password: password,
|
||||
useSSL: useSSL,
|
||||
isLightWallet: isLightWallet);
|
||||
}
|
||||
|
||||
bool _isConnected(Object _) => isConnectedSync();
|
||||
|
||||
int _getNodeHeight(Object _) => getNodeHeightSync();
|
||||
|
||||
void startRefresh() => startRefreshSync();
|
||||
|
||||
Future<void> setupNode(
|
||||
{required String address,
|
||||
String? login,
|
||||
String? password,
|
||||
bool useSSL = false,
|
||||
bool isLightWallet = false}) =>
|
||||
compute<Map<String, Object?>, void>(_setupNodeSync, {
|
||||
'address': address,
|
||||
'login': login ,
|
||||
'password': password,
|
||||
'useSSL': useSSL,
|
||||
'isLightWallet': isLightWallet
|
||||
});
|
||||
|
||||
Future<void> store() => compute<int, void>(_storeSync, 0);
|
||||
|
||||
Future<bool> isConnected() => compute(_isConnected, 0);
|
||||
|
||||
Future<int> getNodeHeight() => compute(_getNodeHeight, 0);
|
||||
|
||||
void rescanBlockchainAsync() => rescanBlockchainAsyncNative();
|
||||
|
||||
String getSubaddressLabel(int accountIndex, int addressIndex) {
|
||||
return convertUTF8ToString(pointer: getSubaddressLabelNative(accountIndex, addressIndex));
|
||||
}
|
||||
|
||||
Future setTrustedDaemon(bool trusted) async => setTrustedDaemonNative(_boolToInt(trusted));
|
||||
|
||||
Future<bool> trustedDaemon() async => trustedDaemonNative() != 0;
|
254
cw_nano/lib/api/wallet_manager.dart
Normal file
254
cw_nano/lib/api/wallet_manager.dart
Normal file
|
@ -0,0 +1,254 @@
|
|||
import 'dart:ffi';
|
||||
import 'package:ffi/ffi.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_monero/api/convert_utf8_to_string.dart';
|
||||
import 'package:cw_monero/api/signatures.dart';
|
||||
import 'package:cw_monero/api/types.dart';
|
||||
import 'package:cw_monero/api/monero_api.dart';
|
||||
import 'package:cw_monero/api/wallet.dart';
|
||||
import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
|
||||
import 'package:cw_monero/api/exceptions/wallet_creation_exception.dart';
|
||||
import 'package:cw_monero/api/exceptions/wallet_restore_from_keys_exception.dart';
|
||||
import 'package:cw_monero/api/exceptions/wallet_restore_from_seed_exception.dart';
|
||||
|
||||
final createWalletNative = moneroApi
|
||||
.lookup<NativeFunction<create_wallet>>('create_wallet')
|
||||
.asFunction<CreateWallet>();
|
||||
|
||||
final restoreWalletFromSeedNative = moneroApi
|
||||
.lookup<NativeFunction<restore_wallet_from_seed>>(
|
||||
'restore_wallet_from_seed')
|
||||
.asFunction<RestoreWalletFromSeed>();
|
||||
|
||||
final restoreWalletFromKeysNative = moneroApi
|
||||
.lookup<NativeFunction<restore_wallet_from_keys>>(
|
||||
'restore_wallet_from_keys')
|
||||
.asFunction<RestoreWalletFromKeys>();
|
||||
|
||||
final isWalletExistNative = moneroApi
|
||||
.lookup<NativeFunction<is_wallet_exist>>('is_wallet_exist')
|
||||
.asFunction<IsWalletExist>();
|
||||
|
||||
final loadWalletNative = moneroApi
|
||||
.lookup<NativeFunction<load_wallet>>('load_wallet')
|
||||
.asFunction<LoadWallet>();
|
||||
|
||||
final errorStringNative = moneroApi
|
||||
.lookup<NativeFunction<error_string>>('error_string')
|
||||
.asFunction<ErrorString>();
|
||||
|
||||
void createWalletSync(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String language,
|
||||
int nettype = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final languagePointer = language.toNativeUtf8();
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isWalletCreated = createWalletNative(pathPointer, passwordPointer,
|
||||
languagePointer, nettype, errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
calloc.free(languagePointer);
|
||||
|
||||
if (!isWalletCreated) {
|
||||
throw WalletCreationException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
|
||||
// setupNodeSync(address: "node.moneroworld.com:18089");
|
||||
}
|
||||
|
||||
bool isWalletExistSync({required String path}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final isExist = isWalletExistNative(pathPointer) != 0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
|
||||
return isExist;
|
||||
}
|
||||
|
||||
void restoreWalletFromSeedSync(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String seed,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final seedPointer = seed.toNativeUtf8();
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isWalletRestored = restoreWalletFromSeedNative(
|
||||
pathPointer,
|
||||
passwordPointer,
|
||||
seedPointer,
|
||||
nettype,
|
||||
restoreHeight,
|
||||
errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
calloc.free(seedPointer);
|
||||
|
||||
if (!isWalletRestored) {
|
||||
throw WalletRestoreFromSeedException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
}
|
||||
|
||||
void restoreWalletFromKeysSync(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String language,
|
||||
required String address,
|
||||
required String viewKey,
|
||||
required String spendKey,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final languagePointer = language.toNativeUtf8();
|
||||
final addressPointer = address.toNativeUtf8();
|
||||
final viewKeyPointer = viewKey.toNativeUtf8();
|
||||
final spendKeyPointer = spendKey.toNativeUtf8();
|
||||
final errorMessagePointer = ''.toNativeUtf8();
|
||||
final isWalletRestored = restoreWalletFromKeysNative(
|
||||
pathPointer,
|
||||
passwordPointer,
|
||||
languagePointer,
|
||||
addressPointer,
|
||||
viewKeyPointer,
|
||||
spendKeyPointer,
|
||||
nettype,
|
||||
restoreHeight,
|
||||
errorMessagePointer) !=
|
||||
0;
|
||||
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
calloc.free(languagePointer);
|
||||
calloc.free(addressPointer);
|
||||
calloc.free(viewKeyPointer);
|
||||
calloc.free(spendKeyPointer);
|
||||
|
||||
if (!isWalletRestored) {
|
||||
throw WalletRestoreFromKeysException(
|
||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
||||
}
|
||||
}
|
||||
|
||||
void loadWallet({
|
||||
required String path,
|
||||
required String password,
|
||||
int nettype = 0}) {
|
||||
final pathPointer = path.toNativeUtf8();
|
||||
final passwordPointer = password.toNativeUtf8();
|
||||
final loaded = loadWalletNative(pathPointer, passwordPointer, nettype) != 0;
|
||||
calloc.free(pathPointer);
|
||||
calloc.free(passwordPointer);
|
||||
|
||||
if (!loaded) {
|
||||
throw WalletOpeningException(
|
||||
message: convertUTF8ToString(pointer: errorStringNative()));
|
||||
}
|
||||
}
|
||||
|
||||
void _createWallet(Map<String, dynamic> args) {
|
||||
final path = args['path'] as String;
|
||||
final password = args['password'] as String;
|
||||
final language = args['language'] as String;
|
||||
|
||||
createWalletSync(path: path, password: password, language: language);
|
||||
}
|
||||
|
||||
void _restoreFromSeed(Map<String, dynamic> args) {
|
||||
final path = args['path'] as String;
|
||||
final password = args['password'] as String;
|
||||
final seed = args['seed'] as String;
|
||||
final restoreHeight = args['restoreHeight'] as int;
|
||||
|
||||
restoreWalletFromSeedSync(
|
||||
path: path, password: password, seed: seed, restoreHeight: restoreHeight);
|
||||
}
|
||||
|
||||
void _restoreFromKeys(Map<String, dynamic> args) {
|
||||
final path = args['path'] as String;
|
||||
final password = args['password'] as String;
|
||||
final language = args['language'] as String;
|
||||
final restoreHeight = args['restoreHeight'] as int;
|
||||
final address = args['address'] as String;
|
||||
final viewKey = args['viewKey'] as String;
|
||||
final spendKey = args['spendKey'] as String;
|
||||
|
||||
restoreWalletFromKeysSync(
|
||||
path: path,
|
||||
password: password,
|
||||
language: language,
|
||||
restoreHeight: restoreHeight,
|
||||
address: address,
|
||||
viewKey: viewKey,
|
||||
spendKey: spendKey);
|
||||
}
|
||||
|
||||
Future<void> _openWallet(Map<String, String> args) async =>
|
||||
loadWallet(path: args['path'] as String, password: args['password'] as String);
|
||||
|
||||
bool _isWalletExist(String path) => isWalletExistSync(path: path);
|
||||
|
||||
void openWallet({required String path, required String password, int nettype = 0}) async =>
|
||||
loadWallet(path: path, password: password, nettype: nettype);
|
||||
|
||||
Future<void> openWalletAsync(Map<String, String> args) async =>
|
||||
compute(_openWallet, args);
|
||||
|
||||
Future<void> createWallet(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String language,
|
||||
int nettype = 0}) async =>
|
||||
compute(_createWallet, {
|
||||
'path': path,
|
||||
'password': password,
|
||||
'language': language,
|
||||
'nettype': nettype
|
||||
});
|
||||
|
||||
Future<void> restoreFromSeed(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String seed,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) async =>
|
||||
compute<Map<String, Object>, void>(_restoreFromSeed, {
|
||||
'path': path,
|
||||
'password': password,
|
||||
'seed': seed,
|
||||
'nettype': nettype,
|
||||
'restoreHeight': restoreHeight
|
||||
});
|
||||
|
||||
Future<void> restoreFromKeys(
|
||||
{required String path,
|
||||
required String password,
|
||||
required String language,
|
||||
required String address,
|
||||
required String viewKey,
|
||||
required String spendKey,
|
||||
int nettype = 0,
|
||||
int restoreHeight = 0}) async =>
|
||||
compute<Map<String, Object>, void>(_restoreFromKeys, {
|
||||
'path': path,
|
||||
'password': password,
|
||||
'language': language,
|
||||
'address': address,
|
||||
'viewKey': viewKey,
|
||||
'spendKey': spendKey,
|
||||
'nettype': nettype,
|
||||
'restoreHeight': restoreHeight
|
||||
});
|
||||
|
||||
Future<bool> isWalletExist({required String path}) => compute(_isWalletExist, path);
|
82
cw_nano/lib/nano_account_list.dart
Normal file
82
cw_nano/lib/nano_account_list.dart
Normal file
|
@ -0,0 +1,82 @@
|
|||
import 'package:cw_core/monero_amount_format.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/account.dart';
|
||||
import 'package:cw_nano/api/account_list.dart' as account_list;
|
||||
import 'package:cw_nano/api/wallet.dart' as monero_wallet;
|
||||
|
||||
part 'nano_account_list.g.dart';
|
||||
|
||||
class NanoAccountList = NanoAccountListBase with _$NanoAccountList;
|
||||
|
||||
abstract class NanoAccountListBase with Store {
|
||||
NanoAccountListBase()
|
||||
: accounts = ObservableList<Account>(),
|
||||
_isRefreshing = false,
|
||||
_isUpdating = false {
|
||||
refresh();
|
||||
}
|
||||
|
||||
@observable
|
||||
ObservableList<Account> accounts;
|
||||
bool _isRefreshing;
|
||||
bool _isUpdating;
|
||||
|
||||
void update() async {
|
||||
if (_isUpdating) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_isUpdating = true;
|
||||
refresh();
|
||||
final accounts = getAll();
|
||||
|
||||
if (accounts.isNotEmpty) {
|
||||
this.accounts.clear();
|
||||
this.accounts.addAll(accounts);
|
||||
}
|
||||
|
||||
_isUpdating = false;
|
||||
} catch (e) {
|
||||
_isUpdating = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
List<Account> getAll() => account_list.getAllAccount().map((accountRow) {
|
||||
final accountIndex = accountRow.getId();
|
||||
final balance = monero_wallet.getFullBalance(accountIndex: accountIndex);
|
||||
|
||||
return Account(
|
||||
id: accountRow.getId(),
|
||||
label: accountRow.getLabel(),
|
||||
balance: moneroAmountToString(amount: balance),
|
||||
);
|
||||
}).toList();
|
||||
|
||||
Future<void> addAccount({required String label}) async {
|
||||
await account_list.addAccount(label: label);
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> setLabelAccount({required int accountIndex, required String label}) async {
|
||||
await account_list.setLabelForAccount(accountIndex: accountIndex, label: label);
|
||||
update();
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
if (_isRefreshing) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
_isRefreshing = true;
|
||||
account_list.refreshAccounts();
|
||||
_isRefreshing = false;
|
||||
} catch (e) {
|
||||
_isRefreshing = false;
|
||||
print(e);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,6 @@ class NanoBalance extends Balance {
|
|||
// super(moneroParseAmount(amount: formattedReceivableBalance),
|
||||
// moneroParseAmount(amount: formattedCurrentBalance));
|
||||
|
||||
|
||||
@override
|
||||
String get formattedAvailableBalance => "error";
|
||||
|
||||
|
|
28
cw_nano/lib/nano_transaction_history.dart
Normal file
28
cw_nano/lib/nano_transaction_history.dart
Normal file
|
@ -0,0 +1,28 @@
|
|||
import 'dart:core';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_nano/nano_transaction_info.dart';
|
||||
|
||||
part 'nano_transaction_history.g.dart';
|
||||
|
||||
class NanoTransactionHistory = NanoTransactionHistoryBase
|
||||
with _$NanoTransactionHistory;
|
||||
|
||||
abstract class NanoTransactionHistoryBase
|
||||
extends TransactionHistoryBase<NanoTransactionInfo> with Store {
|
||||
NanoTransactionHistoryBase() {
|
||||
transactions = ObservableMap<String, NanoTransactionInfo>();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> save() async {}
|
||||
|
||||
@override
|
||||
void addOne(NanoTransactionInfo transaction) =>
|
||||
transactions[transaction.id] = transaction;
|
||||
|
||||
@override
|
||||
void addMany(Map<String, MoneroTransactionInfo> transactions) =>
|
||||
this.transactions.addAll(transactions);
|
||||
|
||||
}
|
|
@ -3,23 +3,11 @@ import 'dart:io';
|
|||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/monero_amount_format.dart';
|
||||
import 'package:cw_monero/monero_transaction_creation_exception.dart';
|
||||
import 'package:cw_monero/monero_transaction_info.dart';
|
||||
import 'package:cw_monero/monero_wallet_addresses.dart';
|
||||
import 'package:cw_core/monero_wallet_utils.dart';
|
||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
||||
import 'package:cw_nano/nano_balance.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_monero/api/transaction_history.dart'
|
||||
as monero_transaction_history;
|
||||
import 'package:cw_monero/api/wallet.dart';
|
||||
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
|
||||
import 'package:cw_monero/api/transaction_history.dart' as transaction_history;
|
||||
import 'package:cw_monero/api/monero_output.dart';
|
||||
import 'package:cw_monero/monero_transaction_creation_credentials.dart';
|
||||
import 'package:cw_monero/pending_monero_transaction.dart';
|
||||
import 'package:cw_core/monero_wallet_keys.dart';
|
||||
import 'package:cw_core/monero_balance.dart';
|
||||
import 'package:cw_monero/monero_transaction_history.dart';
|
||||
import 'package:cw_core/account.dart';
|
||||
import 'package:cw_core/pending_transaction.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
|
@ -35,33 +23,30 @@ const moneroBlockSize = 1000;
|
|||
|
||||
class NanoWallet = NanoWalletBase with _$NanoWallet;
|
||||
|
||||
abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
||||
MoneroTransactionHistory, MoneroTransactionInfo> with Store {
|
||||
abstract class NanoWalletBase
|
||||
extends WalletBase<NanoBalance, NanoTransactionHistory, NanoTransactionInfo> with Store {
|
||||
NanoWalletBase({required WalletInfo walletInfo})
|
||||
: balance = ObservableMap<CryptoCurrency, MoneroBalance>.of({
|
||||
CryptoCurrency.xmr: MoneroBalance(
|
||||
fullBalance: monero_wallet.getFullBalance(accountIndex: 0),
|
||||
unlockedBalance: monero_wallet.getFullBalance(accountIndex: 0))
|
||||
}),
|
||||
: balance = ObservableMap<CryptoCurrency, NanoBalance>.of({
|
||||
CryptoCurrency.nano: NanoBalance(
|
||||
currentBalance: nano_wallet.getFullBalance(accountIndex: 0),
|
||||
receivableBalance: nano_wallet.getFullBalance(accountIndex: 0))
|
||||
}),
|
||||
_isTransactionUpdating = false,
|
||||
_hasSyncAfterStartup = false,
|
||||
walletAddresses = NanoWalletAddresses(walletInfo),
|
||||
syncStatus = NotConnectedSyncStatus(),
|
||||
super(walletInfo) {
|
||||
transactionHistory = MoneroTransactionHistory();
|
||||
_onAccountChangeReaction = reaction((_) => walletAddresses.account,
|
||||
(Account? account) {
|
||||
_onAccountChangeReaction = reaction((_) => walletAddresses.account, (Account? account) {
|
||||
if (account == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(
|
||||
<CryptoCurrency, MoneroBalance>{
|
||||
currency: MoneroBalance(
|
||||
balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(<CryptoCurrency, MoneroBalance>{
|
||||
currency: MoneroBalance(
|
||||
fullBalance: monero_wallet.getFullBalance(accountIndex: account.id),
|
||||
unlockedBalance:
|
||||
monero_wallet.getUnlockedBalance(accountIndex: account.id))
|
||||
});
|
||||
unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: account.id))
|
||||
});
|
||||
walletAddresses.updateSubaddressList(accountIndex: account.id);
|
||||
});
|
||||
}
|
||||
|
@ -97,12 +82,12 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
|
||||
Future<void> init() async {
|
||||
await walletAddresses.init();
|
||||
balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(
|
||||
<CryptoCurrency, MoneroBalance>{
|
||||
currency: MoneroBalance(
|
||||
fullBalance: monero_wallet.getFullBalance(accountIndex: walletAddresses.account!.id),
|
||||
unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id))
|
||||
});
|
||||
balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(<CryptoCurrency, MoneroBalance>{
|
||||
currency: MoneroBalance(
|
||||
fullBalance: monero_wallet.getFullBalance(accountIndex: walletAddresses.account!.id),
|
||||
unlockedBalance:
|
||||
monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id))
|
||||
});
|
||||
_setListeners();
|
||||
await updateTransactions();
|
||||
|
||||
|
@ -110,8 +95,7 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
monero_wallet.setRecoveringFromSeed(isRecovery: walletInfo.isRecovery);
|
||||
|
||||
if (monero_wallet.getCurrentHeight() <= 1) {
|
||||
monero_wallet.setRefreshFromBlockHeight(
|
||||
height: walletInfo.restoreHeight);
|
||||
monero_wallet.setRefreshFromBlockHeight(height: walletInfo.restoreHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,6 +103,7 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
// Duration(seconds: _autoSaveInterval),
|
||||
// (_) async => await save());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void>? updateBalance() => null;
|
||||
|
||||
|
@ -134,9 +119,7 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
try {
|
||||
syncStatus = ConnectingSyncStatus();
|
||||
await monero_wallet.setupNode(
|
||||
address: node.uri.toString(),
|
||||
useSSL: node.isSSL,
|
||||
isLightWallet: false);
|
||||
address: node.uri.toString(), useSSL: node.isSSL, isLightWallet: false);
|
||||
|
||||
monero_wallet.setTrustedDaemon(node.trusted);
|
||||
syncStatus = ConnectedSyncStatus();
|
||||
|
@ -166,96 +149,14 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
|
||||
@override
|
||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||
final _credentials = credentials as MoneroTransactionCreationCredentials;
|
||||
final outputs = _credentials.outputs;
|
||||
final hasMultiDestination = outputs.length > 1;
|
||||
final unlockedBalance =
|
||||
monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id);
|
||||
|
||||
PendingTransactionDescription pendingTransactionDescription;
|
||||
|
||||
if (!(syncStatus is SyncedSyncStatus)) {
|
||||
throw MoneroTransactionCreationException('The wallet is not synced.');
|
||||
}
|
||||
|
||||
if (hasMultiDestination) {
|
||||
if (outputs.any((item) => item.sendAll
|
||||
|| (item.formattedCryptoAmount ?? 0) <= 0)) {
|
||||
throw MoneroTransactionCreationException('You do not have enough XMR to send this amount.');
|
||||
}
|
||||
|
||||
final int totalAmount = outputs.fold(0, (acc, value) =>
|
||||
acc + (value.formattedCryptoAmount ?? 0));
|
||||
|
||||
if (unlockedBalance < totalAmount) {
|
||||
throw MoneroTransactionCreationException('You do not have enough XMR to send this amount.');
|
||||
}
|
||||
|
||||
final moneroOutputs = outputs.map((output) {
|
||||
final outputAddress = output.isParsedAddress
|
||||
? output.extractedAddress
|
||||
: output.address;
|
||||
|
||||
return MoneroOutput(
|
||||
address: outputAddress!,
|
||||
amount: output.cryptoAmount!.replaceAll(',', '.'));
|
||||
}).toList();
|
||||
|
||||
pendingTransactionDescription =
|
||||
await transaction_history.createTransactionMultDest(
|
||||
outputs: moneroOutputs,
|
||||
priorityRaw: _credentials.priority.serialize(),
|
||||
accountIndex: walletAddresses.account!.id);
|
||||
} else {
|
||||
final output = outputs.first;
|
||||
final address = output.isParsedAddress
|
||||
? output.extractedAddress
|
||||
: output.address;
|
||||
final amount = output.sendAll
|
||||
? null
|
||||
: output.cryptoAmount!.replaceAll(',', '.');
|
||||
final formattedAmount = output.sendAll
|
||||
? null
|
||||
: output.formattedCryptoAmount;
|
||||
|
||||
if ((formattedAmount != null && unlockedBalance < formattedAmount) ||
|
||||
(formattedAmount == null && unlockedBalance <= 0)) {
|
||||
final formattedBalance = moneroAmountToString(amount: unlockedBalance);
|
||||
|
||||
throw MoneroTransactionCreationException(
|
||||
'You do not have enough unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${output.cryptoAmount}.');
|
||||
}
|
||||
|
||||
pendingTransactionDescription =
|
||||
await transaction_history.createTransaction(
|
||||
address: address!,
|
||||
amount: amount,
|
||||
priorityRaw: _credentials.priority.serialize(),
|
||||
accountIndex: walletAddresses.account!.id);
|
||||
}
|
||||
|
||||
return PendingMoneroTransaction(pendingTransactionDescription);
|
||||
// final _credentials = credentials as MoneroTransactionCreationCredentials;
|
||||
// return null;
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
|
||||
// FIXME: hardcoded value;
|
||||
|
||||
if (priority is MoneroTransactionPriority) {
|
||||
switch (priority) {
|
||||
case MoneroTransactionPriority.slow:
|
||||
return 24590000;
|
||||
case MoneroTransactionPriority.automatic:
|
||||
return 123050000;
|
||||
case MoneroTransactionPriority.medium:
|
||||
return 245029999;
|
||||
case MoneroTransactionPriority.fast:
|
||||
return 614530000;
|
||||
case MoneroTransactionPriority.fastest:
|
||||
return 26021600000;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -272,10 +173,8 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
|
||||
try {
|
||||
// -- rename the waller folder --
|
||||
final currentWalletDir =
|
||||
Directory(await pathForWalletDir(name: name, type: type));
|
||||
final newWalletDirPath =
|
||||
await pathForWalletDir(name: newWalletName, type: type);
|
||||
final currentWalletDir = Directory(await pathForWalletDir(name: name, type: type));
|
||||
final newWalletDirPath = await pathForWalletDir(name: newWalletName, type: type);
|
||||
await currentWalletDir.rename(newWalletDirPath);
|
||||
|
||||
// -- use new waller folder to rename files with old names still --
|
||||
|
@ -285,8 +184,7 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
final currentKeysFile = File('$renamedWalletPath.keys');
|
||||
final currentAddressListFile = File('$renamedWalletPath.address.txt');
|
||||
|
||||
final newWalletPath =
|
||||
await pathForWallet(name: newWalletName, type: type);
|
||||
final newWalletPath = await pathForWallet(name: newWalletName, type: type);
|
||||
|
||||
if (currentCacheFile.existsSync()) {
|
||||
await currentCacheFile.rename(newWalletPath);
|
||||
|
@ -304,8 +202,7 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
final currentKeysFile = File('$currentWalletPath.keys');
|
||||
final currentAddressListFile = File('$currentWalletPath.address.txt');
|
||||
|
||||
final newWalletPath =
|
||||
await pathForWallet(name: newWalletName, type: type);
|
||||
final newWalletPath = await pathForWallet(name: newWalletName, type: type);
|
||||
|
||||
// Copies current wallet files into new wallet name's dir and files
|
||||
if (currentCacheFile.existsSync()) {
|
||||
|
@ -352,16 +249,14 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
}
|
||||
|
||||
String getTransactionAddress(int accountIndex, int addressIndex) =>
|
||||
monero_wallet.getAddress(
|
||||
accountIndex: accountIndex,
|
||||
addressIndex: addressIndex);
|
||||
monero_wallet.getAddress(accountIndex: accountIndex, addressIndex: addressIndex);
|
||||
|
||||
@override
|
||||
Future<Map<String, MoneroTransactionInfo>> fetchTransactions() async {
|
||||
monero_transaction_history.refreshTransactions();
|
||||
return _getAllTransactions(null).fold<Map<String, MoneroTransactionInfo>>(
|
||||
<String, MoneroTransactionInfo>{},
|
||||
(Map<String, MoneroTransactionInfo> acc, MoneroTransactionInfo tx) {
|
||||
return _getAllTransactions(null)
|
||||
.fold<Map<String, MoneroTransactionInfo>>(<String, MoneroTransactionInfo>{},
|
||||
(Map<String, MoneroTransactionInfo> acc, MoneroTransactionInfo tx) {
|
||||
acc[tx.id] = tx;
|
||||
return acc;
|
||||
});
|
||||
|
@ -388,11 +283,10 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
return monero_wallet.getSubaddressLabel(accountIndex, addressIndex);
|
||||
}
|
||||
|
||||
List<MoneroTransactionInfo> _getAllTransactions(dynamic _) =>
|
||||
monero_transaction_history
|
||||
.getAllTransations()
|
||||
.map((row) => MoneroTransactionInfo.fromRow(row))
|
||||
.toList();
|
||||
List<MoneroTransactionInfo> _getAllTransactions(dynamic _) => monero_transaction_history
|
||||
.getAllTransations()
|
||||
.map((row) => MoneroTransactionInfo.fromRow(row))
|
||||
.toList();
|
||||
|
||||
void _setListeners() {
|
||||
_listener?.stop();
|
||||
|
@ -414,8 +308,7 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
}
|
||||
|
||||
int _getHeightDistance(DateTime date) {
|
||||
final distance =
|
||||
DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch;
|
||||
final distance = DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch;
|
||||
final daysTmp = (distance / 86400).round();
|
||||
final days = daysTmp < 1 ? 1 : daysTmp;
|
||||
|
||||
|
@ -439,16 +332,13 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
|
||||
if (balance[currency]!.fullBalance != fullBalance ||
|
||||
balance[currency]!.unlockedBalance != unlockedBalance) {
|
||||
balance[currency] = MoneroBalance(
|
||||
fullBalance: fullBalance, unlockedBalance: unlockedBalance);
|
||||
balance[currency] = MoneroBalance(fullBalance: fullBalance, unlockedBalance: unlockedBalance);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _askForUpdateTransactionHistory() async =>
|
||||
await updateTransactions();
|
||||
Future<void> _askForUpdateTransactionHistory() async => await updateTransactions();
|
||||
|
||||
int _getFullBalance() =>
|
||||
monero_wallet.getFullBalance(accountIndex: walletAddresses.account!.id);
|
||||
int _getFullBalance() => monero_wallet.getFullBalance(accountIndex: walletAddresses.account!.id);
|
||||
|
||||
int _getUnlockedBalance() =>
|
||||
monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id);
|
||||
|
@ -468,9 +358,9 @@ abstract class NanoWalletBase extends WalletBase<MoneroBalance,
|
|||
syncStatus = SyncedSyncStatus();
|
||||
|
||||
if (!_hasSyncAfterStartup) {
|
||||
_hasSyncAfterStartup = true;
|
||||
await save();
|
||||
}
|
||||
_hasSyncAfterStartup = true;
|
||||
await save();
|
||||
}
|
||||
|
||||
if (walletInfo.isRecovery) {
|
||||
await setAsRecovered();
|
||||
|
|
45
cw_nano/lib/nano_wallet_addresses.dart
Normal file
45
cw_nano/lib/nano_wallet_addresses.dart
Normal file
|
@ -0,0 +1,45 @@
|
|||
import 'package:cw_core/wallet_addresses.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/account.dart';
|
||||
import 'package:cw_nano/nano_account_list.dart';
|
||||
import 'package:cw_core/subaddress.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
part 'monero_wallet_addresses.g.dart';
|
||||
|
||||
class NanoWalletAddresses = NanoWalletAddressesBase
|
||||
with _$NanoWalletAddresses;
|
||||
|
||||
abstract class NanoWalletAddressesBase extends WalletAddresses with Store {
|
||||
NanoWalletAddressesBase(WalletInfo walletInfo)
|
||||
: accountList = NanoAccountList(),
|
||||
address = '',
|
||||
super(walletInfo);
|
||||
|
||||
@override
|
||||
@observable
|
||||
String address;
|
||||
|
||||
@observable
|
||||
Account? account;
|
||||
|
||||
|
||||
NanoAccountList accountList;
|
||||
|
||||
@override
|
||||
Future<void> init() async {
|
||||
accountList.update();
|
||||
account = accountList.accounts.first;
|
||||
}
|
||||
|
||||
bool validate() {
|
||||
accountList.update();
|
||||
final accountListLength = accountList.accounts.length ?? 0;
|
||||
|
||||
if (accountListLength <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
26
cw_nano/lib/nano_wallet_creation_credentials.dart
Normal file
26
cw_nano/lib/nano_wallet_creation_credentials.dart
Normal file
|
@ -0,0 +1,26 @@
|
|||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
|
||||
class NanoNewWalletCredentials extends WalletCredentials {
|
||||
NanoNewWalletCredentials({required String name, WalletInfo? walletInfo})
|
||||
: super(name: name, walletInfo: walletInfo);
|
||||
}
|
||||
|
||||
class NanoRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||
NanoRestoreWalletFromSeedCredentials(
|
||||
{required String name,
|
||||
required String password,
|
||||
required this.mnemonic,
|
||||
WalletInfo? walletInfo})
|
||||
: super(name: name, password: password, walletInfo: walletInfo);
|
||||
|
||||
final String mnemonic;
|
||||
}
|
||||
|
||||
class NanoRestoreWalletFromWIFCredentials extends WalletCredentials {
|
||||
NanoRestoreWalletFromWIFCredentials(
|
||||
{required String name, required String password, required this.wif, WalletInfo? walletInfo})
|
||||
: super(name: name, password: password, walletInfo: walletInfo);
|
||||
|
||||
final String wif;
|
||||
}
|
103
cw_nano/lib/nano_wallet_service.dart
Normal file
103
cw_nano/lib/nano_wallet_service.dart
Normal file
|
@ -0,0 +1,103 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cw_core/pathForWallet.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_nano/nano_mnemonics.dart';
|
||||
import 'package:cw_nano/nano_wallet.dart';
|
||||
import 'package:cw_nano/nano_wallet_creation_credentials.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
|
||||
|
||||
|
||||
class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||
NanoRestoreWalletFromSeedCredentials, NanoRestoreWalletFromWIFCredentials> {
|
||||
NanoWalletService(this.walletInfoSource);
|
||||
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
@override
|
||||
Future<NanoWallet> create(NanoNewWalletCredentials credentials) async {
|
||||
final mnemonic = bip39.generateMnemonic();
|
||||
final wallet = NanoWallet(
|
||||
walletInfo: credentials.walletInfo!,
|
||||
mnemonic: mnemonic,
|
||||
password: credentials.password!,
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
await wallet.save();
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@override
|
||||
WalletType getType() => WalletType.ethereum;
|
||||
|
||||
@override
|
||||
Future<bool> isWalletExit(String name) async =>
|
||||
File(await pathForWallet(name: name, type: getType())).existsSync();
|
||||
|
||||
@override
|
||||
Future<NanoWallet> openWallet(String name, String password) async {
|
||||
final walletInfo =
|
||||
walletInfoSource.values.firstWhere((info) => info.id == WalletBase.idFor(name, getType()));
|
||||
final wallet = await NanoWalletBase.open(
|
||||
name: name,
|
||||
password: password,
|
||||
walletInfo: walletInfo,
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
await wallet.save();
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> remove(String wallet) async =>
|
||||
File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
|
||||
|
||||
@override
|
||||
Future<NanoWallet> restoreFromKeys(credentials) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<NanoWallet> restoreFromSeed(
|
||||
NanoRestoreWalletFromSeedCredentials credentials) async {
|
||||
// if (!bip39.validateMnemonic(credentials.mnemonic)) {
|
||||
// throw EthereumMnemonicIsIncorrectException();
|
||||
// }
|
||||
|
||||
final wallet = await NanoWallet(
|
||||
// password: credentials.password!,
|
||||
// mnemonic: credentials.mnemonic,
|
||||
walletInfo: credentials.walletInfo!,
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
await wallet.save();
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> rename(String currentName, String password, String newName) async {
|
||||
final currentWalletInfo = walletInfoSource.values
|
||||
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||
final currentWallet = await NanoWalletBase.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);
|
||||
}
|
||||
}
|
|
@ -1,121 +1,105 @@
|
|||
part of 'nano.dart';
|
||||
|
||||
|
||||
// class CWMoneroAccountList extends MoneroAccountList {
|
||||
// CWMoneroAccountList(this._wallet);
|
||||
// final Object _wallet;
|
||||
|
||||
// @override
|
||||
// @computed
|
||||
// ObservableList<Account> get accounts {
|
||||
// final moneroWallet = _wallet as MoneroWallet;
|
||||
// final accounts = moneroWallet.walletAddresses.accountList
|
||||
// .accounts
|
||||
// .map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
|
||||
// .toList();
|
||||
// return ObservableList<Account>.of(accounts);
|
||||
// }
|
||||
|
||||
// @override
|
||||
// void update(Object wallet) {
|
||||
// final moneroWallet = wallet as MoneroWallet;
|
||||
// moneroWallet.walletAddresses.accountList.update();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// void refresh(Object wallet) {
|
||||
// final moneroWallet = wallet as MoneroWallet;
|
||||
// moneroWallet.walletAddresses.accountList.refresh();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// List<Account> getAll(Object wallet) {
|
||||
// final moneroWallet = wallet as MoneroWallet;
|
||||
// return moneroWallet.walletAddresses.accountList
|
||||
// .getAll()
|
||||
// .map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
|
||||
// .toList();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> addAccount(Object wallet, {required String label}) async {
|
||||
// final moneroWallet = wallet as MoneroWallet;
|
||||
// await moneroWallet.walletAddresses.accountList.addAccount(label: label);
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label}) async {
|
||||
// final moneroWallet = wallet as MoneroWallet;
|
||||
// await moneroWallet.walletAddresses.accountList
|
||||
// .setLabelAccount(
|
||||
// accountIndex: accountIndex,
|
||||
// label: label);
|
||||
// }
|
||||
// }
|
||||
|
||||
class CWNano extends Nano {
|
||||
@override
|
||||
List<String> getNanoWordList(String language) => EthereumMnemonics.englishWordlist;
|
||||
|
||||
WalletService createNanoWalletService(Box<WalletInfo> walletInfoSource) =>
|
||||
EthereumWalletService(walletInfoSource);
|
||||
// @override
|
||||
// NanoAccountList getAccountList(Object wallet) {
|
||||
// return CWNanoAccountList(wallet);
|
||||
// }
|
||||
|
||||
@override
|
||||
WalletCredentials createEthereumNewWalletCredentials({
|
||||
List<String> getNanoWordList(String language) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
WalletService createNanoWalletService(Box<WalletInfo> walletInfoSource) {
|
||||
return NanoWalletService(walletInfoSource);
|
||||
}
|
||||
|
||||
// @override
|
||||
// WalletCredentials createNanoNewWalletCredentials({
|
||||
// required String name,
|
||||
// WalletInfo? walletInfo,
|
||||
// }) =>
|
||||
// NanoNewWalletCredentials(name: name, walletInfo: walletInfo);
|
||||
|
||||
@override
|
||||
WalletCredentials createNanoNewWalletCredentials({
|
||||
required String name,
|
||||
WalletInfo? walletInfo,
|
||||
}) =>
|
||||
EthereumNewWalletCredentials(name: name, walletInfo: walletInfo);
|
||||
|
||||
@override
|
||||
WalletCredentials createEthereumRestoreWalletFromSeedCredentials({
|
||||
required String name,
|
||||
required String mnemonic,
|
||||
required String password,
|
||||
}) =>
|
||||
EthereumRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic);
|
||||
|
||||
@override
|
||||
String getAddress(WalletBase wallet) => (wallet as EthereumWallet).walletAddresses.address;
|
||||
|
||||
@override
|
||||
TransactionPriority getDefaultTransactionPriority() => EthereumTransactionPriority.medium;
|
||||
|
||||
@override
|
||||
List<TransactionPriority> getTransactionPriorities() => EthereumTransactionPriority.all;
|
||||
|
||||
@override
|
||||
TransactionPriority deserializeEthereumTransactionPriority(int raw) =>
|
||||
EthereumTransactionPriority.deserialize(raw: raw);
|
||||
|
||||
@override
|
||||
int getEstimatedFee(Object wallet, TransactionPriority priority) {
|
||||
final ethereumWallet = wallet as EthereumWallet;
|
||||
return ethereumWallet.feeRate(priority);
|
||||
}
|
||||
|
||||
Object createEthereumTransactionCredentials(
|
||||
List<Output> outputs, {
|
||||
required TransactionPriority priority,
|
||||
required CryptoCurrency currency,
|
||||
int? feeRate,
|
||||
}) =>
|
||||
EthereumTransactionCredentials(
|
||||
outputs
|
||||
.map((out) => OutputInfo(
|
||||
fiatAmount: out.fiatAmount,
|
||||
cryptoAmount: out.cryptoAmount,
|
||||
address: out.address,
|
||||
note: out.note,
|
||||
sendAll: out.sendAll,
|
||||
extractedAddress: out.extractedAddress,
|
||||
isParsedAddress: out.isParsedAddress,
|
||||
formattedCryptoAmount: out.formattedCryptoAmount))
|
||||
.toList(),
|
||||
priority: priority as EthereumTransactionPriority,
|
||||
currency: currency,
|
||||
feeRate: feeRate,
|
||||
);
|
||||
|
||||
Object createEthereumTransactionCredentialsRaw(
|
||||
List<OutputInfo> outputs, {
|
||||
TransactionPriority? priority,
|
||||
required CryptoCurrency currency,
|
||||
required int feeRate,
|
||||
}) =>
|
||||
EthereumTransactionCredentials(
|
||||
outputs,
|
||||
priority: priority as EthereumTransactionPriority?,
|
||||
currency: currency,
|
||||
feeRate: feeRate,
|
||||
);
|
||||
|
||||
@override
|
||||
int formatterEthereumParseAmount(String amount) => EthereumFormatter.parseEthereumAmount(amount);
|
||||
|
||||
@override
|
||||
double formatterEthereumAmountToDouble({required TransactionInfo transaction}) {
|
||||
transaction as EthereumTransactionInfo;
|
||||
return cryptoAmountToDouble(
|
||||
amount: transaction.amount, divider: BigInt.from(10).pow(transaction.exponent).toInt());
|
||||
required String language,
|
||||
String? password,
|
||||
}) {
|
||||
return NanoNewWalletCredentials(name: name, password: password, language: language);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Erc20Token> getERC20Currencies(WalletBase wallet) {
|
||||
final ethereumWallet = wallet as EthereumWallet;
|
||||
return ethereumWallet.erc20Currencies;
|
||||
TransactionHistoryBase getTransactionHistory(Object wallet) {
|
||||
// final moneroWallet = wallet as MoneroWallet;
|
||||
// return moneroWallet.transactionHistory;
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addErc20Token(WalletBase wallet, Erc20Token token) async =>
|
||||
await (wallet as EthereumWallet).addErc20Token(token);
|
||||
|
||||
@override
|
||||
Future<void> deleteErc20Token(WalletBase wallet, Erc20Token token) async =>
|
||||
await (wallet as EthereumWallet).deleteErc20Token(token);
|
||||
|
||||
@override
|
||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress) async {
|
||||
final ethereumWallet = wallet as EthereumWallet;
|
||||
return await ethereumWallet.getErc20Token(contractAddress);
|
||||
void onStartup() {
|
||||
// monero_wallet_api.onStartup();
|
||||
}
|
||||
|
||||
@override
|
||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
|
||||
transaction as EthereumTransactionInfo;
|
||||
if (transaction.tokenSymbol == CryptoCurrency.eth.title) {
|
||||
return CryptoCurrency.eth;
|
||||
}
|
||||
|
||||
wallet as EthereumWallet;
|
||||
return wallet.erc20Currencies
|
||||
.firstWhere((element) => transaction.tokenSymbol == element.symbol);
|
||||
List<String> getMoneroWordList(String language) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,61 +1,59 @@
|
|||
|
||||
import 'package:cake_wallet/view_model/send/output.dart';
|
||||
import 'package:cw_core/crypto_amount_format.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/erc20_token.dart';
|
||||
import 'package:cw_core/output_info.dart';
|
||||
import 'package:cw_core/transaction_info.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cw_ethereum/ethereum_formatter.dart';
|
||||
import 'package:cw_ethereum/ethereum_mnemonics.dart';
|
||||
import 'package:cw_ethereum/ethereum_transaction_credentials.dart';
|
||||
import 'package:cw_ethereum/ethereum_transaction_info.dart';
|
||||
import 'package:cw_ethereum/ethereum_wallet.dart';
|
||||
import 'package:cw_ethereum/ethereum_wallet_creation_credentials.dart';
|
||||
import 'package:cw_ethereum/ethereum_wallet_service.dart';
|
||||
import 'package:cw_ethereum/ethereum_transaction_priority.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:cw_nano/api/wallet.dart' as nano_wallet_api;
|
||||
import 'package:cw_nano/nano_balance.dart';
|
||||
import 'package:cw_nano/nano_wallet_creation_credentials.dart';
|
||||
|
||||
part 'cw_nano.dart';
|
||||
|
||||
Nano? nano = CWNano();
|
||||
|
||||
abstract class Nano {
|
||||
List<String> getNanoWordList(String language);
|
||||
WalletService createNanoWalletService(Box<WalletInfo> walletInfoSource);
|
||||
WalletCredentials createEthereumNewWalletCredentials({required String name, WalletInfo? walletInfo});
|
||||
WalletCredentials createEthereumRestoreWalletFromSeedCredentials({required String name, required String mnemonic, required String password});
|
||||
String getAddress(WalletBase wallet);
|
||||
TransactionPriority getDefaultTransactionPriority();
|
||||
List<TransactionPriority> getTransactionPriorities();
|
||||
TransactionPriority deserializeEthereumTransactionPriority(int raw);
|
||||
int getEstimatedFee(Object wallet, TransactionPriority priority);
|
||||
|
||||
Object createEthereumTransactionCredentials(
|
||||
List<Output> outputs, {
|
||||
required TransactionPriority priority,
|
||||
required CryptoCurrency currency,
|
||||
int? feeRate,
|
||||
});
|
||||
|
||||
Object createEthereumTransactionCredentialsRaw(
|
||||
List<OutputInfo> outputs, {
|
||||
TransactionPriority? priority,
|
||||
required CryptoCurrency currency,
|
||||
required int feeRate,
|
||||
});
|
||||
|
||||
int formatterEthereumParseAmount(String amount);
|
||||
double formatterEthereumAmountToDouble({required TransactionInfo transaction});
|
||||
List<Erc20Token> getERC20Currencies(WalletBase wallet);
|
||||
Future<void> addErc20Token(WalletBase wallet, Erc20Token token);
|
||||
Future<void> deleteErc20Token(WalletBase wallet, Erc20Token token);
|
||||
Future<Erc20Token?> getErc20Token(WalletBase wallet, String contractAddress);
|
||||
|
||||
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction);
|
||||
class Account {
|
||||
Account({required this.id, required this.label, this.balance});
|
||||
final int id;
|
||||
final String label;
|
||||
final String? balance;
|
||||
}
|
||||
|
||||
abstract class NanoWalletDetails {
|
||||
@observable
|
||||
late Account account;
|
||||
|
||||
@observable
|
||||
late NanoBalance balance;
|
||||
}
|
||||
|
||||
abstract class Nano {
|
||||
// NanoAccountList getAccountList(Object wallet);
|
||||
|
||||
WalletService createNanoWalletService(Box<WalletInfo> walletInfoSource);
|
||||
|
||||
TransactionHistoryBase getTransactionHistory(Object wallet);
|
||||
|
||||
NanoWalletDetails getNanoWalletDetails(Object wallet);
|
||||
|
||||
WalletCredentials createNanoNewWalletCredentials({
|
||||
required String name,
|
||||
required String language,
|
||||
String password,
|
||||
});
|
||||
|
||||
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex);
|
||||
|
||||
void onStartup();
|
||||
|
||||
List<String> getNanoWordList(String language);
|
||||
}
|
||||
|
||||
abstract class NanoAccountList {
|
||||
ObservableList<Account> get accounts;
|
||||
void update(Object wallet);
|
||||
void refresh(Object wallet);
|
||||
List<Account> getAll(Object wallet);
|
||||
Future<void> addAccount(Object wallet, {required String label});
|
||||
Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label});
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/monero/monero.dart';
|
||||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cake_wallet/core/wallet_creation_service.dart';
|
||||
|
@ -45,6 +46,8 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
|
|||
name: name, language: options as String);
|
||||
case WalletType.ethereum:
|
||||
return ethereum!.createEthereumNewWalletCredentials(name: name);
|
||||
case WalletType.nano:
|
||||
return nano!.createNanoNewWalletCredentials(name: name, language: options as String);
|
||||
default:
|
||||
throw Exception('Unexpected type: ${type.toString()}');;
|
||||
}
|
||||
|
|
1
model_generator.sh
Normal file → Executable file
1
model_generator.sh
Normal file → Executable file
|
@ -3,4 +3,5 @@ cd cw_monero && flutter pub get && flutter packages pub run build_runner build -
|
|||
cd cw_bitcoin && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
|
||||
cd cw_haven && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
|
||||
cd cw_ethereum && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
|
||||
cd cw_nano && flutter pub get && flutter packages pub run build_runner build --delete-conflicting-outputs && cd ..
|
||||
flutter packages pub run build_runner build --delete-conflicting-outputs
|
|
@ -10,7 +10,7 @@ case $APP_ANDROID_TYPE in
|
|||
CONFIG_ARGS="--monero"
|
||||
;;
|
||||
$CAKEWALLET)
|
||||
CONFIG_ARGS="--monero --bitcoin --haven --ethereum"
|
||||
CONFIG_ARGS="--monero --bitcoin --haven --ethereum --nano"
|
||||
;;
|
||||
$HAVEN)
|
||||
CONFIG_ARGS="--haven"
|
||||
|
|
|
@ -14,12 +14,32 @@ Future<void> main(List<String> args) async {
|
|||
final hasMonero = args.contains('${prefix}monero');
|
||||
final hasHaven = args.contains('${prefix}haven');
|
||||
final hasEthereum = args.contains('${prefix}ethereum');
|
||||
final hasNano = args.contains('${prefix}nano');
|
||||
final hasBanano = args.contains('${prefix}banano');
|
||||
|
||||
await generateBitcoin(hasBitcoin);
|
||||
await generateMonero(hasMonero);
|
||||
await generateHaven(hasHaven);
|
||||
await generateEthereum(hasEthereum);
|
||||
await generatePubspec(hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum);
|
||||
await generateWalletTypes(hasMonero: hasMonero, hasBitcoin: hasBitcoin, hasHaven: hasHaven, hasEthereum: hasEthereum);
|
||||
await generateNano(hasNano);
|
||||
// await generateBanano(hasEthereum);
|
||||
|
||||
await generatePubspec(
|
||||
hasMonero: hasMonero,
|
||||
hasBitcoin: hasBitcoin,
|
||||
hasHaven: hasHaven,
|
||||
hasEthereum: hasEthereum,
|
||||
hasNano: hasNano,
|
||||
hasBanano: hasBanano,
|
||||
);
|
||||
await generateWalletTypes(
|
||||
hasMonero: hasMonero,
|
||||
hasBitcoin: hasBitcoin,
|
||||
hasHaven: hasHaven,
|
||||
hasEthereum: hasEthereum,
|
||||
hasNano: hasNano,
|
||||
hasBanano: hasBanano,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> generateBitcoin(bool hasImplementation) async {
|
||||
|
@ -105,12 +125,12 @@ abstract class Bitcoin {
|
|||
const bitcoinEmptyDefinition = 'Bitcoin? bitcoin;\n';
|
||||
const bitcoinCWDefinition = 'Bitcoin? bitcoin = CWBitcoin();\n';
|
||||
|
||||
final output = '$bitcoinCommonHeaders\n'
|
||||
+ (hasImplementation ? '$bitcoinCWHeaders\n' : '\n')
|
||||
+ (hasImplementation ? '$bitcoinCwPart\n\n' : '\n')
|
||||
+ (hasImplementation ? bitcoinCWDefinition : bitcoinEmptyDefinition)
|
||||
+ '\n'
|
||||
+ bitcoinContent;
|
||||
final output = '$bitcoinCommonHeaders\n' +
|
||||
(hasImplementation ? '$bitcoinCWHeaders\n' : '\n') +
|
||||
(hasImplementation ? '$bitcoinCwPart\n\n' : '\n') +
|
||||
(hasImplementation ? bitcoinCWDefinition : bitcoinEmptyDefinition) +
|
||||
'\n' +
|
||||
bitcoinContent;
|
||||
|
||||
if (outputFile.existsSync()) {
|
||||
await outputFile.delete();
|
||||
|
@ -279,12 +299,12 @@ abstract class MoneroAccountList {
|
|||
const moneroEmptyDefinition = 'Monero? monero;\n';
|
||||
const moneroCWDefinition = 'Monero? monero = CWMonero();\n';
|
||||
|
||||
final output = '$moneroCommonHeaders\n'
|
||||
+ (hasImplementation ? '$moneroCWHeaders\n' : '\n')
|
||||
+ (hasImplementation ? '$moneroCwPart\n\n' : '\n')
|
||||
+ (hasImplementation ? moneroCWDefinition : moneroEmptyDefinition)
|
||||
+ '\n'
|
||||
+ moneroContent;
|
||||
final output = '$moneroCommonHeaders\n' +
|
||||
(hasImplementation ? '$moneroCWHeaders\n' : '\n') +
|
||||
(hasImplementation ? '$moneroCwPart\n\n' : '\n') +
|
||||
(hasImplementation ? moneroCWDefinition : moneroEmptyDefinition) +
|
||||
'\n' +
|
||||
moneroContent;
|
||||
|
||||
if (outputFile.existsSync()) {
|
||||
await outputFile.delete();
|
||||
|
@ -294,7 +314,6 @@ abstract class MoneroAccountList {
|
|||
}
|
||||
|
||||
Future<void> generateHaven(bool hasImplementation) async {
|
||||
|
||||
final outputFile = File(havenOutputPath);
|
||||
const havenCommonHeaders = """
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -459,12 +478,12 @@ abstract class HavenAccountList {
|
|||
const havenEmptyDefinition = 'Haven? haven;\n';
|
||||
const havenCWDefinition = 'Haven? haven = CWHaven();\n';
|
||||
|
||||
final output = '$havenCommonHeaders\n'
|
||||
+ (hasImplementation ? '$havenCWHeaders\n' : '\n')
|
||||
+ (hasImplementation ? '$havenCwPart\n\n' : '\n')
|
||||
+ (hasImplementation ? havenCWDefinition : havenEmptyDefinition)
|
||||
+ '\n'
|
||||
+ havenContent;
|
||||
final output = '$havenCommonHeaders\n' +
|
||||
(hasImplementation ? '$havenCWHeaders\n' : '\n') +
|
||||
(hasImplementation ? '$havenCwPart\n\n' : '\n') +
|
||||
(hasImplementation ? havenCWDefinition : havenEmptyDefinition) +
|
||||
'\n' +
|
||||
havenContent;
|
||||
|
||||
if (outputFile.existsSync()) {
|
||||
await outputFile.delete();
|
||||
|
@ -474,7 +493,6 @@ abstract class HavenAccountList {
|
|||
}
|
||||
|
||||
Future<void> generateEthereum(bool hasImplementation) async {
|
||||
|
||||
final outputFile = File(ethereumOutputPath);
|
||||
const ethereumCommonHeaders = """
|
||||
""";
|
||||
|
@ -541,12 +559,12 @@ abstract class Ethereum {
|
|||
const ethereumEmptyDefinition = 'Ethereum? ethereum;\n';
|
||||
const ethereumCWDefinition = 'Ethereum? ethereum = CWEthereum();\n';
|
||||
|
||||
final output = '$ethereumCommonHeaders\n'
|
||||
+ (hasImplementation ? '$ethereumCWHeaders\n' : '\n')
|
||||
+ (hasImplementation ? '$ethereumCwPart\n\n' : '\n')
|
||||
+ (hasImplementation ? ethereumCWDefinition : ethereumEmptyDefinition)
|
||||
+ '\n'
|
||||
+ ethereumContent;
|
||||
final output = '$ethereumCommonHeaders\n' +
|
||||
(hasImplementation ? '$ethereumCWHeaders\n' : '\n') +
|
||||
(hasImplementation ? '$ethereumCwPart\n\n' : '\n') +
|
||||
(hasImplementation ? ethereumCWDefinition : ethereumEmptyDefinition) +
|
||||
'\n' +
|
||||
ethereumContent;
|
||||
|
||||
if (outputFile.existsSync()) {
|
||||
await outputFile.delete();
|
||||
|
@ -555,8 +573,81 @@ abstract class Ethereum {
|
|||
await outputFile.writeAsString(output);
|
||||
}
|
||||
|
||||
Future<void> generatePubspec({required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum}) async {
|
||||
const cwCore = """
|
||||
Future<void> generateNano(bool hasImplementation) async {
|
||||
final outputFile = File(ethereumOutputPath);
|
||||
const nanoCommonHeaders = """
|
||||
""";
|
||||
const nanoCWHeaders = """
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:cw_nano/api/wallet.dart' as nano_wallet_api;
|
||||
import 'package:cw_nano/nano_balance.dart';
|
||||
import 'package:cw_nano/nano_wallet_creation_credentials.dart';
|
||||
""";
|
||||
const nanoCwPart = "part 'cw_nano.dart';";
|
||||
const nanoContent = """
|
||||
abstract class Nano {
|
||||
// NanoAccountList getAccountList(Object wallet);
|
||||
|
||||
WalletService createNanoWalletService(Box<WalletInfo> walletInfoSource);
|
||||
|
||||
TransactionHistoryBase getTransactionHistory(Object wallet);
|
||||
|
||||
NanoWalletDetails getNanoWalletDetails(Object wallet);
|
||||
|
||||
WalletCredentials createNanoNewWalletCredentials({
|
||||
required String name,
|
||||
required String language,
|
||||
String password,
|
||||
});
|
||||
|
||||
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex);
|
||||
|
||||
void onStartup();
|
||||
|
||||
List<String> getNanoWordList(String language);
|
||||
}
|
||||
|
||||
abstract class NanoAccountList {
|
||||
ObservableList<Account> get accounts;
|
||||
void update(Object wallet);
|
||||
void refresh(Object wallet);
|
||||
List<Account> getAll(Object wallet);
|
||||
Future<void> addAccount(Object wallet, {required String label});
|
||||
Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label});
|
||||
}
|
||||
""";
|
||||
|
||||
const nanoEmptyDefinition = 'Nano? nano;\n';
|
||||
const nanoCWDefinition = 'Nano? nano = CWNano();\n';
|
||||
|
||||
final output = '$nanoCommonHeaders\n' +
|
||||
(hasImplementation ? '$nanoCWHeaders\n' : '\n') +
|
||||
(hasImplementation ? '$nanoCwPart\n\n' : '\n') +
|
||||
(hasImplementation ? nanoCWDefinition : nanoEmptyDefinition) +
|
||||
'\n' +
|
||||
nanoContent;
|
||||
|
||||
if (outputFile.existsSync()) {
|
||||
await outputFile.delete();
|
||||
}
|
||||
|
||||
await outputFile.writeAsString(output);
|
||||
}
|
||||
|
||||
Future<void> generatePubspec({
|
||||
required bool hasMonero,
|
||||
required bool hasBitcoin,
|
||||
required bool hasHaven,
|
||||
required bool hasEthereum,
|
||||
required bool hasNano,
|
||||
required bool hasBanano,
|
||||
}) async {
|
||||
const cwCore = """
|
||||
cw_core:
|
||||
path: ./cw_core
|
||||
""";
|
||||
|
@ -580,6 +671,14 @@ Future<void> generatePubspec({required bool hasMonero, required bool hasBitcoin,
|
|||
cw_ethereum:
|
||||
path: ./cw_ethereum
|
||||
""";
|
||||
const cwNano = """
|
||||
cw_nano:
|
||||
path: ./cw_nano
|
||||
""";
|
||||
const cwBanano = """
|
||||
cw_nano:
|
||||
path: ./cw_banano
|
||||
""";
|
||||
final inputFile = File(pubspecOutputPath);
|
||||
final inputText = await inputFile.readAsString();
|
||||
final inputLines = inputText.split('\n');
|
||||
|
@ -604,11 +703,19 @@ Future<void> generatePubspec({required bool hasMonero, required bool hasBitcoin,
|
|||
output += '\n$cwEthereum';
|
||||
}
|
||||
|
||||
if (hasNano) {
|
||||
output += '\n$cwNano';
|
||||
}
|
||||
|
||||
if (hasBanano) {
|
||||
output += '\n$cwBanano';
|
||||
}
|
||||
|
||||
final outputLines = output.split('\n');
|
||||
inputLines.insertAll(dependenciesIndex + 1, outputLines);
|
||||
final outputContent = inputLines.join('\n');
|
||||
final outputFile = File(pubspecOutputPath);
|
||||
|
||||
|
||||
if (outputFile.existsSync()) {
|
||||
await outputFile.delete();
|
||||
}
|
||||
|
@ -616,9 +723,16 @@ Future<void> generatePubspec({required bool hasMonero, required bool hasBitcoin,
|
|||
await outputFile.writeAsString(outputContent);
|
||||
}
|
||||
|
||||
Future<void> generateWalletTypes({required bool hasMonero, required bool hasBitcoin, required bool hasHaven, required bool hasEthereum}) async {
|
||||
Future<void> generateWalletTypes({
|
||||
required bool hasMonero,
|
||||
required bool hasBitcoin,
|
||||
required bool hasHaven,
|
||||
required bool hasEthereum,
|
||||
required bool hasNano,
|
||||
required bool hasBanano,
|
||||
}) async {
|
||||
final walletTypesFile = File(walletTypesPath);
|
||||
|
||||
|
||||
if (walletTypesFile.existsSync()) {
|
||||
await walletTypesFile.delete();
|
||||
}
|
||||
|
@ -647,6 +761,14 @@ Future<void> generateWalletTypes({required bool hasMonero, required bool hasBitc
|
|||
outputContent += '\tWalletType.haven,\n';
|
||||
}
|
||||
|
||||
if (hasNano) {
|
||||
outputContent += '\tWalletType.nano,\n';
|
||||
}
|
||||
|
||||
if (hasBanano) {
|
||||
outputContent += '\tWalletType.banano,\n';
|
||||
}
|
||||
|
||||
outputContent += '];\n';
|
||||
await walletTypesFile.writeAsString(outputContent);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue