wallet recovery

This commit is contained in:
leo 2023-12-14 04:51:16 +00:00
parent 2d886e1213
commit 8d3dd6f202
23 changed files with 2357 additions and 2000 deletions

View file

@ -96,6 +96,8 @@ class AmountConverter {
case CryptoCurrency.xnzd: case CryptoCurrency.xnzd:
case CryptoCurrency.xusd: case CryptoCurrency.xusd:
return _moneroAmountToString(amount); return _moneroAmountToString(amount);
case CryptoCurrency.zano:
return _moneroAmountToString(amount);
default: default:
return ''; return '';
} }

View file

@ -1,10 +1,13 @@
import 'package:cw_core/balance.dart'; import 'package:cw_core/balance.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/transaction_history.dart'; import 'package:cw_core/transaction_history.dart';
import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'dummy_wallet_creation_credentials.dart'; import 'dummy_wallet_creation_credentials.dart';
@ -15,7 +18,7 @@ class DummyWalletService extends WalletService<DummyNewWalletCredentials, DummyR
final Box<WalletInfo> walletInfoSource; final Box<WalletInfo> walletInfoSource;
@override @override
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> create(DummyNewWalletCredentials credentials) => throw UnimplementedError(); Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> create(WalletCredentials credentials) => throw UnimplementedError();
@override @override
WalletType getType() => WalletType.dummy; WalletType getType() => WalletType.dummy;

View file

@ -20,6 +20,9 @@ dependencies:
cw_core: cw_core:
path: ../cw_core path: ../cw_core
cw_zano:
path: ../cw_zano
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter

View file

@ -419,6 +419,12 @@ extern "C"
return strdup(plain_wallet::get_wallet_status(hwallet).c_str()); return strdup(plain_wallet::get_wallet_status(hwallet).c_str());
} }
char* get_address_info(char* address)
{
return strdup(plain_wallet::get_address_info(address).c_str());
}
char* async_call(char* method_name, uint64_t instance_id, char* params) char* async_call(char* method_name, uint64_t instance_id, char* params)
{ {
return strdup(plain_wallet::async_call(method_name, instance_id, params).c_str()); return strdup(plain_wallet::async_call(method_name, instance_id, params).c_str());

View file

@ -3,7 +3,7 @@ import 'dart:convert';
import 'package:cw_zano/api/model/recent_history.dart'; import 'package:cw_zano/api/model/recent_history.dart';
import 'package:cw_zano/api/model/wi.dart'; import 'package:cw_zano/api/model/wi.dart';
class CreateLoadRestoreWalletResult { class CreateWalletResult {
final String name; final String name;
final String pass; final String pass;
final RecentHistory recentHistory; final RecentHistory recentHistory;
@ -14,7 +14,7 @@ class CreateLoadRestoreWalletResult {
final int walletLocalBcSize; final int walletLocalBcSize;
final Wi wi; final Wi wi;
CreateLoadRestoreWalletResult( CreateWalletResult(
{required this.name, {required this.name,
required this.pass, required this.pass,
required this.recentHistory, required this.recentHistory,
@ -25,8 +25,8 @@ class CreateLoadRestoreWalletResult {
required this.walletLocalBcSize, required this.walletLocalBcSize,
required this.wi}); required this.wi});
factory CreateLoadRestoreWalletResult.fromJson(Map<String, dynamic> json) => factory CreateWalletResult.fromJson(Map<String, dynamic> json) =>
CreateLoadRestoreWalletResult( CreateWalletResult(
name: json['name'] as String, name: json['name'] as String,
pass: json['pass'] as String, pass: json['pass'] as String,
recentHistory: RecentHistory.fromJson( recentHistory: RecentHistory.fromJson(

View file

@ -62,7 +62,7 @@ class History {
.map((e) => Subtransfer.fromJson(e as Map<String, dynamic>)) .map((e) => Subtransfer.fromJson(e as Map<String, dynamic>))
.toList(), .toList(),
timestamp: json['timestamp'] as int, timestamp: json['timestamp'] as int,
transferInternalIndex: json['transfer_internal_index'] as int, transferInternalIndex: json['transfer_internal_index'] is double ? (json['transfer_internal_index'] as double).toInt() : json['transfer_internal_index'] as int,
txBlobSize: json['tx_blob_size'] as int, txBlobSize: json['tx_blob_size'] as int,
txHash: json['tx_hash'] as String, txHash: json['tx_hash'] as String,
txType: json['tx_type'] as int, txType: json['tx_type'] as int,

View file

@ -0,0 +1,12 @@
class ZanoWalletKeys {
const ZanoWalletKeys(
{required this.privateSpendKey,
required this.privateViewKey,
required this.publicSpendKey,
required this.publicViewKey});
final String publicViewKey;
final String privateViewKey;
final String publicSpendKey;
final String privateSpendKey;
}

View file

@ -32,9 +32,9 @@ final transactionCreateMultDestNative = zanoApi
'transaction_create_mult_dest') 'transaction_create_mult_dest')
.asFunction<TransactionCreateMultDest>(); .asFunction<TransactionCreateMultDest>();
final transactionCommitNative = zanoApi // final transactionCommitNative = zanoApi
.lookup<NativeFunction<transaction_commit>>('transaction_commit') // .lookup<NativeFunction<transaction_commit>>('transaction_commit')
.asFunction<TransactionCommit>(); // .asFunction<TransactionCommit>();
final getTxKeyNative = zanoApi final getTxKeyNative = zanoApi
.lookup<NativeFunction<get_tx_key>>('get_tx_key') .lookup<NativeFunction<get_tx_key>>('get_tx_key')
@ -53,11 +53,11 @@ String getTxKey(String txId) {
return ''; return '';
} }
void refreshTransactions() { // void refreshTransactions() {
// TODO: fix it // // TODO: fix it
//transactionsRefreshNative(); // //transactionsRefreshNative();
debugPrint("refreshing transactions"); // debugPrint("refreshing transactions");
} // }
int countOfTransactions() { int countOfTransactions() {
//return transactionsCountNative(); //return transactionsCountNative();
@ -184,8 +184,9 @@ void commitTransactionFromPointerAddress({required int address}) =>
void commitTransaction( void commitTransaction(
{required Pointer<PendingTransactionRaw> transactionPointer}) { {required Pointer<PendingTransactionRaw> transactionPointer}) {
final errorMessagePointer = calloc<Utf8Box>(); final errorMessagePointer = calloc<Utf8Box>();
final isCommited = print("commit transaction");
transactionCommitNative(transactionPointer, errorMessagePointer) != 0; final isCommited = true;
//transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
if (!isCommited) { if (!isCommited) {
final message = errorMessagePointer.ref.getValue(); final message = errorMessagePointer.ref.getValue();

View file

@ -1,5 +1,12 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:ffi'; import 'dart:ffi';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_zano/api/model/get_wallet_info_result.dart';
import 'package:cw_zano/api/model/get_wallet_status_result.dart';
import 'package:cw_zano/api/model/zano_wallet_keys.dart';
import 'package:cw_zano/zano_balance.dart';
import 'package:cw_zano/zano_wallet.dart';
import 'package:ffi/ffi.dart'; import 'package:ffi/ffi.dart';
import 'package:cw_zano/api/structs/ut8_box.dart'; import 'package:cw_zano/api/structs/ut8_box.dart';
import 'package:cw_zano/api/convert_utf8_to_string.dart'; import 'package:cw_zano/api/convert_utf8_to_string.dart';
@ -10,19 +17,18 @@ import 'package:cw_zano/api/calls.dart' as calls;
import 'package:cw_zano/api/exceptions/setup_wallet_exception.dart'; import 'package:cw_zano/api/exceptions/setup_wallet_exception.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:mobx/mobx.dart' as mobx;
int _boolToInt(bool value) => value ? 1 : 0; int _boolToInt(bool value) => value ? 1 : 0;
final getFileNameNative = zanoApi final getFileNameNative =
.lookup<NativeFunction<get_filename>>('get_filename') zanoApi.lookup<NativeFunction<get_filename>>('get_filename').asFunction<GetFilename>();
.asFunction<GetFilename>();
/*final getSeedNative = /*final getSeedNative =
zanoApi.lookup<NativeFunction<get_seed>>('seed').asFunction<GetSeed>();*/ zanoApi.lookup<NativeFunction<get_seed>>('seed').asFunction<GetSeed>();*/
final getAddressNative = zanoApi final getAddressNative =
.lookup<NativeFunction<get_address>>('get_address') zanoApi.lookup<NativeFunction<get_address>>('get_address').asFunction<GetAddress>();
.asFunction<GetAddress>();
final getFullBalanceNative = zanoApi final getFullBalanceNative = zanoApi
.lookup<NativeFunction<get_full_balanace>>('get_full_balance') .lookup<NativeFunction<get_full_balanace>>('get_full_balance')
@ -36,42 +42,36 @@ final getUnlockedBalanceNative = zanoApi
.lookup<NativeFunction<get_current_height>>('get_current_height') .lookup<NativeFunction<get_current_height>>('get_current_height')
.asFunction<GetCurrentHeight>();*/ .asFunction<GetCurrentHeight>();*/
final getNodeHeightNative = zanoApi // final getNodeHeightNative = zanoApi
.lookup<NativeFunction<get_node_height>>('get_node_height') // .lookup<NativeFunction<get_node_height>>('get_node_height')
.asFunction<GetNodeHeight>(); // .asFunction<GetNodeHeight>();
final isConnectedNative = zanoApi final isConnectedNative =
.lookup<NativeFunction<is_connected>>('is_connected') zanoApi.lookup<NativeFunction<is_connected>>('is_connected').asFunction<IsConnected>();
.asFunction<IsConnected>();
final setupNodeNative = zanoApi final setupNodeNative =
.lookup<NativeFunction<setup_node>>('setup_node') zanoApi.lookup<NativeFunction<setup_node>>('setup_node').asFunction<SetupNode>();
.asFunction<SetupNode>();
final startRefreshNative = zanoApi // final startRefreshNative = zanoApi
.lookup<NativeFunction<start_refresh>>('start_refresh') // .lookup<NativeFunction<start_refresh>>('start_refresh')
.asFunction<StartRefresh>(); // .asFunction<StartRefresh>();
final connecToNodeNative = zanoApi final connecToNodeNative =
.lookup<NativeFunction<connect_to_node>>('connect_to_node') zanoApi.lookup<NativeFunction<connect_to_node>>('connect_to_node').asFunction<ConnectToNode>();
.asFunction<ConnectToNode>();
final setRefreshFromBlockHeightNative = zanoApi final setRefreshFromBlockHeightNative = zanoApi
.lookup<NativeFunction<set_refresh_from_block_height>>( .lookup<NativeFunction<set_refresh_from_block_height>>('set_refresh_from_block_height')
'set_refresh_from_block_height')
.asFunction<SetRefreshFromBlockHeight>(); .asFunction<SetRefreshFromBlockHeight>();
final setRecoveringFromSeedNative = zanoApi // final setRecoveringFromSeedNative = zanoApi
.lookup<NativeFunction<set_recovering_from_seed>>( // .lookup<NativeFunction<set_recovering_from_seed>>('set_recovering_from_seed')
'set_recovering_from_seed') // .asFunction<SetRecoveringFromSeed>();
.asFunction<SetRecoveringFromSeed>();
final storeNative =
zanoApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
final setPasswordNative = zanoApi final storeNative = zanoApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
.lookup<NativeFunction<set_password>>('set_password')
.asFunction<SetPassword>(); final setPasswordNative =
zanoApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>();
/**final setListenerNative = zanoApi /**final setListenerNative = zanoApi
.lookup<NativeFunction<set_listener>>('set_listener') .lookup<NativeFunction<set_listener>>('set_listener')
@ -85,18 +85,15 @@ final isNeededToRefreshNative = zanoApi
.lookup<NativeFunction<is_needed_to_refresh>>('is_needed_to_refresh') .lookup<NativeFunction<is_needed_to_refresh>>('is_needed_to_refresh')
.asFunction<IsNeededToRefresh>(); .asFunction<IsNeededToRefresh>();
final isNewTransactionExistNative = zanoApi // final isNewTransactionExistNative = zanoApi
.lookup<NativeFunction<is_new_transaction_exist>>( // .lookup<NativeFunction<is_new_transaction_exist>>('is_new_transaction_exist')
'is_new_transaction_exist') // .asFunction<IsNewTransactionExist>();
.asFunction<IsNewTransactionExist>();
final getSecretViewKeyNative = zanoApi final getSecretViewKeyNative =
.lookup<NativeFunction<secret_view_key>>('secret_view_key') zanoApi.lookup<NativeFunction<secret_view_key>>('secret_view_key').asFunction<SecretViewKey>();
.asFunction<SecretViewKey>();
final getPublicViewKeyNative = zanoApi final getPublicViewKeyNative =
.lookup<NativeFunction<public_view_key>>('public_view_key') zanoApi.lookup<NativeFunction<public_view_key>>('public_view_key').asFunction<PublicViewKey>();
.asFunction<PublicViewKey>();
final getSecretSpendKeyNative = zanoApi final getSecretSpendKeyNative = zanoApi
.lookup<NativeFunction<secret_spend_key>>('secret_spend_key') .lookup<NativeFunction<secret_spend_key>>('secret_spend_key')
@ -110,27 +107,25 @@ final closeCurrentWalletNative = zanoApi
.lookup<NativeFunction<close_current_wallet>>('close_current_wallet') .lookup<NativeFunction<close_current_wallet>>('close_current_wallet')
.asFunction<CloseCurrentWallet>(); .asFunction<CloseCurrentWallet>();
final onStartupNative = zanoApi final onStartupNative =
.lookup<NativeFunction<on_startup>>('on_startup') zanoApi.lookup<NativeFunction<on_startup>>('on_startup').asFunction<OnStartup>();
.asFunction<OnStartup>();
final rescanBlockchainAsyncNative = zanoApi final rescanBlockchainAsyncNative = zanoApi
.lookup<NativeFunction<rescan_blockchain>>('rescan_blockchain') .lookup<NativeFunction<rescan_blockchain>>('rescan_blockchain')
.asFunction<RescanBlockchainAsync>(); .asFunction<RescanBlockchainAsync>();
final setTrustedDaemonNative = zanoApi // final setTrustedDaemonNative = zanoApi
.lookup<NativeFunction<set_trusted_daemon>>('set_trusted_daemon') // .lookup<NativeFunction<set_trusted_daemon>>('set_trusted_daemon')
.asFunction<SetTrustedDaemon>(); // .asFunction<SetTrustedDaemon>();
final trustedDaemonNative = zanoApi final trustedDaemonNative =
.lookup<NativeFunction<trusted_daemon>>('trusted_daemon') zanoApi.lookup<NativeFunction<trusted_daemon>>('trusted_daemon').asFunction<TrustedDaemon>();
.asFunction<TrustedDaemon>();
int getSyncingHeight() => getSyncingHeightNative(); int getSyncingHeight() => getSyncingHeightNative();
bool isNeededToRefresh() => isNeededToRefreshNative() != 0; bool isNeededToRefresh() => isNeededToRefreshNative() != 0;
bool isNewTransactionExist() => isNewTransactionExistNative() != 0; //bool isNewTransactionExist() => isNewTransactionExistNative() != 0;
String getFilename() => convertUTF8ToString(pointer: getFileNameNative()); String getFilename() => convertUTF8ToString(pointer: getFileNameNative());
@ -139,29 +134,49 @@ String getFilename() => convertUTF8ToString(pointer: getFileNameNative());
String getAddress({int accountIndex = 0, int addressIndex = 0}) => String getAddress({int accountIndex = 0, int addressIndex = 0}) =>
convertUTF8ToString(pointer: getAddressNative(accountIndex, addressIndex)); convertUTF8ToString(pointer: getAddressNative(accountIndex, addressIndex));
int getFullBalance({int accountIndex = 0}) => int getFullBalance({int accountIndex = 0}) => getFullBalanceNative(accountIndex);
getFullBalanceNative(accountIndex);
int getUnlockedBalance({int accountIndex = 0}) => int getUnlockedBalance({int accountIndex = 0}) => getUnlockedBalanceNative(accountIndex);
getUnlockedBalanceNative(accountIndex);
int getCurrentHeight(int hWallet) { int getCurrentHeight(int hWallet) {
calls.getWalletStatus(hWallet); final json = calls.getWalletStatus(hWallet);
return -1; final walletStatus = GetWalletStatusResult.fromJson(jsonDecode(json) as Map<String, dynamic>);
//return getCurrentHeightNative(); return walletStatus.currentWalletHeight;
} }
int getNodeHeightSync() => getNodeHeightNative(); int getNodeHeightSync(int hWallet) {
final json = calls.getWalletStatus(hWallet);
final walletStatus = GetWalletStatusResult.fromJson(jsonDecode(json) as Map<String, dynamic>);
return walletStatus.currentDaemonHeight;
}
// int getWalletInfo(int hWallet) {
// final json = calls.getWalletInfo(hWallet);
// final walletInfo = GetWalletInfoResult.fromJson(jsonDecode(json) as Map<String, dynamic>);
// zanoSeed = walletInfo.wiExtended.seed;
// zanoKeys = ZanoWalletKeys(
// privateSpendKey: walletInfo.wiExtended.spendPrivateKey,
// privateViewKey: walletInfo.wiExtended.viewPrivateKey,
// publicSpendKey: walletInfo.wiExtended.spendPublicKey,
// publicViewKey: walletInfo.wiExtended.viewPublicKey,
// );
// return 0;
// }
int getTxFee(int priority) {
return calls.getCurrentTxFee(priority);
}
bool isConnectedSync() => isConnectedNative() != 0; bool isConnectedSync() => isConnectedNative() != 0;
bool setupNodeSync( bool setupNodeSync({
{required String address, required String address,
String? login, String? login,
String? password, String? password,
bool useSSL = false, bool useSSL = false,
bool isLightWallet = false, bool isLightWallet = false,
/*String? socksProxyAddress*/}) { /*String? socksProxyAddress*/
}) {
final addressPointer = address.toNativeUtf8(); final addressPointer = address.toNativeUtf8();
Pointer<Utf8>? loginPointer; Pointer<Utf8>? loginPointer;
Pointer<Utf8>? socksProxyAddressPointer; Pointer<Utf8>? socksProxyAddressPointer;
@ -180,7 +195,8 @@ bool setupNodeSync(
}*/ }*/
final errorMessagePointer = ''.toNativeUtf8(); final errorMessagePointer = ''.toNativeUtf8();
debugPrint("setup_node address $address login $login password $password useSSL $useSSL isLightWallet $isLightWallet"); debugPrint(
"setup_node address $address login $login password $password useSSL $useSSL isLightWallet $isLightWallet");
// TODO: here can be ZERO! upd: no // TODO: here can be ZERO! upd: no
final isSetupNode = setupNodeNative( final isSetupNode = setupNodeNative(
addressPointer, addressPointer,
@ -212,15 +228,14 @@ bool setupNodeSync(
return isSetupNode; return isSetupNode;
} }
void startRefreshSync() => startRefreshNative(); //void startRefreshSync() => startRefreshNative();
Future<bool> connectToNode() async => connecToNodeNative() != 0; Future<bool> connectToNode() async => connecToNodeNative() != 0;
void setRefreshFromBlockHeight({required int height}) => void setRefreshFromBlockHeight({required int height}) => setRefreshFromBlockHeightNative(height);
setRefreshFromBlockHeightNative(height);
void setRecoveringFromSeed({required bool isRecovery}) => // void setRecoveringFromSeed({required bool isRecovery}) =>
setRecoveringFromSeedNative(_boolToInt(isRecovery)); // setRecoveringFromSeedNative(_boolToInt(isRecovery));
void storeSync(int hWallet) { void storeSync(int hWallet) {
calls.store(hWallet); calls.store(hWallet);
@ -247,17 +262,13 @@ void setPasswordSync(String password) {
void closeCurrentWallet() => closeCurrentWalletNative(); void closeCurrentWallet() => closeCurrentWalletNative();
String getSecretViewKey() => String getSecretViewKey() => convertUTF8ToString(pointer: getSecretViewKeyNative());
convertUTF8ToString(pointer: getSecretViewKeyNative());
String getPublicViewKey() => String getPublicViewKey() => convertUTF8ToString(pointer: getPublicViewKeyNative());
convertUTF8ToString(pointer: getPublicViewKeyNative());
String getSecretSpendKey() => String getSecretSpendKey() => convertUTF8ToString(pointer: getSecretSpendKeyNative());
convertUTF8ToString(pointer: getSecretSpendKeyNative());
String getPublicSpendKey() => String getPublicSpendKey() => convertUTF8ToString(pointer: getPublicSpendKeyNative());
convertUTF8ToString(pointer: getPublicSpendKeyNative());
class SyncListener { class SyncListener {
SyncListener(this.onNewBlock, this.onNewTransaction) SyncListener(this.onNewBlock, this.onNewTransaction)
@ -273,36 +284,54 @@ class SyncListener {
int _lastKnownBlockHeight; int _lastKnownBlockHeight;
int _initialSyncHeight; int _initialSyncHeight;
Future<int> getNodeHeightOrUpdate(int baseHeight) async { Future<int> getNodeHeightOrUpdate(int hWallet, int baseHeight) async {
if (_cachedBlockchainHeight < baseHeight || _cachedBlockchainHeight == 0) { if (_cachedBlockchainHeight < baseHeight || _cachedBlockchainHeight == 0) {
_cachedBlockchainHeight = await getNodeHeight(); _cachedBlockchainHeight = await compute<int, int>(getNodeHeightSync, hWallet);
} }
return _cachedBlockchainHeight; return _cachedBlockchainHeight;
} }
void start() { void start(ZanoWalletBase wallet, int hWallet) async {
_cachedBlockchainHeight = 0; _cachedBlockchainHeight = 0;
_lastKnownBlockHeight = 0; _lastKnownBlockHeight = 0;
_initialSyncHeight = 0; _initialSyncHeight = 0;
_updateSyncInfoTimer ??= _updateSyncInfoTimer ??= Timer.periodic(Duration(milliseconds: 1200), (_) async {
Timer.periodic(Duration(milliseconds: 1200), (_) async { /**if (isNewTransactionExist()) {
if (isNewTransactionExist()) {
onNewTransaction?.call(); onNewTransaction?.call();
} }*/
var syncHeight = getSyncingHeight(); ///var syncHeight = getSyncingHeight();
var syncHeight = getCurrentHeight(hWallet);
if (syncHeight <= 0) { if (syncHeight <= 0) {
// TODO: fix it syncHeight = getCurrentHeight(hWallet);
syncHeight = getCurrentHeight(-1);
} }
//getWalletInfo(hWallet);
final json = calls.getWalletInfo(hWallet);
final result = GetWalletInfoResult.fromJson(jsonDecode(json) as Map<String, dynamic>);
wallet.seed = result.wiExtended.seed;
wallet.keys = ZanoWalletKeys(
privateSpendKey: result.wiExtended.spendPrivateKey,
privateViewKey: result.wiExtended.viewPrivateKey,
publicSpendKey: result.wiExtended.spendPublicKey,
publicViewKey: result.wiExtended.viewPublicKey,
);
final balance = result.wi.balances.first;
wallet.assetId = balance.assetInfo.assetId;
wallet.balance = mobx.ObservableMap.of(
{CryptoCurrency.zano: ZanoBalance(total: balance.total, unlocked: balance.unlocked)});
getTxFee(hWallet);
if (_initialSyncHeight <= 0) { if (_initialSyncHeight <= 0) {
_initialSyncHeight = syncHeight; _initialSyncHeight = syncHeight;
} }
final bchHeight = await getNodeHeightOrUpdate(syncHeight); final bchHeight = await getNodeHeightOrUpdate(hWallet, syncHeight);
if (_lastKnownBlockHeight == syncHeight || syncHeight == null) { if (_lastKnownBlockHeight == syncHeight || syncHeight == null) {
return; return;
@ -326,8 +355,8 @@ class SyncListener {
void stop() => _updateSyncInfoTimer?.cancel(); void stop() => _updateSyncInfoTimer?.cancel();
} }
SyncListener setListeners(void Function(int, int, double) onNewBlock, SyncListener setListeners(
void Function() onNewTransaction) { void Function(int, int, double) onNewBlock, void Function() onNewTransaction) {
final listener = SyncListener(onNewBlock, onNewTransaction); final listener = SyncListener(onNewBlock, onNewTransaction);
/**setListenerNative();*/ /**setListenerNative();*/
return listener; return listener;
@ -350,15 +379,15 @@ bool _setupNodeSync(Map args) {
login: login, login: login,
password: password, password: password,
useSSL: useSSL, useSSL: useSSL,
isLightWallet: isLightWallet, isLightWallet: isLightWallet, /*socksProxyAddress: socksProxyAddress*/
/*socksProxyAddress: socksProxyAddress*/); );
} }
bool _isConnected(Object _) => isConnectedSync(); bool _isConnected(Object _) => isConnectedSync();
int _getNodeHeight(Object _) => getNodeHeightSync(); //int _getNodeHeight(Object _) => getNodeHeightSync();
void startRefresh() => startRefreshSync(); //void startRefresh() => startRefreshSync();
Future<bool> setupNode( Future<bool> setupNode(
{required String address, {required String address,
@ -380,11 +409,11 @@ Future<void> store(int hWallet) => compute<int, void>(_storeSync, 0);
Future<bool> isConnected() => compute(_isConnected, 0); Future<bool> isConnected() => compute(_isConnected, 0);
Future<int> getNodeHeight() => compute(_getNodeHeight, 0); //Future<int> getNodeHeight() => compute(_getNodeHeight, 0);
void rescanBlockchainAsync() => rescanBlockchainAsyncNative(); void rescanBlockchainAsync() => rescanBlockchainAsyncNative();
Future setTrustedDaemon(bool trusted) async => // Future setTrustedDaemon(bool trusted) async =>
setTrustedDaemonNative(_boolToInt(trusted)); // setTrustedDaemonNative(_boolToInt(trusted));
Future<bool> trustedDaemon() async => trustedDaemonNative() != 0; Future<bool> trustedDaemon() async => trustedDaemonNative() != 0;

View file

@ -200,11 +200,11 @@ Future<void> _openWallet(Map<String, String> args) async => loadWallet(
bool _isWalletExist(String path) => isWalletExistSync(path: path); bool _isWalletExist(String path) => isWalletExistSync(path: path);
void openWallet( // void openWallet(
{required String path, // {required String path,
required String password, // required String password,
int nettype = 0}) async => // int nettype = 0}) async =>
loadWallet(path: path, password: password, nettype: nettype); // loadWallet(path: path, password: password, nettype: nettype);
Future<void> openWalletAsync(Map<String, String> args) async => Future<void> openWalletAsync(Map<String, String> args) async =>
compute(_openWallet, args); compute(_openWallet, args);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,19 @@
import 'package:cw_core/wallet_addresses.dart';
class NewZanoWalletAddresses extends WalletAddresses {
@override
String address;
NewZanoWalletAddresses(super.walletInfo): address = "";
@override
Future<void> init() async {
print("NewZanoWalletAddresses init");
}
@override
Future<void> updateAddressesInBox() async {
print("NewZanoWalletAddresses updateAddressesInBox");
}
}

View file

@ -0,0 +1,239 @@
import 'dart:async';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/wallet_addresses.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_zano/api/model/balance.dart';
import 'package:cw_zano/api/model/create_wallet_result.dart';
import 'package:cw_zano/api/zano_api.dart';
import 'package:cw_zano/zano_balance.dart';
import 'package:cw_zano/zano_transaction_history.dart';
import 'package:cw_zano/zano_transaction_info.dart';
import 'package:mobx/src/api/observable_collections.dart';
import 'package:cw_zano/api/wallet.dart' as zano_wallet;
import 'dart:convert';
import 'dart:ffi';
import 'package:cw_zano/api/signatures.dart';
import 'package:cw_zano/api/types.dart';
import 'package:ffi/ffi.dart';
import 'api/model/zano_wallet_keys.dart';
import 'new_zano_addresses_base.dart';
typedef _load_wallet = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>, Int8);
typedef _LoadWallet = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>, int);
class NewZanoWallet extends WalletBase<ZanoBalance, ZanoTransactionHistory, ZanoTransactionInfo> {
@override
SyncStatus syncStatus;
Timer? _autoSaveTimer;
static const int _autoSaveInterval = 30;
NewZanoWallet(super.walletInfo)
: balance = ObservableMap.of({CryptoCurrency.zano: ZanoBalance(total: 0, unlocked: 0)}),
walletAddresses = NewZanoWalletAddresses(walletInfo),
syncStatus = NotConnectedSyncStatus() {
transactionHistory = ZanoTransactionHistory();
}
Future<void> init() async {
print("NewZanoWallet init");
if (walletInfo.isRecovery) {
print("is recovery");
}
_autoSaveTimer =
Timer.periodic(Duration(seconds: _autoSaveInterval), (_) async => await save());
}
String getTransactionAddress(int accountIndex, int addressIndex) {
print("NewZanoWallet getTransactionAddress");
return "";
}
@override
ObservableMap<CryptoCurrency, ZanoBalance> balance;
@override
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
// TODO: implement calculateEstimatedFee
throw UnimplementedError();
}
@override
Future<void> changePassword(String password) {
// TODO: implement changePassword
throw UnimplementedError();
}
@override
void close() {
// TODO: implement close
}
@override
Future<void> connectToNode({required Node node}) async {
print("NewZanoWallet connecttoNode");
try {
syncStatus = ConnectingSyncStatus();
_setupNode(address: "195.201.107.230:33336", login: "", password: "");
syncStatus = ConnectedSyncStatus();
} catch (e) {
syncStatus = FailedSyncStatus();
print("connectToNode error $e");
}
}
@override
Future<PendingTransaction> createTransaction(Object credentials) {
// TODO: implement createTransaction
throw UnimplementedError();
}
@override
Future<Map<String, ZanoTransactionInfo>> fetchTransactions() {
// TODO: implement fetchTransactions
throw UnimplementedError();
}
@override
ZanoWalletKeys get keys => ZanoWalletKeys(
privateSpendKey: "", privateViewKey: "", publicSpendKey: "", publicViewKey: "");
@override
Future<void> renameWalletFiles(String newWalletName) {
// TODO: implement renameWalletFiles
throw UnimplementedError();
}
@override
Future<void> rescan({required int height}) {
// TODO: implement rescan
throw UnimplementedError();
}
@override
Future<void> save() async {
await walletAddresses.updateAddressesInBox();
if (hWallet != null) await zano_wallet.store(hWallet!);
}
@override
// TODO: implement seed
String? seed = "Тут пока пусто";
@override
Future<void> startSync() {
// TODO: implement startSync
throw UnimplementedError();
}
@override
Future<void>? updateBalance() {
// TODO: implement updateBalance
throw UnimplementedError();
}
@override
NewZanoWalletAddresses walletAddresses;
CreateWalletResult? createWalletResult;
List<Balance>? balances;
int? hWallet;
final assetIds = <String, String>{};
final _setupNodeNative =
zanoApi.lookup<NativeFunction<setup_node>>('setup_node').asFunction<SetupNode>();
final _createWalletNative =
zanoApi.lookup<NativeFunction<create_wallet>>('create_wallet').asFunction<CreateWallet>();
final _loadWalletNative =
zanoApi.lookup<NativeFunction<_load_wallet>>('load_wallet').asFunction<_LoadWallet>();
bool _setupNode(
{required String address,
required String login,
required String password,
bool useSSL = false,
bool isLightWallet = false}) {
final addressPointer = address.toNativeUtf8();
final loginPointer = login.toNativeUtf8();
final passwordPointer = password.toNativeUtf8();
final errorMessagePointer = ''.toNativeUtf8();
print(
"setup_node address $address login $login password $password useSSL $useSSL isLightWallet $isLightWallet");
final result = _intToBool(_setupNodeNative(addressPointer, loginPointer, passwordPointer,
_boolToInt(useSSL), _boolToInt(isLightWallet), errorMessagePointer));
print("setup_node result $result");
calloc.free(addressPointer);
calloc.free(loginPointer);
calloc.free(passwordPointer);
return result;
}
String _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();
print("create_wallet path $path password $password language $language");
final result = _convertUTF8ToString(
pointer: _createWalletNative(
pathPointer, passwordPointer, languagePointer, nettype, errorMessagePointer));
print("create_wallet $result");
calloc.free(pathPointer);
calloc.free(passwordPointer);
calloc.free(languagePointer);
return result;
}
void createWallet({required String path, required String password}) {
final createResult = _createWalletSync(path: path, password: password, language: "");
final address = _parseResult(createResult)!;
walletAddresses.address = address;
}
String loadWallet(String path, String password) {
print('load_wallet path $path password $password');
final pathPointer = path.toNativeUtf8();
final passwordPointer = password.toNativeUtf8();
final result = _convertUTF8ToString(
pointer: _loadWalletNative(pathPointer, passwordPointer, 0),
);
print('load_wallet result $result');
return result;
}
int _boolToInt(bool value) => value ? 1 : 0;
bool _intToBool(int value) => value != 0;
String _convertUTF8ToString({required Pointer<Utf8> pointer}) {
final str = pointer.toDartString();
calloc.free(pointer);
return str;
}
// TODO: kind of stupid thing, in one method parsing json and then setting properties of a class
String? _parseResult(String result) {
final map = json.decode(result) as Map<String, dynamic>;
if (map['result'] != null) {
createWalletResult =
CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
balances = createWalletResult!.wi.balances;
hWallet = createWalletResult!.walletId;
assetIds.clear();
for (final balance in createWalletResult!.wi.balances) {
assetIds[balance.assetInfo.assetId] = balance.assetInfo.ticker;
}
return createWalletResult!.wi.address;
}
return null;
}
}

View file

@ -27,8 +27,10 @@ class PendingZanoTransaction with PendingTransaction {
String get hex => ''; String get hex => '';
@override @override
String get amountFormatted => AmountConverter.amountIntToString( String get amountFormatted {
return AmountConverter.amountIntToString(
cryptoCurrency, pendingTransactionDescription.amount); cryptoCurrency, pendingTransactionDescription.amount);
}
@override @override
String get feeFormatted => AmountConverter.amountIntToString( String get feeFormatted => AmountConverter.amountIntToString(

View file

@ -1,53 +1,23 @@
import 'package:cw_core/balance.dart'; import 'package:cw_core/balance.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_core/monero_balance.dart'; import 'package:cw_core/monero_balance.dart';
import 'package:cw_zano/api/balance_list.dart'; import 'package:cw_zano/api/balance_list.dart';
import 'package:cw_zano/api/structs/zano_balance_row.dart'; import 'package:cw_zano/api/structs/zano_balance_row.dart';
class ZanoBalance extends Balance { class ZanoBalance extends Balance {
ZanoBalance(super.available, super.additional); final int total;
late int unlockedBalance; final int unlocked;
@override ZanoBalance({required this.total, required this.unlocked}): super(unlocked, 0);
// TODO: implement formattedAdditionalBalance
String get formattedAdditionalBalance {
// TODO: fix it
return "0";
}
@override @override
// TODO: implement formattedAvailableBalance String get formattedAdditionalBalance => moneroAmountToString(amount: additional);
String get formattedAvailableBalance {
// TODO: fix it @override
return "0"; String get formattedAvailableBalance => moneroAmountToString(amount: unlocked);
}
@override
String get formattedFrozenBalance => total == unlocked ? '' : moneroAmountToString(amount: total - unlocked);
} }
Map<CryptoCurrency, ZanoBalance> getZanoBalance() {
// TODO: fix it
return { CryptoCurrency.zano: ZanoBalance(0, 0) };
}
/*Map<CryptoCurrency, MoneroBalance> getZanoBalance({required int accountIndex}) {
final fullBalances = getZanoFullBalance(accountIndex: accountIndex);
final unlockedBalances = getZanoUnlockedBalance(accountIndex: accountIndex);
final zanoBalances = <CryptoCurrency, MoneroBalance>{};
final balancesLength = fullBalances.length;
for (int i = 0; i < balancesLength; i++) {
final assetType = fullBalances[i].getAssetType();
final fullBalance = fullBalances[i].getAmount();
final unlockedBalance = unlockedBalances[i].getAmount();
final moneroBalance = MoneroBalance(
fullBalance: fullBalance, unlockedBalance: unlockedBalance);
final currency = CryptoCurrency.fromString(assetType);
if (inactiveBalances.indexOf(currency) >= 0) {
continue;
}
zanoBalances[currency] = moneroBalance;
}
return zanoBalances;
}*/

View file

@ -1,5 +1,6 @@
import 'package:cw_core/transaction_info.dart'; import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/monero_amount_format.dart'; import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_zano/api/model/history.dart';
import 'package:cw_zano/api/structs/transaction_info_row.dart'; import 'package:cw_zano/api/structs/transaction_info_row.dart';
import 'package:cw_core/parseBoolFromString.dart'; import 'package:cw_core/parseBoolFromString.dart';
import 'package:cw_core/transaction_direction.dart'; import 'package:cw_core/transaction_direction.dart';
@ -19,7 +20,22 @@ class ZanoTransactionInfo extends TransactionInfo {
this.fee, this.fee,
this.confirmations); this.confirmations);
ZanoTransactionInfo.fromMap(Map<String, Object> map) ZanoTransactionInfo.fromHistory(History history)
: id = history.txHash,
height = history.height,
direction = history.subtransfers.first.isIncome ? TransactionDirection.incoming :
TransactionDirection.outgoing,
date = DateTime.fromMillisecondsSinceEpoch(history.timestamp * 1000),
isPending = false,
amount = history.subtransfers.first.amount,
accountIndex = 0,
addressIndex = 0,
fee = history.fee,
confirmations = 1,
assetType = 'ZANO', // TODO: FIXIT:
recipientAddress = history.remoteAddresses.isNotEmpty ? history.remoteAddresses.first : '';
/*ZanoTransactionInfo.fromMap(Map<String, Object> map)
: id = (map['hash'] ?? '') as String, : id = (map['hash'] ?? '') as String,
height = (map['height'] ?? 0) as int, height = (map['height'] ?? 0) as int,
direction = direction =
@ -33,9 +49,9 @@ class ZanoTransactionInfo extends TransactionInfo {
addressIndex = map['addressIndex'] as int, addressIndex = map['addressIndex'] as int,
confirmations = map['confirmations'] as int, confirmations = map['confirmations'] as int,
key = getTxKey((map['hash'] ?? '') as String), key = getTxKey((map['hash'] ?? '') as String),
fee = map['fee'] as int? ?? 0; fee = map['fee'] as int? ?? 0;*/
ZanoTransactionInfo.fromRow(TransactionInfoRow row) /*ZanoTransactionInfo.fromRow(TransactionInfoRow row)
: id = row.getHash(), : id = row.getHash(),
height = row.blockHeight, height = row.blockHeight,
direction = parseTransactionDirectionFromInt(row.direction) ?? direction = parseTransactionDirectionFromInt(row.direction) ??
@ -48,7 +64,7 @@ class ZanoTransactionInfo extends TransactionInfo {
confirmations = row.confirmations, confirmations = row.confirmations,
key = null, //getTxKey(row.getHash()), key = null, //getTxKey(row.getHash()),
fee = row.fee, fee = row.fee,
assetType = row.getAssetType(); assetType = row.getAssetType();*/
final String id; final String id;
final int height; final int height;

View file

@ -1,37 +1,35 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:ffi';
import 'dart:io'; import 'dart:io';
import 'dart:math';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_zano/api/zano_output.dart';
import 'package:cw_zano/zano_transaction_creation_credentials.dart';
import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_zano/zano_transaction_creation_exception.dart';
import 'package:cw_zano/zano_transaction_info.dart';
import 'package:cw_zano/zano_wallet_addresses.dart';
import 'package:cw_zano/api/calls.dart' as calls;
import 'package:cw_core/monero_wallet_utils.dart'; import 'package:cw_core/monero_wallet_utils.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_zano/api/calls.dart' as calls;
import 'package:cw_zano/api/model/destination.dart';
import 'package:cw_zano/api/model/history.dart';
import 'package:cw_zano/api/model/transfer_params.dart';
import 'package:cw_zano/api/model/zano_wallet_keys.dart';
import 'package:cw_zano/api/structs/pending_transaction.dart'; import 'package:cw_zano/api/structs/pending_transaction.dart';
import 'package:flutter/foundation.dart';
import 'package:mobx/mobx.dart';
import 'package:cw_zano/api/transaction_history.dart'
as zano_transaction_history;
//import 'package:cw_zano/wallet.dart'; //import 'package:cw_zano/wallet.dart';
import 'package:cw_zano/api/wallet.dart' as zano_wallet; import 'package:cw_zano/api/wallet.dart' as zano_wallet;
import 'package:cw_zano/api/transaction_history.dart' as transaction_history; import 'package:cw_zano/api/zano_api.dart';
import 'package:cw_zano/api/zano_output.dart';
import 'package:cw_zano/pending_zano_transaction.dart'; import 'package:cw_zano/pending_zano_transaction.dart';
import 'package:cw_core/monero_wallet_keys.dart';
import 'package:cw_core/monero_balance.dart';
import 'package:cw_zano/zano_transaction_history.dart';
import 'package:cw_core/account.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/monero_transaction_priority.dart';
import 'package:cw_zano/zano_balance.dart'; import 'package:cw_zano/zano_balance.dart';
import 'package:cw_zano/zano_transaction_creation_credentials.dart';
import 'package:cw_zano/zano_transaction_history.dart';
import 'package:cw_zano/zano_transaction_info.dart';
import 'package:cw_zano/zano_wallet_addresses.dart';
import 'package:ffi/ffi.dart';
import 'package:mobx/mobx.dart';
part 'zano_wallet.g.dart'; part 'zano_wallet.g.dart';
@ -39,21 +37,16 @@ const moneroBlockSize = 1000;
class ZanoWallet = ZanoWalletBase with _$ZanoWallet; class ZanoWallet = ZanoWalletBase with _$ZanoWallet;
abstract class ZanoWalletBase typedef _load_wallet = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>, Int8);
extends WalletBase<ZanoBalance, ZanoTransactionHistory, ZanoTransactionInfo> typedef _LoadWallet = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>, int);
with Store {
ZanoWalletBase.simple({required WalletInfo walletInfo})
: balance = ObservableMap(),
_isTransactionUpdating = false,
_hasSyncAfterStartup = false,
walletAddresses = ZanoWalletAddresses(walletInfo),
syncStatus = NotConnectedSyncStatus(),
super(walletInfo) {
transactionHistory = ZanoTransactionHistory();
}
ZanoWalletBase({required WalletInfo walletInfo})
: balance = ObservableMap.of({CryptoCurrency.zano: ZanoBalance(0, 0)}), const int zanoMixin = 10;
abstract class ZanoWalletBase
extends WalletBase<ZanoBalance, ZanoTransactionHistory, ZanoTransactionInfo> with Store {
ZanoWalletBase(WalletInfo walletInfo)
: balance = ObservableMap.of({CryptoCurrency.zano: ZanoBalance(total: 0, unlocked: 0)}),
_isTransactionUpdating = false, _isTransactionUpdating = false,
_hasSyncAfterStartup = false, _hasSyncAfterStartup = false,
walletAddresses = ZanoWalletAddresses(walletInfo), walletAddresses = ZanoWalletAddresses(walletInfo),
@ -70,6 +63,9 @@ abstract class ZanoWalletBase
});*/ });*/
} }
List<History> history = [];
String assetId = '';
static const int _autoSaveInterval = 30; static const int _autoSaveInterval = 30;
@override @override
@ -84,20 +80,11 @@ abstract class ZanoWalletBase
ObservableMap<CryptoCurrency, ZanoBalance> balance; ObservableMap<CryptoCurrency, ZanoBalance> balance;
@override @override
String get seed { String seed = '';
// TODO: fix it
//return calls.seed(hWallet);
return "test";
/**zano_wallet.getSeed();*/
}
@override @override
// TODO: ?? why monero ZanoWalletKeys keys = ZanoWalletKeys(
MoneroWalletKeys get keys => MoneroWalletKeys( privateSpendKey: '', privateViewKey: '', publicSpendKey: '', publicViewKey: '');
privateSpendKey: zano_wallet.getSecretSpendKey(),
privateViewKey: zano_wallet.getSecretViewKey(),
publicSpendKey: zano_wallet.getPublicSpendKey(),
publicViewKey: zano_wallet.getPublicViewKey());
zano_wallet.SyncListener? _listener; zano_wallet.SyncListener? _listener;
/**ReactionDisposer? _onAccountChangeReaction;*/ /**ReactionDisposer? _onAccountChangeReaction;*/
@ -115,21 +102,20 @@ abstract class ZanoWalletBase
Future<void> init() async { Future<void> init() async {
await walletAddresses.init(); await walletAddresses.init();
balance ///balance.addAll(getZanoBalance(/**accountIndex: walletAddresses.account?.id ?? 0*/));
.addAll(getZanoBalance(/**accountIndex: walletAddresses.account?.id ?? 0*/));
_setListeners(); _setListeners();
await updateTransactions(); await updateTransactions();
if (walletInfo.isRecovery) { if (walletInfo.isRecovery) {
zano_wallet.setRecoveringFromSeed(isRecovery: walletInfo.isRecovery); ///zano_wallet.setRecoveringFromSeed(isRecovery: walletInfo.isRecovery);
if (zano_wallet.getCurrentHeight(hWallet) <= 1) { if (zano_wallet.getCurrentHeight(hWallet) <= 1) {
zano_wallet.setRefreshFromBlockHeight(height: walletInfo.restoreHeight); zano_wallet.setRefreshFromBlockHeight(height: walletInfo.restoreHeight);
} }
} }
_autoSaveTimer = Timer.periodic( _autoSaveTimer =
Duration(seconds: _autoSaveInterval), (_) async => await save()); Timer.periodic(Duration(seconds: _autoSaveInterval), (_) async => await save());
} }
@override @override
@ -155,7 +141,7 @@ abstract class ZanoWalletBase
/*socksProxyAddress: node.socksProxyAddress*/ /*socksProxyAddress: node.socksProxyAddress*/
); );
zano_wallet.setTrustedDaemon(node.trusted); //zano_wallet.setTrustedDaemon(node.trusted);
syncStatus = ConnectedSyncStatus(); syncStatus = ConnectedSyncStatus();
} catch (e) { } catch (e) {
syncStatus = FailedSyncStatus(); syncStatus = FailedSyncStatus();
@ -171,9 +157,10 @@ abstract class ZanoWalletBase
try { try {
syncStatus = AttemptingSyncStatus(); syncStatus = AttemptingSyncStatus();
zano_wallet.startRefresh(); //zano_wallet.startRefresh();
print("start refresh");
_setListeners(); _setListeners();
_listener?.start(); _listener?.start(this, hWallet);
} catch (e) { } catch (e) {
syncStatus = FailedSyncStatus(); syncStatus = FailedSyncStatus();
print(e); print(e);
@ -183,7 +170,38 @@ abstract class ZanoWalletBase
@override @override
Future<PendingTransaction> createTransaction(Object credentials) async { Future<PendingTransaction> createTransaction(Object credentials) async {
final _credentials = credentials as ZanoTransactionCreationCredentials; final creds = credentials as ZanoTransactionCreationCredentials;
final output = creds.outputs.first;
final address = output.isParsedAddress && (output.extractedAddress?.isNotEmpty ?? false)
? output.extractedAddress!
: output.address;
final amount = output.sendAll ? null : output.cryptoAmount!.replaceAll(',', '.');
final int? formattedAmount = output.sendAll ? null : output.formattedCryptoAmount;
final fee = calculateEstimatedFee(creds.priority);
// final result = await calls.transfer(
// hWallet,
// TransferParams(
// destinations: [
// Destination(
// amount: amount!,
// address: address,
// assetId: assetId,
// )
// ],
// fee: fee,
// mixin: zanoMixin,
// paymentId: '', // TODO: fixit
// comment: output.note ?? '',
// pushPayer: false,
// hideReceiver: false,
// ));
int iAmount = (double.parse(amount!) * pow(10, 12)).toInt();
final description = PendingTransactionDescription(
amount: iAmount, fee: fee, hash: 'fade', pointerAddress: 0);
final transaction = PendingZanoTransaction(description, CryptoCurrency.zano);
return transaction;
/*final _credentials = credentials as ZanoTransactionCreationCredentials;
final outputs = _credentials.outputs; final outputs = _credentials.outputs;
final hasMultiDestination = outputs.length > 1; final hasMultiDestination = outputs.length > 1;
final assetType = final assetType =
@ -249,29 +267,12 @@ abstract class ZanoWalletBase
priorityRaw: _credentials.priority.serialize()); priorityRaw: _credentials.priority.serialize());
} }
return PendingZanoTransaction(pendingTransactionDescription, assetType); return PendingZanoTransaction(pendingTransactionDescription, assetType);*/
} }
@override @override
int calculateEstimatedFee(TransactionPriority priority, int? amount) { int calculateEstimatedFee(TransactionPriority priority, [int? amount = null]) {
// FIXME: hardcoded value; return calls.getCurrentTxFee(priority.raw);
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;
} }
@override @override
@ -310,7 +311,7 @@ abstract class ZanoWalletBase
zano_wallet.setPasswordSync(password); zano_wallet.setPasswordSync(password);
} }
Future<int> getNodeHeight() async => zano_wallet.getNodeHeight(); //Future<int> getNodeHeight() async => zano_wallet.getNodeHeight();
Future<bool> isConnected() async => zano_wallet.isConnected(); Future<bool> isConnected() async => zano_wallet.isConnected();
@ -334,18 +335,37 @@ abstract class ZanoWalletBase
} }
String getTransactionAddress(int accountIndex, int addressIndex) => String getTransactionAddress(int accountIndex, int addressIndex) =>
zano_wallet.getAddress( zano_wallet.getAddress(accountIndex: accountIndex, addressIndex: addressIndex);
accountIndex: accountIndex, addressIndex: addressIndex);
Future<void> _refreshTransactions() async {
final result = await calls.getRecentTxsAndInfo(hWallet: hWallet, offset: 0, count: 30);
final map = jsonDecode(result);
if (map == null || map["result"] == null || map["result"]["result"] == null) {
return;
}
if (map["result"]["result"]["transfers"] != null)
history = (map["result"]["result"]["transfers"] as List<dynamic>)
.map((e) => History.fromJson(e as Map<String, dynamic>))
.toList();
}
@override @override
Future<Map<String, ZanoTransactionInfo>> fetchTransactions() async { Future<Map<String, ZanoTransactionInfo>> fetchTransactions() async {
zano_transaction_history.refreshTransactions(); //zano_transaction_history.refreshTransactions();
return _getAllTransactions(null) await _refreshTransactions();
return history
.map<ZanoTransactionInfo>((history) => ZanoTransactionInfo.fromHistory(history))
.fold<Map<String, ZanoTransactionInfo>>(<String, ZanoTransactionInfo>{}, .fold<Map<String, ZanoTransactionInfo>>(<String, ZanoTransactionInfo>{},
(Map<String, ZanoTransactionInfo> acc, ZanoTransactionInfo tx) { (Map<String, ZanoTransactionInfo> acc, ZanoTransactionInfo tx) {
acc[tx.id] = tx; acc[tx.id] = tx;
return acc; return acc;
}); });
// return _getAllTransactions(null)
// .fold<Map<String, ZanoTransactionInfo>>(<String, ZanoTransactionInfo>{},
// (Map<String, ZanoTransactionInfo> acc, ZanoTransactionInfo tx) {
// acc[tx.id] = tx;
// return acc;
// });
} }
Future<void> updateTransactions() async { Future<void> updateTransactions() async {
@ -365,11 +385,11 @@ abstract class ZanoWalletBase
} }
} }
List<ZanoTransactionInfo> _getAllTransactions(dynamic _) => // List<ZanoTransactionInfo> _getAllTransactions(dynamic _) =>
zano_transaction_history // zano_transaction_history
.getAllTransations() // .getAllTransations()
.map((row) => ZanoTransactionInfo.fromRow(row)) // .map((row) => ZanoTransactionInfo.fromRow(row))
.toList(); // .toList();
void _setListeners() { void _setListeners() {
_listener?.stop(); _listener?.stop();
@ -385,36 +405,39 @@ abstract class ZanoWalletBase
if (currentHeight <= 1) { if (currentHeight <= 1) {
final height = _getHeightByDate(walletInfo.date); final height = _getHeightByDate(walletInfo.date);
zano_wallet.setRecoveringFromSeed(isRecovery: true); ///zano_wallet.setRecoveringFromSeed(isRecovery: true);
zano_wallet.setRefreshFromBlockHeight(height: height); zano_wallet.setRefreshFromBlockHeight(height: height);
} }
} }
int _getHeightDistance(DateTime date) { // int _getHeightDistance(DateTime date) {
final distance = // final distance =
DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch; // DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch;
final daysTmp = (distance / 86400).round(); // final daysTmp = (distance / 86400).round();
final days = daysTmp < 1 ? 1 : daysTmp; // final days = daysTmp < 1 ? 1 : daysTmp;
return days * 1000; // return days * 1000;
} // }
int _getHeightByDate(DateTime date) { int _getHeightByDate(DateTime date) {
final nodeHeight = zano_wallet.getNodeHeightSync(); // TODO: !!! 12/10 commented
final heightDistance = _getHeightDistance(date);
if (nodeHeight <= 0) {
return 0; return 0;
// final nodeHeight = zano_wallet.getNodeHeightSync();
// final heightDistance = _getHeightDistance(date);
// if (nodeHeight <= 0) {
// return 0;
// }
// return nodeHeight - heightDistance;
} }
return nodeHeight - heightDistance; void _askForUpdateBalance() {
print("ask for update balance");
//balance.addAll(getZanoBalance());
} }
void _askForUpdateBalance() => Future<void> _askForUpdateTransactionHistory() async => await updateTransactions();
balance.addAll(getZanoBalance());
Future<void> _askForUpdateTransactionHistory() async =>
await updateTransactions();
void _onNewBlock(int height, int blocksLeft, double ptc) async { void _onNewBlock(int height, int blocksLeft, double ptc) async {
try { try {
@ -455,4 +478,24 @@ abstract class ZanoWalletBase
print(e.toString()); print(e.toString());
} }
} }
final _loadWalletNative =
zanoApi.lookup<NativeFunction<_load_wallet>>('load_wallet').asFunction<_LoadWallet>();
String loadWallet(String path, String password) {
print('load_wallet path $path password $password');
final pathPointer = path.toNativeUtf8();
final passwordPointer = password.toNativeUtf8();
final result = _convertUTF8ToString(
pointer: _loadWalletNative(pathPointer, passwordPointer, 0),
);
print('load_wallet result $result');
return result;
}
String _convertUTF8ToString({required Pointer<Utf8> pointer}) {
final str = pointer.toDartString();
calloc.free(pointer);
return str;
}
} }

View file

@ -1,8 +1,13 @@
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/node.dart'; import 'package:cw_core/node.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/monero_wallet_utils.dart'; import 'package:cw_core/monero_wallet_utils.dart';
import 'package:cw_zano/api/model/create_wallet_result.dart';
import 'package:cw_zano/new_zano_wallet.dart';
import 'package:cw_zano/zano_balance.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:cw_zano/api/wallet_manager.dart' as zano_wallet_manager; import 'package:cw_zano/api/wallet_manager.dart' as zano_wallet_manager;
import 'package:cw_zano/api/wallet.dart' as zano_wallet; import 'package:cw_zano/api/wallet.dart' as zano_wallet;
@ -14,6 +19,7 @@ import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:mobx/mobx.dart';
class ZanoNewWalletCredentials extends WalletCredentials { class ZanoNewWalletCredentials extends WalletCredentials {
ZanoNewWalletCredentials({required String name, String? password}) ZanoNewWalletCredentials({required String name, String? password})
@ -22,10 +28,7 @@ class ZanoNewWalletCredentials extends WalletCredentials {
class ZanoRestoreWalletFromSeedCredentials extends WalletCredentials { class ZanoRestoreWalletFromSeedCredentials extends WalletCredentials {
ZanoRestoreWalletFromSeedCredentials( ZanoRestoreWalletFromSeedCredentials(
{required String name, {required String name, required String password, required int height, required this.mnemonic})
required String password,
required int height,
required this.mnemonic})
: super(name: name, password: password, height: height); : super(name: name, password: password, height: height);
final String mnemonic; final String mnemonic;
@ -53,10 +56,8 @@ class ZanoRestoreWalletFromKeysCredentials extends WalletCredentials {
final String spendKey; final String spendKey;
} }
class ZanoWalletService extends WalletService< class ZanoWalletService extends WalletService<ZanoNewWalletCredentials,
ZanoNewWalletCredentials, ZanoRestoreWalletFromSeedCredentials, ZanoRestoreWalletFromKeysCredentials> {
ZanoRestoreWalletFromSeedCredentials,
ZanoRestoreWalletFromKeysCredentials> {
ZanoWalletService(this.walletInfoSource); ZanoWalletService(this.walletInfoSource);
final Box<WalletInfo> walletInfoSource; final Box<WalletInfo> walletInfoSource;
@ -69,18 +70,38 @@ class ZanoWalletService extends WalletService<
@override @override
WalletType getType() => WalletType.zano; WalletType getType() => WalletType.zano;
// @override
// Future<ZanoWallet> create(WalletCredentials credentials) async {
// try {
// final wallet = ZanoWallet(credentials.walletInfo!);
// wallet.connectToNode(node: Node()); // TODO: Node() ???
// //wallet.setupNode(address: "195.201.107.230:33336", login: "", password: "");
// final path = await pathForWallet(name: credentials.name, type: getType());
// wallet.createWallet(path: path, password: credentials.password!);
// return wallet;
// } catch (e) {
// print("ZanoWalletService.create error $e");
// rethrow;
// }
// }
@override @override
Future<ZanoWallet> create(ZanoNewWalletCredentials credentials) async { Future<ZanoWallet> create(WalletCredentials credentials) async {
try { try {
final wallet = ZanoWallet.simple(walletInfo: credentials.walletInfo!); final wallet = ZanoWallet(credentials.walletInfo!);
wallet.connectToNode(node: Node()); await wallet.connectToNode(node: Node());
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
final result = await zano_wallet_manager.createWallet( final result = await zano_wallet_manager.createWallet(
language: "", path: path, password: credentials.password!); language: "", path: path, password: credentials.password!);
hWallet = -1; print("create wallet result $result");
wallet.hWallet = hWallet; final map = json.decode(result) as Map<String, dynamic>;
// TODO: remove it if (map['result'] != null) {
calls.store(hWallet); final createWalletResult =
CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
_parseCreateWalletResult(createWalletResult, wallet);
}
// TODO: remove it TODO why?
await calls.store(hWallet);
await wallet.init(); await wallet.init();
return wallet; return wallet;
} catch (e) { } catch (e) {
@ -111,37 +132,36 @@ class ZanoWalletService extends WalletService<
await repairOldAndroidWallet(name); await repairOldAndroidWallet(name);
} }
await zano_wallet_manager final walletInfo = walletInfoSource.values
.openWalletAsync({'path': path, 'password': password}); .firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
final walletInfo = walletInfoSource.values.firstWhereOrNull( final wallet = ZanoWallet(walletInfo);
(info) => info.id == WalletBase.idFor(name, getType()))!; await wallet.connectToNode(node: Node());
final wallet = ZanoWallet(walletInfo: walletInfo); final result = wallet.loadWallet(path, password);
/*final isValid = wallet.walletAddresses.validate(); print("load wallet result $result");
final map = json.decode(result) as Map<String, dynamic>;
if (!isValid) { if (map['result'] != null) {
await restoreOrResetWalletFiles(name); final createWalletResult =
wallet.close(); CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
return openWallet(name, password); _parseCreateWalletResult(createWalletResult, wallet);
}*/ }
await calls.store(hWallet);
await wallet.init(); await wallet.init();
return wallet; return wallet;
} catch (e) { } catch (e) {
// TODO: Implement Exception for wallet list service. rethrow;
}
if ((e.toString().contains('bad_alloc') ||
(e is WalletOpeningException &&
(e.message == 'std::bad_alloc' ||
e.message.contains('bad_alloc')))) ||
(e.toString().contains('does not correspond') ||
(e is WalletOpeningException &&
e.message.contains('does not correspond')))) {
await restoreOrResetWalletFiles(name);
return openWallet(name, password);
} }
rethrow; void _parseCreateWalletResult(CreateWalletResult result, ZanoWallet wallet) {
hWallet = result.walletId;
wallet.hWallet = hWallet;
wallet.walletAddresses.address = result.wi.address;
final balance = result.wi.balances.first;
wallet.assetId = balance.assetInfo.assetId;
wallet.balance = ObservableMap.of(
{CryptoCurrency.zano: ZanoBalance(total: balance.total, unlocked: balance.unlocked)});
if (result.recentHistory.history != null) {
wallet.history = result.recentHistory.history!;
} }
} }
@ -161,11 +181,10 @@ class ZanoWalletService extends WalletService<
} }
@override @override
Future<void> rename( Future<void> rename(String currentName, String password, String newName) async {
String currentName, String password, String newName) async { final currentWalletInfo = walletInfoSource.values
final currentWalletInfo = walletInfoSource.values.firstWhere( .firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
(info) => info.id == WalletBase.idFor(currentName, getType())); final currentWallet = ZanoWallet(currentWalletInfo);
final currentWallet = ZanoWallet(walletInfo: currentWalletInfo);
await currentWallet.renameWalletFiles(newName); await currentWallet.renameWalletFiles(newName);
@ -177,8 +196,7 @@ class ZanoWalletService extends WalletService<
} }
@override @override
Future<ZanoWallet> restoreFromKeys( Future<ZanoWallet> restoreFromKeys(ZanoRestoreWalletFromKeysCredentials credentials) async {
ZanoRestoreWalletFromKeysCredentials credentials) async {
try { try {
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await zano_wallet_manager.restoreFromKeys( await zano_wallet_manager.restoreFromKeys(
@ -189,7 +207,7 @@ class ZanoWalletService extends WalletService<
address: credentials.address, address: credentials.address,
viewKey: credentials.viewKey, viewKey: credentials.viewKey,
spendKey: credentials.spendKey); spendKey: credentials.spendKey);
final wallet = ZanoWallet(walletInfo: credentials.walletInfo!); final wallet = ZanoWallet(credentials.walletInfo!);
await wallet.init(); await wallet.init();
return wallet; return wallet;
@ -201,18 +219,21 @@ class ZanoWalletService extends WalletService<
} }
@override @override
Future<ZanoWallet> restoreFromSeed( Future<ZanoWallet> restoreFromSeed(ZanoRestoreWalletFromSeedCredentials credentials) async {
ZanoRestoreWalletFromSeedCredentials credentials) async {
try { try {
final wallet = ZanoWallet(credentials.walletInfo!);
await wallet.connectToNode(node: Node());
final path = await pathForWallet(name: credentials.name, type: getType()); final path = await pathForWallet(name: credentials.name, type: getType());
await zano_wallet_manager.restoreFromSeed( final result = calls.restoreWalletFromSeed(path, credentials.password!, credentials.mnemonic);
path: path, print('restore wallet from seed result $result');
password: credentials.password!, final map = json.decode(result) as Map<String, dynamic>;
seed: credentials.mnemonic, if (map['result'] != null) {
restoreHeight: credentials.height!); final createWalletResult =
final wallet = ZanoWallet(walletInfo: credentials.walletInfo!); CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
_parseCreateWalletResult(createWalletResult, wallet);
}
await calls.store(hWallet);
await wallet.init(); await wallet.init();
return wallet; return wallet;
} catch (e) { } catch (e) {
// TODO: Implement Exception for wallet list service. // TODO: Implement Exception for wallet list service.
@ -227,16 +248,14 @@ class ZanoWalletService extends WalletService<
return; return;
} }
final oldAndroidWalletDirPath = final oldAndroidWalletDirPath = await outdatedAndroidPathForWalletDir(name: name);
await outdatedAndroidPathForWalletDir(name: name);
final dir = Directory(oldAndroidWalletDirPath); final dir = Directory(oldAndroidWalletDirPath);
if (!dir.existsSync()) { if (!dir.existsSync()) {
return; return;
} }
final newWalletDirPath = final newWalletDirPath = await pathForWalletDir(name: name, type: getType());
await pathForWalletDir(name: name, type: getType());
dir.listSync().forEach((f) { dir.listSync().forEach((f) {
final file = File(f.path); final file = File(f.path);

View file

@ -239,6 +239,8 @@ class AddressValidator extends TextValidator {
return [64]; return [64];
case CryptoCurrency.btcln: case CryptoCurrency.btcln:
return null; return null;
case CryptoCurrency.zano:
return [97];
default: default:
return []; return [];
} }

View file

@ -211,6 +211,8 @@ class WalletRestorePage extends BasePage {
final seedWords = final seedWords =
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text.split(' '); walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text.split(' ');
if (walletRestoreViewModel.type == WalletType.zano) return true;
if ((walletRestoreViewModel.type == WalletType.monero || if ((walletRestoreViewModel.type == WalletType.monero ||
walletRestoreViewModel.type == WalletType.haven) && walletRestoreViewModel.type == WalletType.haven) &&
seedWords.length != WalletRestoreViewModelBase.moneroSeedMnemonicLength) { seedWords.length != WalletRestoreViewModelBase.moneroSeedMnemonicLength) {

View file

@ -258,8 +258,8 @@ abstract class OutputBase with Store {
break; break;
case WalletType.dummy: case WalletType.dummy:
case WalletType.zano: case WalletType.zano:
// TODO: enter correct values maximumFractionDigits = 12;
throw UnimplementedError(); break;
default: default:
break; break;
} }

View file

@ -9,7 +9,7 @@ import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:cw_zano/api/calls.dart' as calls; import 'package:cw_zano/api/calls.dart' as calls;
import 'package:cw_zano/api/model/balance.dart'; import 'package:cw_zano/api/model/balance.dart';
import 'package:cw_zano/api/model/load_wallet_result.dart'; import 'package:cw_zano/api/model/create_wallet_result.dart';
import 'package:cw_zano/api/wallet.dart' as zano_wallet; import 'package:cw_zano/api/wallet.dart' as zano_wallet;
import 'package:cw_zano/api/wallet_manager.dart' as zano_wallet_manager; import 'package:cw_zano/api/wallet_manager.dart' as zano_wallet_manager;
import 'package:cw_zano/zano_wallet_service.dart'; import 'package:cw_zano/zano_wallet_service.dart';
@ -28,24 +28,21 @@ Future<void> main() async {
/// A callback that is invoked when an unhandled error occurs in the root /// A callback that is invoked when an unhandled error occurs in the root
/// isolate. /// isolate.
PlatformDispatcher.instance.onError = (error, stack) { PlatformDispatcher.instance.onError = (error, stack) {
ExceptionHandler.onError( ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
FlutterErrorDetails(exception: error, stack: stack));
return true; return true;
}; };
await setup(); await setup();
runApp(App()); runApp(App());
}, (error, stackTrace) async { }, (error, stackTrace) async {
ExceptionHandler.onError( ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stackTrace));
FlutterErrorDetails(exception: error, stack: stackTrace));
}); });
} }
final getIt = GetIt.instance; final getIt = GetIt.instance;
Future<void> setup() async { Future<void> setup() async {
getIt.registerFactory<KeyService>( getIt.registerFactory<KeyService>(() => KeyService(getIt.get<FlutterSecureStorage>()));
() => KeyService(getIt.get<FlutterSecureStorage>()));
} }
class App extends StatefulWidget { class App extends StatefulWidget {
@ -79,7 +76,7 @@ class _AppState extends State<App> {
} }
int hWallet = 0; int hWallet = 0;
CreateLoadRestoreWalletResult? lwr; CreateWalletResult? lwr;
List<Balance> balances = []; List<Balance> balances = [];
String seed = '', version = ''; String seed = '', version = '';
final assetIds = <String, String>{}; final assetIds = <String, String>{};
@ -107,11 +104,9 @@ Future<String?> create(String name) async {
final keyService = KeyService(FlutterSecureStorage()); final keyService = KeyService(FlutterSecureStorage());
final password = generateWalletPassword(); final password = generateWalletPassword();
credentials.password = password; credentials.password = password;
await keyService.saveWalletPassword( await keyService.saveWalletPassword(password: password, walletName: credentials.name);
password: password, walletName: credentials.name);
debugPrint('path $path password $password'); debugPrint('path $path password $password');
final result = zano_wallet_manager.createWalletSync( final result = zano_wallet_manager.createWalletSync(path: path, password: password, language: '');
path: path, password: password, language: '');
debugPrint('create result $result'); debugPrint('create result $result');
return _parseResult(result); return _parseResult(result);
} }
@ -122,8 +117,7 @@ Future<String?> connect(String name) async {
final path = await pathForWallet(name: name, type: WalletType.zano); final path = await pathForWallet(name: name, type: WalletType.zano);
final credentials = ZanoNewWalletCredentials(name: name); final credentials = ZanoNewWalletCredentials(name: name);
final keyService = KeyService(FlutterSecureStorage()); final keyService = KeyService(FlutterSecureStorage());
final password = final password = await keyService.getWalletPassword(walletName: credentials.name);
await keyService.getWalletPassword(walletName: credentials.name);
debugPrint('path $path password $password'); debugPrint('path $path password $password');
final result = await calls.loadWallet(path, password, 0); final result = await calls.loadWallet(path, password, 0);
return _parseResult(result); return _parseResult(result);
@ -137,8 +131,7 @@ Future<String?> restore(String name, String seed) async {
final keyService = KeyService(FlutterSecureStorage()); final keyService = KeyService(FlutterSecureStorage());
final password = generateWalletPassword(); final password = generateWalletPassword();
credentials.password = password; credentials.password = password;
await keyService.saveWalletPassword( await keyService.saveWalletPassword(password: password, walletName: credentials.name);
password: password, walletName: credentials.name);
debugPrint('path $path password $password'); debugPrint('path $path password $password');
var result = calls.restoreWalletFromSeed(path, password, seed); var result = calls.restoreWalletFromSeed(path, password, seed);
debugPrint('restore result $result'); debugPrint('restore result $result');
@ -148,8 +141,8 @@ Future<String?> restore(String name, String seed) async {
String? _parseResult(String result) { String? _parseResult(String result) {
final map = json.decode(result) as Map<String, dynamic>; final map = json.decode(result) as Map<String, dynamic>;
if (map['result'] != null) { if (map['result'] != null) {
lwr = CreateLoadRestoreWalletResult.fromJson(map['result'] as Map<String, dynamic>); lwr = CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
balances = lwr!.wi.balances; balances = lwr!.wi.balances;
hWallet = lwr!.walletId; hWallet = lwr!.walletId;
assetIds.clear(); assetIds.clear();
@ -204,14 +197,12 @@ class _DisconnectedWidgetState extends State<DisconnectedWidget> {
child: Column( child: Column(
children: [ children: [
TextField( TextField(
controller: _name, controller: _name, decoration: InputDecoration(labelText: 'Wallet name')),
decoration: InputDecoration(labelText: 'Wallet name')),
TextButton( TextButton(
child: Text('Connect and Open Wallet'), child: Text('Connect and Open Wallet'),
onPressed: () async { onPressed: () async {
//setState(() => _loading = true); //setState(() => _loading = true);
final preferences = final preferences = await SharedPreferences.getInstance();
await SharedPreferences.getInstance();
await preferences.setString(walletName, _name.text); await preferences.setString(walletName, _name.text);
final result = await connect(_name.text); final result = await connect(_name.text);
//setState(() => _loading = false); //setState(() => _loading = false);
@ -232,8 +223,7 @@ class _DisconnectedWidgetState extends State<DisconnectedWidget> {
child: Text('Create and Open Wallet'), child: Text('Create and Open Wallet'),
onPressed: () async { onPressed: () async {
//setState(() => _loading = true); //setState(() => _loading = true);
final preferences = final preferences = await SharedPreferences.getInstance();
await SharedPreferences.getInstance();
await preferences.setString(walletName, _name.text); await preferences.setString(walletName, _name.text);
final result = await create(_name.text); final result = await create(_name.text);
//setState(() => _loading = false); //setState(() => _loading = false);
@ -251,13 +241,11 @@ class _DisconnectedWidgetState extends State<DisconnectedWidget> {
height: 16, height: 16,
), ),
TextField( TextField(
controller: _seed, controller: _seed, decoration: InputDecoration(labelText: 'Wallet seed')),
decoration: InputDecoration(labelText: 'Wallet seed')),
TextButton( TextButton(
child: Text('Restore from seed'), child: Text('Restore from seed'),
onPressed: () async { onPressed: () async {
final preferences = final preferences = await SharedPreferences.getInstance();
await SharedPreferences.getInstance();
await preferences.setString(walletName, _name.text); await preferences.setString(walletName, _name.text);
final result = await restore(_name.text, _seed.text); final result = await restore(_name.text, _seed.text);
if (result != null) { if (result != null) {

View file

@ -1,3 +1,4 @@
import 'package:cw_zano/new_zano_wallet.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_credentials.dart';