mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 03:59:23 +00:00
wallet recovery
This commit is contained in:
parent
2d886e1213
commit
8d3dd6f202
23 changed files with 2357 additions and 2000 deletions
|
@ -96,6 +96,8 @@ class AmountConverter {
|
|||
case CryptoCurrency.xnzd:
|
||||
case CryptoCurrency.xusd:
|
||||
return _moneroAmountToString(amount);
|
||||
case CryptoCurrency.zano:
|
||||
return _moneroAmountToString(amount);
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import 'package:cw_core/balance.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/transaction_info.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_service.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
|
||||
import 'package:hive/hive.dart';
|
||||
import 'dummy_wallet_creation_credentials.dart';
|
||||
|
||||
|
@ -15,7 +18,7 @@ class DummyWalletService extends WalletService<DummyNewWalletCredentials, DummyR
|
|||
final Box<WalletInfo> walletInfoSource;
|
||||
|
||||
@override
|
||||
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> create(DummyNewWalletCredentials credentials) => throw UnimplementedError();
|
||||
Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> create(WalletCredentials credentials) => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
WalletType getType() => WalletType.dummy;
|
||||
|
|
|
@ -20,6 +20,9 @@ dependencies:
|
|||
cw_core:
|
||||
path: ../cw_core
|
||||
|
||||
cw_zano:
|
||||
path: ../cw_zano
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
|
|
@ -419,6 +419,12 @@ extern "C"
|
|||
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)
|
||||
{
|
||||
return strdup(plain_wallet::async_call(method_name, instance_id, params).c_str());
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:convert';
|
|||
import 'package:cw_zano/api/model/recent_history.dart';
|
||||
import 'package:cw_zano/api/model/wi.dart';
|
||||
|
||||
class CreateLoadRestoreWalletResult {
|
||||
class CreateWalletResult {
|
||||
final String name;
|
||||
final String pass;
|
||||
final RecentHistory recentHistory;
|
||||
|
@ -14,7 +14,7 @@ class CreateLoadRestoreWalletResult {
|
|||
final int walletLocalBcSize;
|
||||
final Wi wi;
|
||||
|
||||
CreateLoadRestoreWalletResult(
|
||||
CreateWalletResult(
|
||||
{required this.name,
|
||||
required this.pass,
|
||||
required this.recentHistory,
|
||||
|
@ -25,8 +25,8 @@ class CreateLoadRestoreWalletResult {
|
|||
required this.walletLocalBcSize,
|
||||
required this.wi});
|
||||
|
||||
factory CreateLoadRestoreWalletResult.fromJson(Map<String, dynamic> json) =>
|
||||
CreateLoadRestoreWalletResult(
|
||||
factory CreateWalletResult.fromJson(Map<String, dynamic> json) =>
|
||||
CreateWalletResult(
|
||||
name: json['name'] as String,
|
||||
pass: json['pass'] as String,
|
||||
recentHistory: RecentHistory.fromJson(
|
|
@ -62,7 +62,7 @@ class History {
|
|||
.map((e) => Subtransfer.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
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,
|
||||
txHash: json['tx_hash'] as String,
|
||||
txType: json['tx_type'] as int,
|
||||
|
|
12
cw_zano/lib/api/model/zano_wallet_keys.dart
Normal file
12
cw_zano/lib/api/model/zano_wallet_keys.dart
Normal 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;
|
||||
}
|
|
@ -32,9 +32,9 @@ final transactionCreateMultDestNative = zanoApi
|
|||
'transaction_create_mult_dest')
|
||||
.asFunction<TransactionCreateMultDest>();
|
||||
|
||||
final transactionCommitNative = zanoApi
|
||||
.lookup<NativeFunction<transaction_commit>>('transaction_commit')
|
||||
.asFunction<TransactionCommit>();
|
||||
// final transactionCommitNative = zanoApi
|
||||
// .lookup<NativeFunction<transaction_commit>>('transaction_commit')
|
||||
// .asFunction<TransactionCommit>();
|
||||
|
||||
final getTxKeyNative = zanoApi
|
||||
.lookup<NativeFunction<get_tx_key>>('get_tx_key')
|
||||
|
@ -53,11 +53,11 @@ String getTxKey(String txId) {
|
|||
return '';
|
||||
}
|
||||
|
||||
void refreshTransactions() {
|
||||
// TODO: fix it
|
||||
//transactionsRefreshNative();
|
||||
debugPrint("refreshing transactions");
|
||||
}
|
||||
// void refreshTransactions() {
|
||||
// // TODO: fix it
|
||||
// //transactionsRefreshNative();
|
||||
// debugPrint("refreshing transactions");
|
||||
// }
|
||||
|
||||
int countOfTransactions() {
|
||||
//return transactionsCountNative();
|
||||
|
@ -184,8 +184,9 @@ void commitTransactionFromPointerAddress({required int address}) =>
|
|||
void commitTransaction(
|
||||
{required Pointer<PendingTransactionRaw> transactionPointer}) {
|
||||
final errorMessagePointer = calloc<Utf8Box>();
|
||||
final isCommited =
|
||||
transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
|
||||
print("commit transaction");
|
||||
final isCommited = true;
|
||||
//transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
|
||||
|
||||
if (!isCommited) {
|
||||
final message = errorMessagePointer.ref.getValue();
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
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:cw_zano/api/structs/ut8_box.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:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:mobx/mobx.dart' as mobx;
|
||||
|
||||
int _boolToInt(bool value) => value ? 1 : 0;
|
||||
|
||||
final getFileNameNative = zanoApi
|
||||
.lookup<NativeFunction<get_filename>>('get_filename')
|
||||
.asFunction<GetFilename>();
|
||||
final getFileNameNative =
|
||||
zanoApi.lookup<NativeFunction<get_filename>>('get_filename').asFunction<GetFilename>();
|
||||
|
||||
/*final getSeedNative =
|
||||
zanoApi.lookup<NativeFunction<get_seed>>('seed').asFunction<GetSeed>();*/
|
||||
|
||||
final getAddressNative = zanoApi
|
||||
.lookup<NativeFunction<get_address>>('get_address')
|
||||
.asFunction<GetAddress>();
|
||||
final getAddressNative =
|
||||
zanoApi.lookup<NativeFunction<get_address>>('get_address').asFunction<GetAddress>();
|
||||
|
||||
final getFullBalanceNative = zanoApi
|
||||
.lookup<NativeFunction<get_full_balanace>>('get_full_balance')
|
||||
|
@ -36,42 +42,36 @@ final getUnlockedBalanceNative = zanoApi
|
|||
.lookup<NativeFunction<get_current_height>>('get_current_height')
|
||||
.asFunction<GetCurrentHeight>();*/
|
||||
|
||||
final getNodeHeightNative = zanoApi
|
||||
.lookup<NativeFunction<get_node_height>>('get_node_height')
|
||||
.asFunction<GetNodeHeight>();
|
||||
// final getNodeHeightNative = zanoApi
|
||||
// .lookup<NativeFunction<get_node_height>>('get_node_height')
|
||||
// .asFunction<GetNodeHeight>();
|
||||
|
||||
final isConnectedNative = zanoApi
|
||||
.lookup<NativeFunction<is_connected>>('is_connected')
|
||||
.asFunction<IsConnected>();
|
||||
final isConnectedNative =
|
||||
zanoApi.lookup<NativeFunction<is_connected>>('is_connected').asFunction<IsConnected>();
|
||||
|
||||
final setupNodeNative = zanoApi
|
||||
.lookup<NativeFunction<setup_node>>('setup_node')
|
||||
.asFunction<SetupNode>();
|
||||
final setupNodeNative =
|
||||
zanoApi.lookup<NativeFunction<setup_node>>('setup_node').asFunction<SetupNode>();
|
||||
|
||||
final startRefreshNative = zanoApi
|
||||
.lookup<NativeFunction<start_refresh>>('start_refresh')
|
||||
.asFunction<StartRefresh>();
|
||||
// final startRefreshNative = zanoApi
|
||||
// .lookup<NativeFunction<start_refresh>>('start_refresh')
|
||||
// .asFunction<StartRefresh>();
|
||||
|
||||
final connecToNodeNative = zanoApi
|
||||
.lookup<NativeFunction<connect_to_node>>('connect_to_node')
|
||||
.asFunction<ConnectToNode>();
|
||||
final connecToNodeNative =
|
||||
zanoApi.lookup<NativeFunction<connect_to_node>>('connect_to_node').asFunction<ConnectToNode>();
|
||||
|
||||
final setRefreshFromBlockHeightNative = zanoApi
|
||||
.lookup<NativeFunction<set_refresh_from_block_height>>(
|
||||
'set_refresh_from_block_height')
|
||||
.lookup<NativeFunction<set_refresh_from_block_height>>('set_refresh_from_block_height')
|
||||
.asFunction<SetRefreshFromBlockHeight>();
|
||||
|
||||
final setRecoveringFromSeedNative = zanoApi
|
||||
.lookup<NativeFunction<set_recovering_from_seed>>(
|
||||
'set_recovering_from_seed')
|
||||
.asFunction<SetRecoveringFromSeed>();
|
||||
// final setRecoveringFromSeedNative = zanoApi
|
||||
// .lookup<NativeFunction<set_recovering_from_seed>>('set_recovering_from_seed')
|
||||
// .asFunction<SetRecoveringFromSeed>();
|
||||
|
||||
final storeNative =
|
||||
zanoApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
|
||||
|
||||
final setPasswordNative = zanoApi
|
||||
.lookup<NativeFunction<set_password>>('set_password')
|
||||
.asFunction<SetPassword>();
|
||||
final storeNative = zanoApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
|
||||
|
||||
final setPasswordNative =
|
||||
zanoApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>();
|
||||
|
||||
/**final setListenerNative = zanoApi
|
||||
.lookup<NativeFunction<set_listener>>('set_listener')
|
||||
|
@ -85,18 +85,15 @@ final isNeededToRefreshNative = zanoApi
|
|||
.lookup<NativeFunction<is_needed_to_refresh>>('is_needed_to_refresh')
|
||||
.asFunction<IsNeededToRefresh>();
|
||||
|
||||
final isNewTransactionExistNative = zanoApi
|
||||
.lookup<NativeFunction<is_new_transaction_exist>>(
|
||||
'is_new_transaction_exist')
|
||||
.asFunction<IsNewTransactionExist>();
|
||||
// final isNewTransactionExistNative = zanoApi
|
||||
// .lookup<NativeFunction<is_new_transaction_exist>>('is_new_transaction_exist')
|
||||
// .asFunction<IsNewTransactionExist>();
|
||||
|
||||
final getSecretViewKeyNative = zanoApi
|
||||
.lookup<NativeFunction<secret_view_key>>('secret_view_key')
|
||||
.asFunction<SecretViewKey>();
|
||||
final getSecretViewKeyNative =
|
||||
zanoApi.lookup<NativeFunction<secret_view_key>>('secret_view_key').asFunction<SecretViewKey>();
|
||||
|
||||
final getPublicViewKeyNative = zanoApi
|
||||
.lookup<NativeFunction<public_view_key>>('public_view_key')
|
||||
.asFunction<PublicViewKey>();
|
||||
final getPublicViewKeyNative =
|
||||
zanoApi.lookup<NativeFunction<public_view_key>>('public_view_key').asFunction<PublicViewKey>();
|
||||
|
||||
final getSecretSpendKeyNative = zanoApi
|
||||
.lookup<NativeFunction<secret_spend_key>>('secret_spend_key')
|
||||
|
@ -110,27 +107,25 @@ final closeCurrentWalletNative = zanoApi
|
|||
.lookup<NativeFunction<close_current_wallet>>('close_current_wallet')
|
||||
.asFunction<CloseCurrentWallet>();
|
||||
|
||||
final onStartupNative = zanoApi
|
||||
.lookup<NativeFunction<on_startup>>('on_startup')
|
||||
.asFunction<OnStartup>();
|
||||
final onStartupNative =
|
||||
zanoApi.lookup<NativeFunction<on_startup>>('on_startup').asFunction<OnStartup>();
|
||||
|
||||
final rescanBlockchainAsyncNative = zanoApi
|
||||
.lookup<NativeFunction<rescan_blockchain>>('rescan_blockchain')
|
||||
.asFunction<RescanBlockchainAsync>();
|
||||
|
||||
final setTrustedDaemonNative = zanoApi
|
||||
.lookup<NativeFunction<set_trusted_daemon>>('set_trusted_daemon')
|
||||
.asFunction<SetTrustedDaemon>();
|
||||
// final setTrustedDaemonNative = zanoApi
|
||||
// .lookup<NativeFunction<set_trusted_daemon>>('set_trusted_daemon')
|
||||
// .asFunction<SetTrustedDaemon>();
|
||||
|
||||
final trustedDaemonNative = zanoApi
|
||||
.lookup<NativeFunction<trusted_daemon>>('trusted_daemon')
|
||||
.asFunction<TrustedDaemon>();
|
||||
final trustedDaemonNative =
|
||||
zanoApi.lookup<NativeFunction<trusted_daemon>>('trusted_daemon').asFunction<TrustedDaemon>();
|
||||
|
||||
int getSyncingHeight() => getSyncingHeightNative();
|
||||
|
||||
bool isNeededToRefresh() => isNeededToRefreshNative() != 0;
|
||||
|
||||
bool isNewTransactionExist() => isNewTransactionExistNative() != 0;
|
||||
//bool isNewTransactionExist() => isNewTransactionExistNative() != 0;
|
||||
|
||||
String getFilename() => convertUTF8ToString(pointer: getFileNameNative());
|
||||
|
||||
|
@ -139,29 +134,49 @@ String getFilename() => convertUTF8ToString(pointer: getFileNameNative());
|
|||
String getAddress({int accountIndex = 0, int addressIndex = 0}) =>
|
||||
convertUTF8ToString(pointer: getAddressNative(accountIndex, addressIndex));
|
||||
|
||||
int getFullBalance({int accountIndex = 0}) =>
|
||||
getFullBalanceNative(accountIndex);
|
||||
int getFullBalance({int accountIndex = 0}) => getFullBalanceNative(accountIndex);
|
||||
|
||||
int getUnlockedBalance({int accountIndex = 0}) =>
|
||||
getUnlockedBalanceNative(accountIndex);
|
||||
int getUnlockedBalance({int accountIndex = 0}) => getUnlockedBalanceNative(accountIndex);
|
||||
|
||||
int getCurrentHeight(int hWallet) {
|
||||
calls.getWalletStatus(hWallet);
|
||||
return -1;
|
||||
//return getCurrentHeightNative();
|
||||
final json = calls.getWalletStatus(hWallet);
|
||||
final walletStatus = GetWalletStatusResult.fromJson(jsonDecode(json) as Map<String, dynamic>);
|
||||
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 setupNodeSync(
|
||||
{required String address,
|
||||
bool setupNodeSync({
|
||||
required String address,
|
||||
String? login,
|
||||
String? password,
|
||||
bool useSSL = false,
|
||||
bool isLightWallet = false,
|
||||
/*String? socksProxyAddress*/}) {
|
||||
/*String? socksProxyAddress*/
|
||||
}) {
|
||||
final addressPointer = address.toNativeUtf8();
|
||||
Pointer<Utf8>? loginPointer;
|
||||
Pointer<Utf8>? socksProxyAddressPointer;
|
||||
|
@ -180,7 +195,8 @@ bool setupNodeSync(
|
|||
}*/
|
||||
|
||||
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
|
||||
final isSetupNode = setupNodeNative(
|
||||
addressPointer,
|
||||
|
@ -212,15 +228,14 @@ bool setupNodeSync(
|
|||
return isSetupNode;
|
||||
}
|
||||
|
||||
void startRefreshSync() => startRefreshNative();
|
||||
//void startRefreshSync() => startRefreshNative();
|
||||
|
||||
Future<bool> connectToNode() async => connecToNodeNative() != 0;
|
||||
|
||||
void setRefreshFromBlockHeight({required int height}) =>
|
||||
setRefreshFromBlockHeightNative(height);
|
||||
void setRefreshFromBlockHeight({required int height}) => setRefreshFromBlockHeightNative(height);
|
||||
|
||||
void setRecoveringFromSeed({required bool isRecovery}) =>
|
||||
setRecoveringFromSeedNative(_boolToInt(isRecovery));
|
||||
// void setRecoveringFromSeed({required bool isRecovery}) =>
|
||||
// setRecoveringFromSeedNative(_boolToInt(isRecovery));
|
||||
|
||||
void storeSync(int hWallet) {
|
||||
calls.store(hWallet);
|
||||
|
@ -247,17 +262,13 @@ void setPasswordSync(String password) {
|
|||
|
||||
void closeCurrentWallet() => closeCurrentWalletNative();
|
||||
|
||||
String getSecretViewKey() =>
|
||||
convertUTF8ToString(pointer: getSecretViewKeyNative());
|
||||
String getSecretViewKey() => convertUTF8ToString(pointer: getSecretViewKeyNative());
|
||||
|
||||
String getPublicViewKey() =>
|
||||
convertUTF8ToString(pointer: getPublicViewKeyNative());
|
||||
String getPublicViewKey() => convertUTF8ToString(pointer: getPublicViewKeyNative());
|
||||
|
||||
String getSecretSpendKey() =>
|
||||
convertUTF8ToString(pointer: getSecretSpendKeyNative());
|
||||
String getSecretSpendKey() => convertUTF8ToString(pointer: getSecretSpendKeyNative());
|
||||
|
||||
String getPublicSpendKey() =>
|
||||
convertUTF8ToString(pointer: getPublicSpendKeyNative());
|
||||
String getPublicSpendKey() => convertUTF8ToString(pointer: getPublicSpendKeyNative());
|
||||
|
||||
class SyncListener {
|
||||
SyncListener(this.onNewBlock, this.onNewTransaction)
|
||||
|
@ -273,36 +284,54 @@ class SyncListener {
|
|||
int _lastKnownBlockHeight;
|
||||
int _initialSyncHeight;
|
||||
|
||||
Future<int> getNodeHeightOrUpdate(int baseHeight) async {
|
||||
Future<int> getNodeHeightOrUpdate(int hWallet, int baseHeight) async {
|
||||
if (_cachedBlockchainHeight < baseHeight || _cachedBlockchainHeight == 0) {
|
||||
_cachedBlockchainHeight = await getNodeHeight();
|
||||
_cachedBlockchainHeight = await compute<int, int>(getNodeHeightSync, hWallet);
|
||||
}
|
||||
|
||||
return _cachedBlockchainHeight;
|
||||
}
|
||||
|
||||
void start() {
|
||||
void start(ZanoWalletBase wallet, int hWallet) async {
|
||||
_cachedBlockchainHeight = 0;
|
||||
_lastKnownBlockHeight = 0;
|
||||
_initialSyncHeight = 0;
|
||||
_updateSyncInfoTimer ??=
|
||||
Timer.periodic(Duration(milliseconds: 1200), (_) async {
|
||||
if (isNewTransactionExist()) {
|
||||
_updateSyncInfoTimer ??= Timer.periodic(Duration(milliseconds: 1200), (_) async {
|
||||
/**if (isNewTransactionExist()) {
|
||||
onNewTransaction?.call();
|
||||
}
|
||||
}*/
|
||||
|
||||
var syncHeight = getSyncingHeight();
|
||||
///var syncHeight = getSyncingHeight();
|
||||
var syncHeight = getCurrentHeight(hWallet);
|
||||
|
||||
if (syncHeight <= 0) {
|
||||
// TODO: fix it
|
||||
syncHeight = getCurrentHeight(-1);
|
||||
syncHeight = getCurrentHeight(hWallet);
|
||||
}
|
||||
|
||||
//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) {
|
||||
_initialSyncHeight = syncHeight;
|
||||
}
|
||||
|
||||
final bchHeight = await getNodeHeightOrUpdate(syncHeight);
|
||||
final bchHeight = await getNodeHeightOrUpdate(hWallet, syncHeight);
|
||||
|
||||
if (_lastKnownBlockHeight == syncHeight || syncHeight == null) {
|
||||
return;
|
||||
|
@ -326,8 +355,8 @@ class SyncListener {
|
|||
void stop() => _updateSyncInfoTimer?.cancel();
|
||||
}
|
||||
|
||||
SyncListener setListeners(void Function(int, int, double) onNewBlock,
|
||||
void Function() onNewTransaction) {
|
||||
SyncListener setListeners(
|
||||
void Function(int, int, double) onNewBlock, void Function() onNewTransaction) {
|
||||
final listener = SyncListener(onNewBlock, onNewTransaction);
|
||||
/**setListenerNative();*/
|
||||
return listener;
|
||||
|
@ -350,15 +379,15 @@ bool _setupNodeSync(Map args) {
|
|||
login: login,
|
||||
password: password,
|
||||
useSSL: useSSL,
|
||||
isLightWallet: isLightWallet,
|
||||
/*socksProxyAddress: socksProxyAddress*/);
|
||||
isLightWallet: isLightWallet, /*socksProxyAddress: socksProxyAddress*/
|
||||
);
|
||||
}
|
||||
|
||||
bool _isConnected(Object _) => isConnectedSync();
|
||||
|
||||
int _getNodeHeight(Object _) => getNodeHeightSync();
|
||||
//int _getNodeHeight(Object _) => getNodeHeightSync();
|
||||
|
||||
void startRefresh() => startRefreshSync();
|
||||
//void startRefresh() => startRefreshSync();
|
||||
|
||||
Future<bool> setupNode(
|
||||
{required String address,
|
||||
|
@ -380,11 +409,11 @@ Future<void> store(int hWallet) => compute<int, void>(_storeSync, 0);
|
|||
|
||||
Future<bool> isConnected() => compute(_isConnected, 0);
|
||||
|
||||
Future<int> getNodeHeight() => compute(_getNodeHeight, 0);
|
||||
//Future<int> getNodeHeight() => compute(_getNodeHeight, 0);
|
||||
|
||||
void rescanBlockchainAsync() => rescanBlockchainAsyncNative();
|
||||
|
||||
Future setTrustedDaemon(bool trusted) async =>
|
||||
setTrustedDaemonNative(_boolToInt(trusted));
|
||||
// Future setTrustedDaemon(bool trusted) async =>
|
||||
// setTrustedDaemonNative(_boolToInt(trusted));
|
||||
|
||||
Future<bool> trustedDaemon() async => trustedDaemonNative() != 0;
|
||||
|
|
|
@ -200,11 +200,11 @@ Future<void> _openWallet(Map<String, String> args) async => loadWallet(
|
|||
|
||||
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);
|
||||
// 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);
|
||||
|
|
File diff suppressed because it is too large
Load diff
19
cw_zano/lib/new_zano_addresses_base.dart
Normal file
19
cw_zano/lib/new_zano_addresses_base.dart
Normal 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");
|
||||
}
|
||||
|
||||
}
|
239
cw_zano/lib/new_zano_wallet.dart
Normal file
239
cw_zano/lib/new_zano_wallet.dart
Normal 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;
|
||||
}
|
||||
}
|
|
@ -27,8 +27,10 @@ class PendingZanoTransaction with PendingTransaction {
|
|||
String get hex => '';
|
||||
|
||||
@override
|
||||
String get amountFormatted => AmountConverter.amountIntToString(
|
||||
String get amountFormatted {
|
||||
return AmountConverter.amountIntToString(
|
||||
cryptoCurrency, pendingTransactionDescription.amount);
|
||||
}
|
||||
|
||||
@override
|
||||
String get feeFormatted => AmountConverter.amountIntToString(
|
||||
|
|
|
@ -1,53 +1,23 @@
|
|||
import 'package:cw_core/balance.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_zano/api/balance_list.dart';
|
||||
import 'package:cw_zano/api/structs/zano_balance_row.dart';
|
||||
|
||||
class ZanoBalance extends Balance {
|
||||
ZanoBalance(super.available, super.additional);
|
||||
late int unlockedBalance;
|
||||
@override
|
||||
// TODO: implement formattedAdditionalBalance
|
||||
String get formattedAdditionalBalance {
|
||||
// TODO: fix it
|
||||
return "0";
|
||||
}
|
||||
final int total;
|
||||
final int unlocked;
|
||||
ZanoBalance({required this.total, required this.unlocked}): super(unlocked, 0);
|
||||
|
||||
|
||||
@override
|
||||
// TODO: implement formattedAvailableBalance
|
||||
String get formattedAvailableBalance {
|
||||
// TODO: fix it
|
||||
return "0";
|
||||
}
|
||||
String get formattedAdditionalBalance => moneroAmountToString(amount: additional);
|
||||
|
||||
@override
|
||||
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;
|
||||
}*/
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:cw_core/transaction_info.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_core/parseBoolFromString.dart';
|
||||
import 'package:cw_core/transaction_direction.dart';
|
||||
|
@ -19,7 +20,22 @@ class ZanoTransactionInfo extends TransactionInfo {
|
|||
this.fee,
|
||||
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,
|
||||
height = (map['height'] ?? 0) as int,
|
||||
direction =
|
||||
|
@ -33,9 +49,9 @@ class ZanoTransactionInfo extends TransactionInfo {
|
|||
addressIndex = map['addressIndex'] as int,
|
||||
confirmations = map['confirmations'] as int,
|
||||
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(),
|
||||
height = row.blockHeight,
|
||||
direction = parseTransactionDirectionFromInt(row.direction) ??
|
||||
|
@ -48,7 +64,7 @@ class ZanoTransactionInfo extends TransactionInfo {
|
|||
confirmations = row.confirmations,
|
||||
key = null, //getTxKey(row.getHash()),
|
||||
fee = row.fee,
|
||||
assetType = row.getAssetType();
|
||||
assetType = row.getAssetType();*/
|
||||
|
||||
final String id;
|
||||
final int height;
|
||||
|
|
|
@ -1,37 +1,35 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
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/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: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/api/wallet.dart' as zano_wallet;
|
||||
import 'package:cw_zano/api/transaction_history.dart' as transaction_history;
|
||||
import 'package:cw_zano/api/zano_output.dart';
|
||||
import 'package:cw_zano/api/zano_api.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_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';
|
||||
|
||||
|
@ -39,21 +37,16 @@ const moneroBlockSize = 1000;
|
|||
|
||||
class ZanoWallet = ZanoWalletBase with _$ZanoWallet;
|
||||
|
||||
abstract class ZanoWalletBase
|
||||
extends WalletBase<ZanoBalance, ZanoTransactionHistory, ZanoTransactionInfo>
|
||||
with Store {
|
||||
ZanoWalletBase.simple({required WalletInfo walletInfo})
|
||||
: balance = ObservableMap(),
|
||||
_isTransactionUpdating = false,
|
||||
_hasSyncAfterStartup = false,
|
||||
walletAddresses = ZanoWalletAddresses(walletInfo),
|
||||
syncStatus = NotConnectedSyncStatus(),
|
||||
super(walletInfo) {
|
||||
transactionHistory = ZanoTransactionHistory();
|
||||
}
|
||||
typedef _load_wallet = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>, Int8);
|
||||
typedef _LoadWallet = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>, int);
|
||||
|
||||
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,
|
||||
_hasSyncAfterStartup = false,
|
||||
walletAddresses = ZanoWalletAddresses(walletInfo),
|
||||
|
@ -70,6 +63,9 @@ abstract class ZanoWalletBase
|
|||
});*/
|
||||
}
|
||||
|
||||
List<History> history = [];
|
||||
String assetId = '';
|
||||
|
||||
static const int _autoSaveInterval = 30;
|
||||
|
||||
@override
|
||||
|
@ -84,20 +80,11 @@ abstract class ZanoWalletBase
|
|||
ObservableMap<CryptoCurrency, ZanoBalance> balance;
|
||||
|
||||
@override
|
||||
String get seed {
|
||||
// TODO: fix it
|
||||
//return calls.seed(hWallet);
|
||||
return "test";
|
||||
/**zano_wallet.getSeed();*/
|
||||
}
|
||||
String seed = '';
|
||||
|
||||
@override
|
||||
// TODO: ?? why monero
|
||||
MoneroWalletKeys get keys => MoneroWalletKeys(
|
||||
privateSpendKey: zano_wallet.getSecretSpendKey(),
|
||||
privateViewKey: zano_wallet.getSecretViewKey(),
|
||||
publicSpendKey: zano_wallet.getPublicSpendKey(),
|
||||
publicViewKey: zano_wallet.getPublicViewKey());
|
||||
ZanoWalletKeys keys = ZanoWalletKeys(
|
||||
privateSpendKey: '', privateViewKey: '', publicSpendKey: '', publicViewKey: '');
|
||||
|
||||
zano_wallet.SyncListener? _listener;
|
||||
/**ReactionDisposer? _onAccountChangeReaction;*/
|
||||
|
@ -115,21 +102,20 @@ abstract class ZanoWalletBase
|
|||
|
||||
Future<void> init() async {
|
||||
await walletAddresses.init();
|
||||
balance
|
||||
.addAll(getZanoBalance(/**accountIndex: walletAddresses.account?.id ?? 0*/));
|
||||
///balance.addAll(getZanoBalance(/**accountIndex: walletAddresses.account?.id ?? 0*/));
|
||||
_setListeners();
|
||||
await updateTransactions();
|
||||
|
||||
if (walletInfo.isRecovery) {
|
||||
zano_wallet.setRecoveringFromSeed(isRecovery: walletInfo.isRecovery);
|
||||
///zano_wallet.setRecoveringFromSeed(isRecovery: walletInfo.isRecovery);
|
||||
|
||||
if (zano_wallet.getCurrentHeight(hWallet) <= 1) {
|
||||
zano_wallet.setRefreshFromBlockHeight(height: walletInfo.restoreHeight);
|
||||
}
|
||||
}
|
||||
|
||||
_autoSaveTimer = Timer.periodic(
|
||||
Duration(seconds: _autoSaveInterval), (_) async => await save());
|
||||
_autoSaveTimer =
|
||||
Timer.periodic(Duration(seconds: _autoSaveInterval), (_) async => await save());
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -155,7 +141,7 @@ abstract class ZanoWalletBase
|
|||
/*socksProxyAddress: node.socksProxyAddress*/
|
||||
);
|
||||
|
||||
zano_wallet.setTrustedDaemon(node.trusted);
|
||||
//zano_wallet.setTrustedDaemon(node.trusted);
|
||||
syncStatus = ConnectedSyncStatus();
|
||||
} catch (e) {
|
||||
syncStatus = FailedSyncStatus();
|
||||
|
@ -171,9 +157,10 @@ abstract class ZanoWalletBase
|
|||
|
||||
try {
|
||||
syncStatus = AttemptingSyncStatus();
|
||||
zano_wallet.startRefresh();
|
||||
//zano_wallet.startRefresh();
|
||||
print("start refresh");
|
||||
_setListeners();
|
||||
_listener?.start();
|
||||
_listener?.start(this, hWallet);
|
||||
} catch (e) {
|
||||
syncStatus = FailedSyncStatus();
|
||||
print(e);
|
||||
|
@ -183,7 +170,38 @@ abstract class ZanoWalletBase
|
|||
|
||||
@override
|
||||
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 hasMultiDestination = outputs.length > 1;
|
||||
final assetType =
|
||||
|
@ -249,29 +267,12 @@ abstract class ZanoWalletBase
|
|||
priorityRaw: _credentials.priority.serialize());
|
||||
}
|
||||
|
||||
return PendingZanoTransaction(pendingTransactionDescription, assetType);
|
||||
return PendingZanoTransaction(pendingTransactionDescription, assetType);*/
|
||||
}
|
||||
|
||||
@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;
|
||||
int calculateEstimatedFee(TransactionPriority priority, [int? amount = null]) {
|
||||
return calls.getCurrentTxFee(priority.raw);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -310,7 +311,7 @@ abstract class ZanoWalletBase
|
|||
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();
|
||||
|
||||
|
@ -334,18 +335,37 @@ abstract class ZanoWalletBase
|
|||
}
|
||||
|
||||
String getTransactionAddress(int accountIndex, int addressIndex) =>
|
||||
zano_wallet.getAddress(
|
||||
accountIndex: accountIndex, addressIndex: addressIndex);
|
||||
zano_wallet.getAddress(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
|
||||
Future<Map<String, ZanoTransactionInfo>> fetchTransactions() async {
|
||||
zano_transaction_history.refreshTransactions();
|
||||
return _getAllTransactions(null)
|
||||
//zano_transaction_history.refreshTransactions();
|
||||
await _refreshTransactions();
|
||||
return history
|
||||
.map<ZanoTransactionInfo>((history) => ZanoTransactionInfo.fromHistory(history))
|
||||
.fold<Map<String, ZanoTransactionInfo>>(<String, ZanoTransactionInfo>{},
|
||||
(Map<String, ZanoTransactionInfo> acc, ZanoTransactionInfo tx) {
|
||||
acc[tx.id] = tx;
|
||||
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 {
|
||||
|
@ -365,11 +385,11 @@ abstract class ZanoWalletBase
|
|||
}
|
||||
}
|
||||
|
||||
List<ZanoTransactionInfo> _getAllTransactions(dynamic _) =>
|
||||
zano_transaction_history
|
||||
.getAllTransations()
|
||||
.map((row) => ZanoTransactionInfo.fromRow(row))
|
||||
.toList();
|
||||
// List<ZanoTransactionInfo> _getAllTransactions(dynamic _) =>
|
||||
// zano_transaction_history
|
||||
// .getAllTransations()
|
||||
// .map((row) => ZanoTransactionInfo.fromRow(row))
|
||||
// .toList();
|
||||
|
||||
void _setListeners() {
|
||||
_listener?.stop();
|
||||
|
@ -385,36 +405,39 @@ abstract class ZanoWalletBase
|
|||
|
||||
if (currentHeight <= 1) {
|
||||
final height = _getHeightByDate(walletInfo.date);
|
||||
zano_wallet.setRecoveringFromSeed(isRecovery: true);
|
||||
///zano_wallet.setRecoveringFromSeed(isRecovery: true);
|
||||
zano_wallet.setRefreshFromBlockHeight(height: height);
|
||||
}
|
||||
}
|
||||
|
||||
int _getHeightDistance(DateTime date) {
|
||||
final distance =
|
||||
DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch;
|
||||
final daysTmp = (distance / 86400).round();
|
||||
final days = daysTmp < 1 ? 1 : daysTmp;
|
||||
// int _getHeightDistance(DateTime date) {
|
||||
// final distance =
|
||||
// DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch;
|
||||
// final daysTmp = (distance / 86400).round();
|
||||
// final days = daysTmp < 1 ? 1 : daysTmp;
|
||||
|
||||
return days * 1000;
|
||||
}
|
||||
// return days * 1000;
|
||||
// }
|
||||
|
||||
int _getHeightByDate(DateTime date) {
|
||||
final nodeHeight = zano_wallet.getNodeHeightSync();
|
||||
final heightDistance = _getHeightDistance(date);
|
||||
|
||||
if (nodeHeight <= 0) {
|
||||
// TODO: !!! 12/10 commented
|
||||
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() =>
|
||||
balance.addAll(getZanoBalance());
|
||||
|
||||
Future<void> _askForUpdateTransactionHistory() async =>
|
||||
await updateTransactions();
|
||||
Future<void> _askForUpdateTransactionHistory() async => await updateTransactions();
|
||||
|
||||
void _onNewBlock(int height, int blocksLeft, double ptc) async {
|
||||
try {
|
||||
|
@ -455,4 +478,24 @@ abstract class ZanoWalletBase
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/wallet_base.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:cw_zano/api/wallet_manager.dart' as zano_wallet_manager;
|
||||
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/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
class ZanoNewWalletCredentials extends WalletCredentials {
|
||||
ZanoNewWalletCredentials({required String name, String? password})
|
||||
|
@ -22,10 +28,7 @@ class ZanoNewWalletCredentials extends WalletCredentials {
|
|||
|
||||
class ZanoRestoreWalletFromSeedCredentials extends WalletCredentials {
|
||||
ZanoRestoreWalletFromSeedCredentials(
|
||||
{required String name,
|
||||
required String password,
|
||||
required int height,
|
||||
required this.mnemonic})
|
||||
{required String name, required String password, required int height, required this.mnemonic})
|
||||
: super(name: name, password: password, height: height);
|
||||
|
||||
final String mnemonic;
|
||||
|
@ -53,10 +56,8 @@ class ZanoRestoreWalletFromKeysCredentials extends WalletCredentials {
|
|||
final String spendKey;
|
||||
}
|
||||
|
||||
class ZanoWalletService extends WalletService<
|
||||
ZanoNewWalletCredentials,
|
||||
ZanoRestoreWalletFromSeedCredentials,
|
||||
ZanoRestoreWalletFromKeysCredentials> {
|
||||
class ZanoWalletService extends WalletService<ZanoNewWalletCredentials,
|
||||
ZanoRestoreWalletFromSeedCredentials, ZanoRestoreWalletFromKeysCredentials> {
|
||||
ZanoWalletService(this.walletInfoSource);
|
||||
|
||||
final Box<WalletInfo> walletInfoSource;
|
||||
|
@ -69,18 +70,38 @@ class ZanoWalletService extends WalletService<
|
|||
@override
|
||||
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
|
||||
Future<ZanoWallet> create(ZanoNewWalletCredentials credentials) async {
|
||||
Future<ZanoWallet> create(WalletCredentials credentials) async {
|
||||
try {
|
||||
final wallet = ZanoWallet.simple(walletInfo: credentials.walletInfo!);
|
||||
wallet.connectToNode(node: Node());
|
||||
final wallet = ZanoWallet(credentials.walletInfo!);
|
||||
await wallet.connectToNode(node: Node());
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
final result = await zano_wallet_manager.createWallet(
|
||||
language: "", path: path, password: credentials.password!);
|
||||
hWallet = -1;
|
||||
wallet.hWallet = hWallet;
|
||||
// TODO: remove it
|
||||
calls.store(hWallet);
|
||||
print("create wallet result $result");
|
||||
final map = json.decode(result) as Map<String, dynamic>;
|
||||
if (map['result'] != null) {
|
||||
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();
|
||||
return wallet;
|
||||
} catch (e) {
|
||||
|
@ -111,37 +132,36 @@ class ZanoWalletService extends WalletService<
|
|||
await repairOldAndroidWallet(name);
|
||||
}
|
||||
|
||||
await zano_wallet_manager
|
||||
.openWalletAsync({'path': path, 'password': password});
|
||||
final walletInfo = walletInfoSource.values.firstWhereOrNull(
|
||||
(info) => info.id == WalletBase.idFor(name, getType()))!;
|
||||
final wallet = ZanoWallet(walletInfo: walletInfo);
|
||||
/*final isValid = wallet.walletAddresses.validate();
|
||||
|
||||
if (!isValid) {
|
||||
await restoreOrResetWalletFiles(name);
|
||||
wallet.close();
|
||||
return openWallet(name, password);
|
||||
}*/
|
||||
|
||||
final walletInfo = walletInfoSource.values
|
||||
.firstWhereOrNull((info) => info.id == WalletBase.idFor(name, getType()))!;
|
||||
final wallet = ZanoWallet(walletInfo);
|
||||
await wallet.connectToNode(node: Node());
|
||||
final result = wallet.loadWallet(path, password);
|
||||
print("load wallet result $result");
|
||||
final map = json.decode(result) as Map<String, dynamic>;
|
||||
if (map['result'] != null) {
|
||||
final createWalletResult =
|
||||
CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
|
||||
_parseCreateWalletResult(createWalletResult, wallet);
|
||||
}
|
||||
await calls.store(hWallet);
|
||||
await wallet.init();
|
||||
|
||||
return wallet;
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception for wallet list service.
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
Future<void> rename(
|
||||
String currentName, String password, String newName) async {
|
||||
final currentWalletInfo = walletInfoSource.values.firstWhere(
|
||||
(info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||
final currentWallet = ZanoWallet(walletInfo: currentWalletInfo);
|
||||
Future<void> rename(String currentName, String password, String newName) async {
|
||||
final currentWalletInfo = walletInfoSource.values
|
||||
.firstWhere((info) => info.id == WalletBase.idFor(currentName, getType()));
|
||||
final currentWallet = ZanoWallet(currentWalletInfo);
|
||||
|
||||
await currentWallet.renameWalletFiles(newName);
|
||||
|
||||
|
@ -177,8 +196,7 @@ class ZanoWalletService extends WalletService<
|
|||
}
|
||||
|
||||
@override
|
||||
Future<ZanoWallet> restoreFromKeys(
|
||||
ZanoRestoreWalletFromKeysCredentials credentials) async {
|
||||
Future<ZanoWallet> restoreFromKeys(ZanoRestoreWalletFromKeysCredentials credentials) async {
|
||||
try {
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
await zano_wallet_manager.restoreFromKeys(
|
||||
|
@ -189,7 +207,7 @@ class ZanoWalletService extends WalletService<
|
|||
address: credentials.address,
|
||||
viewKey: credentials.viewKey,
|
||||
spendKey: credentials.spendKey);
|
||||
final wallet = ZanoWallet(walletInfo: credentials.walletInfo!);
|
||||
final wallet = ZanoWallet(credentials.walletInfo!);
|
||||
await wallet.init();
|
||||
|
||||
return wallet;
|
||||
|
@ -201,18 +219,21 @@ class ZanoWalletService extends WalletService<
|
|||
}
|
||||
|
||||
@override
|
||||
Future<ZanoWallet> restoreFromSeed(
|
||||
ZanoRestoreWalletFromSeedCredentials credentials) async {
|
||||
Future<ZanoWallet> restoreFromSeed(ZanoRestoreWalletFromSeedCredentials credentials) async {
|
||||
try {
|
||||
final wallet = ZanoWallet(credentials.walletInfo!);
|
||||
await wallet.connectToNode(node: Node());
|
||||
final path = await pathForWallet(name: credentials.name, type: getType());
|
||||
await zano_wallet_manager.restoreFromSeed(
|
||||
path: path,
|
||||
password: credentials.password!,
|
||||
seed: credentials.mnemonic,
|
||||
restoreHeight: credentials.height!);
|
||||
final wallet = ZanoWallet(walletInfo: credentials.walletInfo!);
|
||||
final result = calls.restoreWalletFromSeed(path, credentials.password!, credentials.mnemonic);
|
||||
print('restore wallet from seed result $result');
|
||||
final map = json.decode(result) as Map<String, dynamic>;
|
||||
if (map['result'] != null) {
|
||||
final createWalletResult =
|
||||
CreateWalletResult.fromJson(map['result'] as Map<String, dynamic>);
|
||||
_parseCreateWalletResult(createWalletResult, wallet);
|
||||
}
|
||||
await calls.store(hWallet);
|
||||
await wallet.init();
|
||||
|
||||
return wallet;
|
||||
} catch (e) {
|
||||
// TODO: Implement Exception for wallet list service.
|
||||
|
@ -227,16 +248,14 @@ class ZanoWalletService extends WalletService<
|
|||
return;
|
||||
}
|
||||
|
||||
final oldAndroidWalletDirPath =
|
||||
await outdatedAndroidPathForWalletDir(name: name);
|
||||
final oldAndroidWalletDirPath = await outdatedAndroidPathForWalletDir(name: name);
|
||||
final dir = Directory(oldAndroidWalletDirPath);
|
||||
|
||||
if (!dir.existsSync()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final newWalletDirPath =
|
||||
await pathForWalletDir(name: name, type: getType());
|
||||
final newWalletDirPath = await pathForWalletDir(name: name, type: getType());
|
||||
|
||||
dir.listSync().forEach((f) {
|
||||
final file = File(f.path);
|
||||
|
|
|
@ -239,6 +239,8 @@ class AddressValidator extends TextValidator {
|
|||
return [64];
|
||||
case CryptoCurrency.btcln:
|
||||
return null;
|
||||
case CryptoCurrency.zano:
|
||||
return [97];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -211,6 +211,8 @@ class WalletRestorePage extends BasePage {
|
|||
final seedWords =
|
||||
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.text.split(' ');
|
||||
|
||||
if (walletRestoreViewModel.type == WalletType.zano) return true;
|
||||
|
||||
if ((walletRestoreViewModel.type == WalletType.monero ||
|
||||
walletRestoreViewModel.type == WalletType.haven) &&
|
||||
seedWords.length != WalletRestoreViewModelBase.moneroSeedMnemonicLength) {
|
||||
|
|
|
@ -258,8 +258,8 @@ abstract class OutputBase with Store {
|
|||
break;
|
||||
case WalletType.dummy:
|
||||
case WalletType.zano:
|
||||
// TODO: enter correct values
|
||||
throw UnimplementedError();
|
||||
maximumFractionDigits = 12;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import 'package:cw_core/pathForWallet.dart';
|
|||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_zano/api/calls.dart' as calls;
|
||||
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_manager.dart' as zano_wallet_manager;
|
||||
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
|
||||
/// isolate.
|
||||
PlatformDispatcher.instance.onError = (error, stack) {
|
||||
ExceptionHandler.onError(
|
||||
FlutterErrorDetails(exception: error, stack: stack));
|
||||
ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
||||
|
||||
return true;
|
||||
};
|
||||
await setup();
|
||||
runApp(App());
|
||||
}, (error, stackTrace) async {
|
||||
ExceptionHandler.onError(
|
||||
FlutterErrorDetails(exception: error, stack: stackTrace));
|
||||
ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stackTrace));
|
||||
});
|
||||
}
|
||||
|
||||
final getIt = GetIt.instance;
|
||||
|
||||
Future<void> setup() async {
|
||||
getIt.registerFactory<KeyService>(
|
||||
() => KeyService(getIt.get<FlutterSecureStorage>()));
|
||||
getIt.registerFactory<KeyService>(() => KeyService(getIt.get<FlutterSecureStorage>()));
|
||||
}
|
||||
|
||||
class App extends StatefulWidget {
|
||||
|
@ -79,7 +76,7 @@ class _AppState extends State<App> {
|
|||
}
|
||||
|
||||
int hWallet = 0;
|
||||
CreateLoadRestoreWalletResult? lwr;
|
||||
CreateWalletResult? lwr;
|
||||
List<Balance> balances = [];
|
||||
String seed = '', version = '';
|
||||
final assetIds = <String, String>{};
|
||||
|
@ -107,11 +104,9 @@ Future<String?> create(String name) async {
|
|||
final keyService = KeyService(FlutterSecureStorage());
|
||||
final password = generateWalletPassword();
|
||||
credentials.password = password;
|
||||
await keyService.saveWalletPassword(
|
||||
password: password, walletName: credentials.name);
|
||||
await keyService.saveWalletPassword(password: password, walletName: credentials.name);
|
||||
debugPrint('path $path password $password');
|
||||
final result = zano_wallet_manager.createWalletSync(
|
||||
path: path, password: password, language: '');
|
||||
final result = zano_wallet_manager.createWalletSync(path: path, password: password, language: '');
|
||||
debugPrint('create result $result');
|
||||
return _parseResult(result);
|
||||
}
|
||||
|
@ -122,8 +117,7 @@ Future<String?> connect(String name) async {
|
|||
final path = await pathForWallet(name: name, type: WalletType.zano);
|
||||
final credentials = ZanoNewWalletCredentials(name: name);
|
||||
final keyService = KeyService(FlutterSecureStorage());
|
||||
final password =
|
||||
await keyService.getWalletPassword(walletName: credentials.name);
|
||||
final password = await keyService.getWalletPassword(walletName: credentials.name);
|
||||
debugPrint('path $path password $password');
|
||||
final result = await calls.loadWallet(path, password, 0);
|
||||
return _parseResult(result);
|
||||
|
@ -137,8 +131,7 @@ Future<String?> restore(String name, String seed) async {
|
|||
final keyService = KeyService(FlutterSecureStorage());
|
||||
final password = generateWalletPassword();
|
||||
credentials.password = password;
|
||||
await keyService.saveWalletPassword(
|
||||
password: password, walletName: credentials.name);
|
||||
await keyService.saveWalletPassword(password: password, walletName: credentials.name);
|
||||
debugPrint('path $path password $password');
|
||||
var result = calls.restoreWalletFromSeed(path, password, seed);
|
||||
debugPrint('restore result $result');
|
||||
|
@ -149,7 +142,7 @@ Future<String?> restore(String name, String seed) async {
|
|||
String? _parseResult(String result) {
|
||||
final map = json.decode(result) as Map<String, dynamic>;
|
||||
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;
|
||||
hWallet = lwr!.walletId;
|
||||
assetIds.clear();
|
||||
|
@ -204,14 +197,12 @@ class _DisconnectedWidgetState extends State<DisconnectedWidget> {
|
|||
child: Column(
|
||||
children: [
|
||||
TextField(
|
||||
controller: _name,
|
||||
decoration: InputDecoration(labelText: 'Wallet name')),
|
||||
controller: _name, decoration: InputDecoration(labelText: 'Wallet name')),
|
||||
TextButton(
|
||||
child: Text('Connect and Open Wallet'),
|
||||
onPressed: () async {
|
||||
//setState(() => _loading = true);
|
||||
final preferences =
|
||||
await SharedPreferences.getInstance();
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
await preferences.setString(walletName, _name.text);
|
||||
final result = await connect(_name.text);
|
||||
//setState(() => _loading = false);
|
||||
|
@ -232,8 +223,7 @@ class _DisconnectedWidgetState extends State<DisconnectedWidget> {
|
|||
child: Text('Create and Open Wallet'),
|
||||
onPressed: () async {
|
||||
//setState(() => _loading = true);
|
||||
final preferences =
|
||||
await SharedPreferences.getInstance();
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
await preferences.setString(walletName, _name.text);
|
||||
final result = await create(_name.text);
|
||||
//setState(() => _loading = false);
|
||||
|
@ -251,13 +241,11 @@ class _DisconnectedWidgetState extends State<DisconnectedWidget> {
|
|||
height: 16,
|
||||
),
|
||||
TextField(
|
||||
controller: _seed,
|
||||
decoration: InputDecoration(labelText: 'Wallet seed')),
|
||||
controller: _seed, decoration: InputDecoration(labelText: 'Wallet seed')),
|
||||
TextButton(
|
||||
child: Text('Restore from seed'),
|
||||
onPressed: () async {
|
||||
final preferences =
|
||||
await SharedPreferences.getInstance();
|
||||
final preferences = await SharedPreferences.getInstance();
|
||||
await preferences.setString(walletName, _name.text);
|
||||
final result = await restore(_name.text, _seed.text);
|
||||
if (result != null) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cw_zano/new_zano_wallet.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
|
|
Loading…
Reference in a new issue