mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-02-02 11:16:26 +00:00
remove monero stuff, work on derivation ui
This commit is contained in:
parent
c6d937ca4e
commit
2fb43e8b28
56 changed files with 368 additions and 1599 deletions
|
@ -1,83 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
import 'package:cw_nano/api/signatures.dart';
|
|
||||||
import 'package:cw_nano/api/types.dart';
|
|
||||||
import 'package:cw_nano/api/monero_api.dart';
|
|
||||||
import 'package:cw_nano/api/structs/account_row.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:cw_nano/api/wallet.dart';
|
|
||||||
|
|
||||||
// final accountSizeNative = moneroApi
|
|
||||||
// .lookup<NativeFunction<account_size>>('account_size')
|
|
||||||
// .asFunction<SubaddressSize>();
|
|
||||||
|
|
||||||
// final accountRefreshNative = moneroApi
|
|
||||||
// .lookup<NativeFunction<account_refresh>>('account_refresh')
|
|
||||||
// .asFunction<AccountRefresh>();
|
|
||||||
|
|
||||||
// final accountGetAllNative = moneroApi
|
|
||||||
// .lookup<NativeFunction<account_get_all>>('account_get_all')
|
|
||||||
// .asFunction<AccountGetAll>();
|
|
||||||
|
|
||||||
// final accountAddNewNative = moneroApi
|
|
||||||
// .lookup<NativeFunction<account_add_new>>('account_add_row')
|
|
||||||
// .asFunction<AccountAddNew>();
|
|
||||||
|
|
||||||
// final accountSetLabelNative = moneroApi
|
|
||||||
// .lookup<NativeFunction<account_set_label>>('account_set_label_row')
|
|
||||||
// .asFunction<AccountSetLabel>();
|
|
||||||
|
|
||||||
bool isUpdating = false;
|
|
||||||
|
|
||||||
void refreshAccounts() {
|
|
||||||
// try {
|
|
||||||
// isUpdating = true;
|
|
||||||
// accountRefreshNative();
|
|
||||||
// isUpdating = false;
|
|
||||||
// } catch (e) {
|
|
||||||
// isUpdating = false;
|
|
||||||
// rethrow;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AccountRow> getAllAccount() {
|
|
||||||
// final size = accountSizeNative();
|
|
||||||
// final accountAddressesPointer = accountGetAllNative();
|
|
||||||
// final accountAddresses = accountAddressesPointer.asTypedList(size);
|
|
||||||
|
|
||||||
// return accountAddresses
|
|
||||||
// .map((addr) => Pointer<AccountRow>.fromAddress(addr).ref)
|
|
||||||
// .toList();
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
void addAccountSync({required String label}) {
|
|
||||||
// final labelPointer = label.toNativeUtf8();
|
|
||||||
// accountAddNewNative(labelPointer);
|
|
||||||
// calloc.free(labelPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLabelForAccountSync({required int accountIndex, required String label}) {
|
|
||||||
// final labelPointer = label.toNativeUtf8();
|
|
||||||
// accountSetLabelNative(accountIndex, labelPointer);
|
|
||||||
// calloc.free(labelPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _addAccount(String label) => addAccountSync(label: label);
|
|
||||||
|
|
||||||
void _setLabelForAccount(Map<String, dynamic> args) {
|
|
||||||
// final label = args['label'] as String;
|
|
||||||
// final accountIndex = args['accountIndex'] as int;
|
|
||||||
|
|
||||||
// setLabelForAccountSync(label: label, accountIndex: accountIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> addAccount({required String label}) async {
|
|
||||||
// await compute(_addAccount, label);
|
|
||||||
// await store();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> setLabelForAccount({required int accountIndex, required String label}) async {
|
|
||||||
// await compute(_setLabelForAccount, {'accountIndex': accountIndex, 'label': label});
|
|
||||||
// await store();
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
String convertUTF8ToString({required Pointer<Utf8> pointer}) {
|
|
||||||
final str = pointer.toDartString();
|
|
||||||
calloc.free(pointer);
|
|
||||||
return str;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
class ConnectionToNodeException implements Exception {
|
|
||||||
ConnectionToNodeException({required this.message});
|
|
||||||
|
|
||||||
final String message;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
class CreationTransactionException implements Exception {
|
|
||||||
CreationTransactionException({required this.message});
|
|
||||||
|
|
||||||
final String message;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => message;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
class SetupWalletException implements Exception {
|
|
||||||
SetupWalletException({required this.message});
|
|
||||||
|
|
||||||
final String message;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
class WalletCreationException implements Exception {
|
|
||||||
WalletCreationException({required this.message});
|
|
||||||
|
|
||||||
final String message;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => message;
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
class WalletOpeningException implements Exception {
|
|
||||||
WalletOpeningException({required this.message});
|
|
||||||
|
|
||||||
final String message;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() => message;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
class WalletRestoreFromKeysException implements Exception {
|
|
||||||
WalletRestoreFromKeysException({required this.message});
|
|
||||||
|
|
||||||
final String message;
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
class WalletRestoreFromSeedException implements Exception {
|
|
||||||
WalletRestoreFromSeedException({required this.message});
|
|
||||||
|
|
||||||
final String message;
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
final DynamicLibrary moneroApi = Platform.isAndroid
|
|
||||||
? DynamicLibrary.open("libcw_monero.so")
|
|
||||||
: DynamicLibrary.open("cw_monero.framework/cw_monero");
|
|
|
@ -1,6 +0,0 @@
|
||||||
class MoneroOutput {
|
|
||||||
MoneroOutput({required this.address, required this.amount});
|
|
||||||
|
|
||||||
final String address;
|
|
||||||
final String amount;
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
|
||||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
typedef create_wallet = Int8 Function(
|
|
||||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef restore_wallet_from_seed = Int8 Function(
|
|
||||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef restore_wallet_from_keys = Int8 Function(Pointer<Utf8>, Pointer<Utf8>,
|
|
||||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef is_wallet_exist = Int8 Function(Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef load_wallet = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Int8);
|
|
||||||
|
|
||||||
typedef error_string = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef get_filename = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef get_seed = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef get_address = Pointer<Utf8> Function(Int32, Int32);
|
|
||||||
|
|
||||||
typedef get_full_balanace = Int64 Function(Int32);
|
|
||||||
|
|
||||||
typedef get_unlocked_balanace = Int64 Function(Int32);
|
|
||||||
|
|
||||||
typedef get_current_height = Int64 Function();
|
|
||||||
|
|
||||||
typedef get_node_height = Int64 Function();
|
|
||||||
|
|
||||||
typedef is_connected = Int8 Function();
|
|
||||||
|
|
||||||
typedef setup_node = Int8 Function(
|
|
||||||
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, Int8, Int8, Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef start_refresh = Void Function();
|
|
||||||
|
|
||||||
typedef connect_to_node = Int8 Function();
|
|
||||||
|
|
||||||
typedef set_refresh_from_block_height = Void Function(Int64);
|
|
||||||
|
|
||||||
typedef set_recovering_from_seed = Void Function(Int8);
|
|
||||||
|
|
||||||
typedef store_c = Void Function(Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef set_password = Int8 Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
|
|
||||||
|
|
||||||
typedef set_listener = Void Function();
|
|
||||||
|
|
||||||
typedef get_syncing_height = Int64 Function();
|
|
||||||
|
|
||||||
typedef is_needed_to_refresh = Int8 Function();
|
|
||||||
|
|
||||||
typedef is_new_transaction_exist = Int8 Function();
|
|
||||||
|
|
||||||
typedef subaddrress_size = Int32 Function();
|
|
||||||
|
|
||||||
typedef subaddrress_refresh = Void Function(Int32);
|
|
||||||
|
|
||||||
typedef subaddress_get_all = Pointer<Int64> Function();
|
|
||||||
|
|
||||||
typedef subaddress_add_new = Void Function(
|
|
||||||
Int32 accountIndex, Pointer<Utf8> label);
|
|
||||||
|
|
||||||
typedef subaddress_set_label = Void Function(
|
|
||||||
Int32 accountIndex, Int32 addressIndex, Pointer<Utf8> label);
|
|
||||||
|
|
||||||
typedef account_size = Int32 Function();
|
|
||||||
|
|
||||||
typedef account_refresh = Void Function();
|
|
||||||
|
|
||||||
typedef account_get_all = Pointer<Int64> Function();
|
|
||||||
|
|
||||||
typedef account_add_new = Void Function(Pointer<Utf8> label);
|
|
||||||
|
|
||||||
typedef account_set_label = Void Function(
|
|
||||||
Int32 accountIndex, Pointer<Utf8> label);
|
|
||||||
|
|
||||||
typedef transactions_refresh = Void Function();
|
|
||||||
|
|
||||||
typedef get_tx_key = Pointer<Utf8>? Function(Pointer<Utf8> txId);
|
|
||||||
|
|
||||||
typedef transactions_count = Int64 Function();
|
|
||||||
|
|
||||||
typedef transactions_get_all = Pointer<Int64> Function();
|
|
||||||
|
|
||||||
typedef transaction_create = Int8 Function(
|
|
||||||
Pointer<Utf8> address,
|
|
||||||
Pointer<Utf8> paymentId,
|
|
||||||
Pointer<Utf8> amount,
|
|
||||||
Int8 priorityRaw,
|
|
||||||
Int32 subaddrAccount,
|
|
||||||
Pointer<Utf8Box> error,
|
|
||||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
|
||||||
|
|
||||||
typedef transaction_create_mult_dest = Int8 Function(
|
|
||||||
Pointer<Pointer<Utf8>> addresses,
|
|
||||||
Pointer<Utf8> paymentId,
|
|
||||||
Pointer<Pointer<Utf8>> amounts,
|
|
||||||
Int32 size,
|
|
||||||
Int8 priorityRaw,
|
|
||||||
Int32 subaddrAccount,
|
|
||||||
Pointer<Utf8Box> error,
|
|
||||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
|
||||||
|
|
||||||
typedef transaction_commit = Int8 Function(Pointer<PendingTransactionRaw>, Pointer<Utf8Box>);
|
|
||||||
|
|
||||||
typedef secret_view_key = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef public_view_key = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef secret_spend_key = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef public_spend_key = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef close_current_wallet = Void Function();
|
|
||||||
|
|
||||||
typedef on_startup = Void Function();
|
|
||||||
|
|
||||||
typedef rescan_blockchain = Void Function();
|
|
||||||
|
|
||||||
typedef get_subaddress_label = Pointer<Utf8> Function(
|
|
||||||
Int32 accountIndex,
|
|
||||||
Int32 addressIndex);
|
|
||||||
|
|
||||||
typedef set_trusted_daemon = Void Function(Int8 trusted);
|
|
||||||
|
|
||||||
typedef trusted_daemon = Int8 Function();
|
|
|
@ -1,12 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
class AccountRow extends Struct {
|
|
||||||
@Int64()
|
|
||||||
external int id;
|
|
||||||
|
|
||||||
external Pointer<Utf8> label;
|
|
||||||
|
|
||||||
String getLabel() => label.toDartString();
|
|
||||||
int getId() => id;
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
class PendingTransactionRaw extends Struct {
|
|
||||||
@Int64()
|
|
||||||
external int amount;
|
|
||||||
|
|
||||||
@Int64()
|
|
||||||
external int fee;
|
|
||||||
|
|
||||||
external Pointer<Utf8> hash;
|
|
||||||
|
|
||||||
external Pointer<Utf8> hex;
|
|
||||||
|
|
||||||
external Pointer<Utf8> txKey;
|
|
||||||
|
|
||||||
String getHash() => hash.toDartString();
|
|
||||||
|
|
||||||
String getHex() => hex.toDartString();
|
|
||||||
|
|
||||||
String getKey() => txKey.toDartString();
|
|
||||||
}
|
|
||||||
|
|
||||||
class PendingTransactionDescription {
|
|
||||||
PendingTransactionDescription({
|
|
||||||
required this.amount,
|
|
||||||
required this.fee,
|
|
||||||
required this.hash,
|
|
||||||
required this.hex,
|
|
||||||
required this.txKey,
|
|
||||||
required this.pointerAddress});
|
|
||||||
|
|
||||||
final int amount;
|
|
||||||
final int fee;
|
|
||||||
final String hash;
|
|
||||||
final String hex;
|
|
||||||
final String txKey;
|
|
||||||
final int pointerAddress;
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
class SubaddressRow extends Struct {
|
|
||||||
@Int64()
|
|
||||||
external int id;
|
|
||||||
|
|
||||||
external Pointer<Utf8> address;
|
|
||||||
|
|
||||||
external Pointer<Utf8> label;
|
|
||||||
|
|
||||||
String getLabel() => label.toDartString();
|
|
||||||
String getAddress() => address.toDartString();
|
|
||||||
int getId() => id;
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
class TransactionInfoRow extends Struct {
|
|
||||||
@Uint64()
|
|
||||||
external int amount;
|
|
||||||
|
|
||||||
@Uint64()
|
|
||||||
external int fee;
|
|
||||||
|
|
||||||
@Uint64()
|
|
||||||
external int blockHeight;
|
|
||||||
|
|
||||||
@Uint64()
|
|
||||||
external int confirmations;
|
|
||||||
|
|
||||||
@Uint32()
|
|
||||||
external int subaddrAccount;
|
|
||||||
|
|
||||||
@Int8()
|
|
||||||
external int direction;
|
|
||||||
|
|
||||||
@Int8()
|
|
||||||
external int isPending;
|
|
||||||
|
|
||||||
@Uint32()
|
|
||||||
external int subaddrIndex;
|
|
||||||
|
|
||||||
external Pointer<Utf8> hash;
|
|
||||||
|
|
||||||
external Pointer<Utf8> paymentId;
|
|
||||||
|
|
||||||
@Int64()
|
|
||||||
external int datetime;
|
|
||||||
|
|
||||||
int getDatetime() => datetime;
|
|
||||||
int getAmount() => amount >= 0 ? amount : amount * -1;
|
|
||||||
bool getIsPending() => isPending != 0;
|
|
||||||
String getHash() => hash.toDartString();
|
|
||||||
String getPaymentId() => paymentId.toDartString();
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
class Utf8Box extends Struct {
|
|
||||||
external Pointer<Utf8> value;
|
|
||||||
|
|
||||||
String getValue() => value.toDartString();
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:cw_monero/api/signatures.dart';
|
|
||||||
import 'package:cw_monero/api/types.dart';
|
|
||||||
import 'package:cw_monero/api/monero_api.dart';
|
|
||||||
import 'package:cw_monero/api/structs/subaddress_row.dart';
|
|
||||||
import 'package:cw_monero/api/wallet.dart';
|
|
||||||
|
|
||||||
final subaddressSizeNative = moneroApi
|
|
||||||
.lookup<NativeFunction<subaddrress_size>>('subaddrress_size')
|
|
||||||
.asFunction<SubaddressSize>();
|
|
||||||
|
|
||||||
final subaddressRefreshNative = moneroApi
|
|
||||||
.lookup<NativeFunction<subaddrress_refresh>>('subaddress_refresh')
|
|
||||||
.asFunction<SubaddressRefresh>();
|
|
||||||
|
|
||||||
final subaddrressGetAllNative = moneroApi
|
|
||||||
.lookup<NativeFunction<subaddress_get_all>>('subaddrress_get_all')
|
|
||||||
.asFunction<SubaddressGetAll>();
|
|
||||||
|
|
||||||
final subaddrressAddNewNative = moneroApi
|
|
||||||
.lookup<NativeFunction<subaddress_add_new>>('subaddress_add_row')
|
|
||||||
.asFunction<SubaddressAddNew>();
|
|
||||||
|
|
||||||
final subaddrressSetLabelNative = moneroApi
|
|
||||||
.lookup<NativeFunction<subaddress_set_label>>('subaddress_set_label')
|
|
||||||
.asFunction<SubaddressSetLabel>();
|
|
||||||
|
|
||||||
bool isUpdating = false;
|
|
||||||
|
|
||||||
void refreshSubaddresses({required int accountIndex}) {
|
|
||||||
try {
|
|
||||||
isUpdating = true;
|
|
||||||
subaddressRefreshNative(accountIndex);
|
|
||||||
isUpdating = false;
|
|
||||||
} catch (e) {
|
|
||||||
isUpdating = false;
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<SubaddressRow> getAllSubaddresses() {
|
|
||||||
final size = subaddressSizeNative();
|
|
||||||
final subaddressAddressesPointer = subaddrressGetAllNative();
|
|
||||||
final subaddressAddresses = subaddressAddressesPointer.asTypedList(size);
|
|
||||||
|
|
||||||
return subaddressAddresses
|
|
||||||
.map((addr) => Pointer<SubaddressRow>.fromAddress(addr).ref)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
void addSubaddressSync({required int accountIndex, required String label}) {
|
|
||||||
final labelPointer = label.toNativeUtf8();
|
|
||||||
subaddrressAddNewNative(accountIndex, labelPointer);
|
|
||||||
calloc.free(labelPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLabelForSubaddressSync(
|
|
||||||
{required int accountIndex, required int addressIndex, required String label}) {
|
|
||||||
final labelPointer = label.toNativeUtf8();
|
|
||||||
|
|
||||||
subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer);
|
|
||||||
calloc.free(labelPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _addSubaddress(Map<String, dynamic> args) {
|
|
||||||
final label = args['label'] as String;
|
|
||||||
final accountIndex = args['accountIndex'] as int;
|
|
||||||
|
|
||||||
addSubaddressSync(accountIndex: accountIndex, label: label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _setLabelForSubaddress(Map<String, dynamic> args) {
|
|
||||||
final label = args['label'] as String;
|
|
||||||
final accountIndex = args['accountIndex'] as int;
|
|
||||||
final addressIndex = args['addressIndex'] as int;
|
|
||||||
|
|
||||||
setLabelForSubaddressSync(
|
|
||||||
accountIndex: accountIndex, addressIndex: addressIndex, label: label);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> addSubaddress({required int accountIndex, required String label}) async {
|
|
||||||
await compute<Map<String, Object>, void>(
|
|
||||||
_addSubaddress, {'accountIndex': accountIndex, 'label': label});
|
|
||||||
await store();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> setLabelForSubaddress(
|
|
||||||
{required int accountIndex, required int addressIndex, required String label}) async {
|
|
||||||
await compute<Map<String, Object>, void>(_setLabelForSubaddress, {
|
|
||||||
'accountIndex': accountIndex,
|
|
||||||
'addressIndex': addressIndex,
|
|
||||||
'label': label
|
|
||||||
});
|
|
||||||
await store();
|
|
||||||
}
|
|
|
@ -1,234 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:cw_monero/api/convert_utf8_to_string.dart';
|
|
||||||
import 'package:cw_monero/api/monero_output.dart';
|
|
||||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:cw_monero/api/signatures.dart';
|
|
||||||
import 'package:cw_monero/api/types.dart';
|
|
||||||
import 'package:cw_monero/api/monero_api.dart';
|
|
||||||
import 'package:cw_monero/api/structs/transaction_info_row.dart';
|
|
||||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
|
||||||
import 'package:cw_monero/api/exceptions/creation_transaction_exception.dart';
|
|
||||||
|
|
||||||
final transactionsRefreshNative = moneroApi
|
|
||||||
.lookup<NativeFunction<transactions_refresh>>('transactions_refresh')
|
|
||||||
.asFunction<TransactionsRefresh>();
|
|
||||||
|
|
||||||
final transactionsCountNative = moneroApi
|
|
||||||
.lookup<NativeFunction<transactions_count>>('transactions_count')
|
|
||||||
.asFunction<TransactionsCount>();
|
|
||||||
|
|
||||||
final transactionsGetAllNative = moneroApi
|
|
||||||
.lookup<NativeFunction<transactions_get_all>>('transactions_get_all')
|
|
||||||
.asFunction<TransactionsGetAll>();
|
|
||||||
|
|
||||||
final transactionCreateNative = moneroApi
|
|
||||||
.lookup<NativeFunction<transaction_create>>('transaction_create')
|
|
||||||
.asFunction<TransactionCreate>();
|
|
||||||
|
|
||||||
final transactionCreateMultDestNative = moneroApi
|
|
||||||
.lookup<NativeFunction<transaction_create_mult_dest>>('transaction_create_mult_dest')
|
|
||||||
.asFunction<TransactionCreateMultDest>();
|
|
||||||
|
|
||||||
final transactionCommitNative = moneroApi
|
|
||||||
.lookup<NativeFunction<transaction_commit>>('transaction_commit')
|
|
||||||
.asFunction<TransactionCommit>();
|
|
||||||
|
|
||||||
final getTxKeyNative = moneroApi
|
|
||||||
.lookup<NativeFunction<get_tx_key>>('get_tx_key')
|
|
||||||
.asFunction<GetTxKey>();
|
|
||||||
|
|
||||||
String getTxKey(String txId) {
|
|
||||||
final txIdPointer = txId.toNativeUtf8();
|
|
||||||
final keyPointer = getTxKeyNative(txIdPointer);
|
|
||||||
|
|
||||||
calloc.free(txIdPointer);
|
|
||||||
|
|
||||||
if (keyPointer != null) {
|
|
||||||
return convertUTF8ToString(pointer: keyPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
void refreshTransactions() => transactionsRefreshNative();
|
|
||||||
|
|
||||||
int countOfTransactions() => transactionsCountNative();
|
|
||||||
|
|
||||||
List<TransactionInfoRow> getAllTransations() {
|
|
||||||
final size = transactionsCountNative();
|
|
||||||
final transactionsPointer = transactionsGetAllNative();
|
|
||||||
final transactionsAddresses = transactionsPointer.asTypedList(size);
|
|
||||||
|
|
||||||
return transactionsAddresses
|
|
||||||
.map((addr) => Pointer<TransactionInfoRow>.fromAddress(addr).ref)
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
PendingTransactionDescription createTransactionSync(
|
|
||||||
{required String address,
|
|
||||||
required String paymentId,
|
|
||||||
required int priorityRaw,
|
|
||||||
String? amount,
|
|
||||||
int accountIndex = 0}) {
|
|
||||||
final addressPointer = address.toNativeUtf8();
|
|
||||||
final paymentIdPointer = paymentId.toNativeUtf8();
|
|
||||||
final amountPointer = amount != null ? amount.toNativeUtf8() : nullptr;
|
|
||||||
final errorMessagePointer = calloc<Utf8Box>();
|
|
||||||
final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
|
|
||||||
final created = transactionCreateNative(
|
|
||||||
addressPointer,
|
|
||||||
paymentIdPointer,
|
|
||||||
amountPointer,
|
|
||||||
priorityRaw,
|
|
||||||
accountIndex,
|
|
||||||
errorMessagePointer,
|
|
||||||
pendingTransactionRawPointer) !=
|
|
||||||
0;
|
|
||||||
|
|
||||||
calloc.free(addressPointer);
|
|
||||||
calloc.free(paymentIdPointer);
|
|
||||||
|
|
||||||
if (amountPointer != nullptr) {
|
|
||||||
calloc.free(amountPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!created) {
|
|
||||||
final message = errorMessagePointer.ref.getValue();
|
|
||||||
calloc.free(errorMessagePointer);
|
|
||||||
throw CreationTransactionException(message: message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return PendingTransactionDescription(
|
|
||||||
amount: pendingTransactionRawPointer.ref.amount,
|
|
||||||
fee: pendingTransactionRawPointer.ref.fee,
|
|
||||||
hash: pendingTransactionRawPointer.ref.getHash(),
|
|
||||||
hex: pendingTransactionRawPointer.ref.getHex(),
|
|
||||||
txKey: pendingTransactionRawPointer.ref.getKey(),
|
|
||||||
pointerAddress: pendingTransactionRawPointer.address);
|
|
||||||
}
|
|
||||||
|
|
||||||
PendingTransactionDescription createTransactionMultDestSync(
|
|
||||||
{required List<MoneroOutput> outputs,
|
|
||||||
required String paymentId,
|
|
||||||
required int priorityRaw,
|
|
||||||
int accountIndex = 0}) {
|
|
||||||
final int size = outputs.length;
|
|
||||||
final List<Pointer<Utf8>> addressesPointers = outputs.map((output) =>
|
|
||||||
output.address.toNativeUtf8()).toList();
|
|
||||||
final Pointer<Pointer<Utf8>> addressesPointerPointer = calloc(size);
|
|
||||||
final List<Pointer<Utf8>> amountsPointers = outputs.map((output) =>
|
|
||||||
output.amount.toNativeUtf8()).toList();
|
|
||||||
final Pointer<Pointer<Utf8>> amountsPointerPointer = calloc(size);
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
addressesPointerPointer[i] = addressesPointers[i];
|
|
||||||
amountsPointerPointer[i] = amountsPointers[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
final paymentIdPointer = paymentId.toNativeUtf8();
|
|
||||||
final errorMessagePointer = calloc<Utf8Box>();
|
|
||||||
final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
|
|
||||||
final created = transactionCreateMultDestNative(
|
|
||||||
addressesPointerPointer,
|
|
||||||
paymentIdPointer,
|
|
||||||
amountsPointerPointer,
|
|
||||||
size,
|
|
||||||
priorityRaw,
|
|
||||||
accountIndex,
|
|
||||||
errorMessagePointer,
|
|
||||||
pendingTransactionRawPointer) !=
|
|
||||||
0;
|
|
||||||
|
|
||||||
calloc.free(addressesPointerPointer);
|
|
||||||
calloc.free(amountsPointerPointer);
|
|
||||||
|
|
||||||
addressesPointers.forEach((element) => calloc.free(element));
|
|
||||||
amountsPointers.forEach((element) => calloc.free(element));
|
|
||||||
|
|
||||||
calloc.free(paymentIdPointer);
|
|
||||||
|
|
||||||
if (!created) {
|
|
||||||
final message = errorMessagePointer.ref.getValue();
|
|
||||||
calloc.free(errorMessagePointer);
|
|
||||||
throw CreationTransactionException(message: message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return PendingTransactionDescription(
|
|
||||||
amount: pendingTransactionRawPointer.ref.amount,
|
|
||||||
fee: pendingTransactionRawPointer.ref.fee,
|
|
||||||
hash: pendingTransactionRawPointer.ref.getHash(),
|
|
||||||
hex: pendingTransactionRawPointer.ref.getHex(),
|
|
||||||
txKey: pendingTransactionRawPointer.ref.getKey(),
|
|
||||||
pointerAddress: pendingTransactionRawPointer.address);
|
|
||||||
}
|
|
||||||
|
|
||||||
void commitTransactionFromPointerAddress({required int address}) => commitTransaction(
|
|
||||||
transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address));
|
|
||||||
|
|
||||||
void commitTransaction({required Pointer<PendingTransactionRaw> transactionPointer}) {
|
|
||||||
final errorMessagePointer = calloc<Utf8Box>();
|
|
||||||
final isCommited =
|
|
||||||
transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
|
|
||||||
|
|
||||||
if (!isCommited) {
|
|
||||||
final message = errorMessagePointer.ref.getValue();
|
|
||||||
calloc.free(errorMessagePointer);
|
|
||||||
throw CreationTransactionException(message: message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PendingTransactionDescription _createTransactionSync(Map args) {
|
|
||||||
final address = args['address'] as String;
|
|
||||||
final paymentId = args['paymentId'] as String;
|
|
||||||
final amount = args['amount'] as String?;
|
|
||||||
final priorityRaw = args['priorityRaw'] as int;
|
|
||||||
final accountIndex = args['accountIndex'] as int;
|
|
||||||
|
|
||||||
return createTransactionSync(
|
|
||||||
address: address,
|
|
||||||
paymentId: paymentId,
|
|
||||||
amount: amount,
|
|
||||||
priorityRaw: priorityRaw,
|
|
||||||
accountIndex: accountIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
PendingTransactionDescription _createTransactionMultDestSync(Map args) {
|
|
||||||
final outputs = args['outputs'] as List<MoneroOutput>;
|
|
||||||
final paymentId = args['paymentId'] as String;
|
|
||||||
final priorityRaw = args['priorityRaw'] as int;
|
|
||||||
final accountIndex = args['accountIndex'] as int;
|
|
||||||
|
|
||||||
return createTransactionMultDestSync(
|
|
||||||
outputs: outputs,
|
|
||||||
paymentId: paymentId,
|
|
||||||
priorityRaw: priorityRaw,
|
|
||||||
accountIndex: accountIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<PendingTransactionDescription> createTransaction(
|
|
||||||
{required String address,
|
|
||||||
required int priorityRaw,
|
|
||||||
String? amount,
|
|
||||||
String paymentId = '',
|
|
||||||
int accountIndex = 0}) =>
|
|
||||||
compute(_createTransactionSync, {
|
|
||||||
'address': address,
|
|
||||||
'paymentId': paymentId,
|
|
||||||
'amount': amount,
|
|
||||||
'priorityRaw': priorityRaw,
|
|
||||||
'accountIndex': accountIndex
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<PendingTransactionDescription> createTransactionMultDest(
|
|
||||||
{required List<MoneroOutput> outputs,
|
|
||||||
required int priorityRaw,
|
|
||||||
String paymentId = '',
|
|
||||||
int accountIndex = 0}) =>
|
|
||||||
compute(_createTransactionMultDestSync, {
|
|
||||||
'outputs': outputs,
|
|
||||||
'paymentId': paymentId,
|
|
||||||
'priorityRaw': priorityRaw,
|
|
||||||
'accountIndex': accountIndex
|
|
||||||
});
|
|
|
@ -1,130 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:cw_monero/api/structs/pending_transaction.dart';
|
|
||||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
|
|
||||||
typedef CreateWallet = int Function(
|
|
||||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef RestoreWalletFromSeed = int Function(
|
|
||||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef RestoreWalletFromKeys = int Function(Pointer<Utf8>, Pointer<Utf8>,
|
|
||||||
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, int, int, Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef IsWalletExist = int Function(Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef LoadWallet = int Function(Pointer<Utf8>, Pointer<Utf8>, int);
|
|
||||||
|
|
||||||
typedef ErrorString = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef GetFilename = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef GetSeed = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef GetAddress = Pointer<Utf8> Function(int, int);
|
|
||||||
|
|
||||||
typedef GetFullBalance = int Function(int);
|
|
||||||
|
|
||||||
typedef GetUnlockedBalance = int Function(int);
|
|
||||||
|
|
||||||
typedef GetCurrentHeight = int Function();
|
|
||||||
|
|
||||||
typedef GetNodeHeight = int Function();
|
|
||||||
|
|
||||||
typedef IsConnected = int Function();
|
|
||||||
|
|
||||||
typedef SetupNode = int Function(
|
|
||||||
Pointer<Utf8>, Pointer<Utf8>?, Pointer<Utf8>?, int, int, Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef StartRefresh = void Function();
|
|
||||||
|
|
||||||
typedef ConnectToNode = int Function();
|
|
||||||
|
|
||||||
typedef SetRefreshFromBlockHeight = void Function(int);
|
|
||||||
|
|
||||||
typedef SetRecoveringFromSeed = void Function(int);
|
|
||||||
|
|
||||||
typedef Store = void Function(Pointer<Utf8>);
|
|
||||||
|
|
||||||
typedef SetPassword = int Function(Pointer<Utf8> password, Pointer<Utf8Box> error);
|
|
||||||
|
|
||||||
typedef SetListener = void Function();
|
|
||||||
|
|
||||||
typedef GetSyncingHeight = int Function();
|
|
||||||
|
|
||||||
typedef IsNeededToRefresh = int Function();
|
|
||||||
|
|
||||||
typedef IsNewTransactionExist = int Function();
|
|
||||||
|
|
||||||
typedef SubaddressSize = int Function();
|
|
||||||
|
|
||||||
typedef SubaddressRefresh = void Function(int);
|
|
||||||
|
|
||||||
typedef SubaddressGetAll = Pointer<Int64> Function();
|
|
||||||
|
|
||||||
typedef SubaddressAddNew = void Function(int accountIndex, Pointer<Utf8> label);
|
|
||||||
|
|
||||||
typedef SubaddressSetLabel = void Function(
|
|
||||||
int accountIndex, int addressIndex, Pointer<Utf8> label);
|
|
||||||
|
|
||||||
typedef AccountSize = int Function();
|
|
||||||
|
|
||||||
typedef AccountRefresh = void Function();
|
|
||||||
|
|
||||||
typedef AccountGetAll = Pointer<Int64> Function();
|
|
||||||
|
|
||||||
typedef AccountAddNew = void Function(Pointer<Utf8> label);
|
|
||||||
|
|
||||||
typedef AccountSetLabel = void Function(int accountIndex, Pointer<Utf8> label);
|
|
||||||
|
|
||||||
typedef TransactionsRefresh = void Function();
|
|
||||||
|
|
||||||
typedef GetTxKey = Pointer<Utf8>? Function(Pointer<Utf8> txId);
|
|
||||||
|
|
||||||
typedef TransactionsCount = int Function();
|
|
||||||
|
|
||||||
typedef TransactionsGetAll = Pointer<Int64> Function();
|
|
||||||
|
|
||||||
typedef TransactionCreate = int Function(
|
|
||||||
Pointer<Utf8> address,
|
|
||||||
Pointer<Utf8> paymentId,
|
|
||||||
Pointer<Utf8> amount,
|
|
||||||
int priorityRaw,
|
|
||||||
int subaddrAccount,
|
|
||||||
Pointer<Utf8Box> error,
|
|
||||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
|
||||||
|
|
||||||
typedef TransactionCreateMultDest = int Function(
|
|
||||||
Pointer<Pointer<Utf8>> addresses,
|
|
||||||
Pointer<Utf8> paymentId,
|
|
||||||
Pointer<Pointer<Utf8>> amounts,
|
|
||||||
int size,
|
|
||||||
int priorityRaw,
|
|
||||||
int subaddrAccount,
|
|
||||||
Pointer<Utf8Box> error,
|
|
||||||
Pointer<PendingTransactionRaw> pendingTransaction);
|
|
||||||
|
|
||||||
typedef TransactionCommit = int Function(Pointer<PendingTransactionRaw>, Pointer<Utf8Box>);
|
|
||||||
|
|
||||||
typedef SecretViewKey = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef PublicViewKey = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef SecretSpendKey = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef PublicSpendKey = Pointer<Utf8> Function();
|
|
||||||
|
|
||||||
typedef CloseCurrentWallet = void Function();
|
|
||||||
|
|
||||||
typedef OnStartup = void Function();
|
|
||||||
|
|
||||||
typedef RescanBlockchainAsync = void Function();
|
|
||||||
|
|
||||||
typedef GetSubaddressLabel = Pointer<Utf8> Function(
|
|
||||||
int accountIndex,
|
|
||||||
int addressIndex);
|
|
||||||
|
|
||||||
typedef SetTrustedDaemon = void Function(int);
|
|
||||||
|
|
||||||
typedef TrustedDaemon = int Function();
|
|
|
@ -1,353 +0,0 @@
|
||||||
import 'dart:async';
|
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
import 'package:cw_monero/api/structs/ut8_box.dart';
|
|
||||||
import 'package:cw_monero/api/convert_utf8_to_string.dart';
|
|
||||||
import 'package:cw_monero/api/signatures.dart';
|
|
||||||
import 'package:cw_monero/api/types.dart';
|
|
||||||
import 'package:cw_monero/api/monero_api.dart';
|
|
||||||
import 'package:cw_monero/api/exceptions/setup_wallet_exception.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
int _boolToInt(bool value) => value ? 1 : 0;
|
|
||||||
|
|
||||||
final getFileNameNative =
|
|
||||||
moneroApi.lookup<NativeFunction<get_filename>>('get_filename').asFunction<GetFilename>();
|
|
||||||
|
|
||||||
final getSeedNative = moneroApi.lookup<NativeFunction<get_seed>>('seed').asFunction<GetSeed>();
|
|
||||||
|
|
||||||
final getAddressNative =
|
|
||||||
moneroApi.lookup<NativeFunction<get_address>>('get_address').asFunction<GetAddress>();
|
|
||||||
|
|
||||||
final getFullBalanceNative = moneroApi
|
|
||||||
.lookup<NativeFunction<get_full_balanace>>('get_full_balance')
|
|
||||||
.asFunction<GetFullBalance>();
|
|
||||||
|
|
||||||
final getUnlockedBalanceNative = moneroApi
|
|
||||||
.lookup<NativeFunction<get_unlocked_balanace>>('get_unlocked_balance')
|
|
||||||
.asFunction<GetUnlockedBalance>();
|
|
||||||
|
|
||||||
final getCurrentHeightNative = moneroApi
|
|
||||||
.lookup<NativeFunction<get_current_height>>('get_current_height')
|
|
||||||
.asFunction<GetCurrentHeight>();
|
|
||||||
|
|
||||||
final getNodeHeightNative = moneroApi
|
|
||||||
.lookup<NativeFunction<get_node_height>>('get_node_height')
|
|
||||||
.asFunction<GetNodeHeight>();
|
|
||||||
|
|
||||||
final isConnectedNative =
|
|
||||||
moneroApi.lookup<NativeFunction<is_connected>>('is_connected').asFunction<IsConnected>();
|
|
||||||
|
|
||||||
final setupNodeNative =
|
|
||||||
moneroApi.lookup<NativeFunction<setup_node>>('setup_node').asFunction<SetupNode>();
|
|
||||||
|
|
||||||
final startRefreshNative =
|
|
||||||
moneroApi.lookup<NativeFunction<start_refresh>>('start_refresh').asFunction<StartRefresh>();
|
|
||||||
|
|
||||||
final connecToNodeNative = moneroApi
|
|
||||||
.lookup<NativeFunction<connect_to_node>>('connect_to_node')
|
|
||||||
.asFunction<ConnectToNode>();
|
|
||||||
|
|
||||||
final setRefreshFromBlockHeightNative = moneroApi
|
|
||||||
.lookup<NativeFunction<set_refresh_from_block_height>>('set_refresh_from_block_height')
|
|
||||||
.asFunction<SetRefreshFromBlockHeight>();
|
|
||||||
|
|
||||||
final setRecoveringFromSeedNative = moneroApi
|
|
||||||
.lookup<NativeFunction<set_recovering_from_seed>>('set_recovering_from_seed')
|
|
||||||
.asFunction<SetRecoveringFromSeed>();
|
|
||||||
|
|
||||||
final storeNative = moneroApi.lookup<NativeFunction<store_c>>('store').asFunction<Store>();
|
|
||||||
|
|
||||||
final setPasswordNative =
|
|
||||||
moneroApi.lookup<NativeFunction<set_password>>('set_password').asFunction<SetPassword>();
|
|
||||||
|
|
||||||
final setListenerNative =
|
|
||||||
moneroApi.lookup<NativeFunction<set_listener>>('set_listener').asFunction<SetListener>();
|
|
||||||
|
|
||||||
final getSyncingHeightNative = moneroApi
|
|
||||||
.lookup<NativeFunction<get_syncing_height>>('get_syncing_height')
|
|
||||||
.asFunction<GetSyncingHeight>();
|
|
||||||
|
|
||||||
final isNeededToRefreshNative = moneroApi
|
|
||||||
.lookup<NativeFunction<is_needed_to_refresh>>('is_needed_to_refresh')
|
|
||||||
.asFunction<IsNeededToRefresh>();
|
|
||||||
|
|
||||||
final isNewTransactionExistNative = moneroApi
|
|
||||||
.lookup<NativeFunction<is_new_transaction_exist>>('is_new_transaction_exist')
|
|
||||||
.asFunction<IsNewTransactionExist>();
|
|
||||||
|
|
||||||
final getSecretViewKeyNative = moneroApi
|
|
||||||
.lookup<NativeFunction<secret_view_key>>('secret_view_key')
|
|
||||||
.asFunction<SecretViewKey>();
|
|
||||||
|
|
||||||
final getPublicViewKeyNative = moneroApi
|
|
||||||
.lookup<NativeFunction<public_view_key>>('public_view_key')
|
|
||||||
.asFunction<PublicViewKey>();
|
|
||||||
|
|
||||||
final getSecretSpendKeyNative = moneroApi
|
|
||||||
.lookup<NativeFunction<secret_spend_key>>('secret_spend_key')
|
|
||||||
.asFunction<SecretSpendKey>();
|
|
||||||
|
|
||||||
final getPublicSpendKeyNative = moneroApi
|
|
||||||
.lookup<NativeFunction<secret_view_key>>('public_spend_key')
|
|
||||||
.asFunction<PublicSpendKey>();
|
|
||||||
|
|
||||||
final closeCurrentWalletNative = moneroApi
|
|
||||||
.lookup<NativeFunction<close_current_wallet>>('close_current_wallet')
|
|
||||||
.asFunction<CloseCurrentWallet>();
|
|
||||||
|
|
||||||
final onStartupNative =
|
|
||||||
moneroApi.lookup<NativeFunction<on_startup>>('on_startup').asFunction<OnStartup>();
|
|
||||||
|
|
||||||
final rescanBlockchainAsyncNative = moneroApi
|
|
||||||
.lookup<NativeFunction<rescan_blockchain>>('rescan_blockchain')
|
|
||||||
.asFunction<RescanBlockchainAsync>();
|
|
||||||
|
|
||||||
final getSubaddressLabelNative = moneroApi
|
|
||||||
.lookup<NativeFunction<get_subaddress_label>>('get_subaddress_label')
|
|
||||||
.asFunction<GetSubaddressLabel>();
|
|
||||||
|
|
||||||
final setTrustedDaemonNative = moneroApi
|
|
||||||
.lookup<NativeFunction<set_trusted_daemon>>('set_trusted_daemon')
|
|
||||||
.asFunction<SetTrustedDaemon>();
|
|
||||||
|
|
||||||
final trustedDaemonNative =
|
|
||||||
moneroApi.lookup<NativeFunction<trusted_daemon>>('trusted_daemon').asFunction<TrustedDaemon>();
|
|
||||||
|
|
||||||
int getSyncingHeight() => getSyncingHeightNative();
|
|
||||||
|
|
||||||
bool isNeededToRefresh() => isNeededToRefreshNative() != 0;
|
|
||||||
|
|
||||||
bool isNewTransactionExist() => isNewTransactionExistNative() != 0;
|
|
||||||
|
|
||||||
String getFilename() => convertUTF8ToString(pointer: getFileNameNative());
|
|
||||||
|
|
||||||
String getSeed() => convertUTF8ToString(pointer: getSeedNative());
|
|
||||||
|
|
||||||
String getAddress({int accountIndex = 0, int addressIndex = 0}) =>
|
|
||||||
convertUTF8ToString(pointer: getAddressNative(accountIndex, addressIndex));
|
|
||||||
|
|
||||||
int getFullBalance({int accountIndex = 0}) => getFullBalanceNative(accountIndex);
|
|
||||||
|
|
||||||
int getUnlockedBalance({int accountIndex = 0}) => getUnlockedBalanceNative(accountIndex);
|
|
||||||
|
|
||||||
int getCurrentHeight() => getCurrentHeightNative();
|
|
||||||
|
|
||||||
int getNodeHeightSync() => getNodeHeightNative();
|
|
||||||
|
|
||||||
bool isConnectedSync() => isConnectedNative() != 0;
|
|
||||||
|
|
||||||
bool setupNodeSync(
|
|
||||||
{required String address,
|
|
||||||
String? login,
|
|
||||||
String? password,
|
|
||||||
bool useSSL = false,
|
|
||||||
bool isLightWallet = false}) {
|
|
||||||
final addressPointer = address.toNativeUtf8();
|
|
||||||
Pointer<Utf8>? loginPointer;
|
|
||||||
Pointer<Utf8>? passwordPointer;
|
|
||||||
|
|
||||||
if (login != null) {
|
|
||||||
loginPointer = login.toNativeUtf8();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (password != null) {
|
|
||||||
passwordPointer = password.toNativeUtf8();
|
|
||||||
}
|
|
||||||
|
|
||||||
final errorMessagePointer = ''.toNativeUtf8();
|
|
||||||
// final isSetupNode = setupNodeNative(
|
|
||||||
// addressPointer,
|
|
||||||
// loginPointer,
|
|
||||||
// passwordPointer,
|
|
||||||
// _boolToInt(useSSL),
|
|
||||||
// _boolToInt(isLightWallet),
|
|
||||||
// errorMessagePointer) !=
|
|
||||||
// 0;
|
|
||||||
|
|
||||||
calloc.free(addressPointer);
|
|
||||||
|
|
||||||
if (loginPointer != null) {
|
|
||||||
calloc.free(loginPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (passwordPointer != null) {
|
|
||||||
calloc.free(passwordPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (!isSetupNode) {
|
|
||||||
// throw SetupWalletException(
|
|
||||||
// message: convertUTF8ToString(pointer: errorMessagePointer));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return isSetupNode;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void startRefreshSync() => startRefreshNative();
|
|
||||||
|
|
||||||
Future<bool> connectToNode() async => connecToNodeNative() != 0;
|
|
||||||
|
|
||||||
void setRefreshFromBlockHeight({required int height}) => setRefreshFromBlockHeightNative(height);
|
|
||||||
|
|
||||||
void setRecoveringFromSeed({required bool isRecovery}) =>
|
|
||||||
setRecoveringFromSeedNative(_boolToInt(isRecovery));
|
|
||||||
|
|
||||||
void storeSync() {
|
|
||||||
final pathPointer = ''.toNativeUtf8();
|
|
||||||
storeNative(pathPointer);
|
|
||||||
calloc.free(pathPointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPasswordSync(String password) {
|
|
||||||
final passwordPointer = password.toNativeUtf8();
|
|
||||||
final errorMessagePointer = calloc<Utf8Box>();
|
|
||||||
final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0;
|
|
||||||
calloc.free(passwordPointer);
|
|
||||||
|
|
||||||
if (!changed) {
|
|
||||||
final message = errorMessagePointer.ref.getValue();
|
|
||||||
calloc.free(errorMessagePointer);
|
|
||||||
throw Exception(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
calloc.free(errorMessagePointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void closeCurrentWallet() => closeCurrentWalletNative();
|
|
||||||
|
|
||||||
String getSecretViewKey() => convertUTF8ToString(pointer: getSecretViewKeyNative());
|
|
||||||
|
|
||||||
String getPublicViewKey() => convertUTF8ToString(pointer: getPublicViewKeyNative());
|
|
||||||
|
|
||||||
String getSecretSpendKey() => convertUTF8ToString(pointer: getSecretSpendKeyNative());
|
|
||||||
|
|
||||||
String getPublicSpendKey() => convertUTF8ToString(pointer: getPublicSpendKeyNative());
|
|
||||||
|
|
||||||
class SyncListener {
|
|
||||||
SyncListener(this.onNewBlock, this.onNewTransaction)
|
|
||||||
: _cachedBlockchainHeight = 0,
|
|
||||||
_lastKnownBlockHeight = 0,
|
|
||||||
_initialSyncHeight = 0;
|
|
||||||
|
|
||||||
void Function(int, int, double) onNewBlock;
|
|
||||||
void Function() onNewTransaction;
|
|
||||||
|
|
||||||
Timer? _updateSyncInfoTimer;
|
|
||||||
int _cachedBlockchainHeight;
|
|
||||||
int _lastKnownBlockHeight;
|
|
||||||
int _initialSyncHeight;
|
|
||||||
|
|
||||||
Future<int> getNodeHeightOrUpdate(int baseHeight) async {
|
|
||||||
if (_cachedBlockchainHeight < baseHeight || _cachedBlockchainHeight == 0) {
|
|
||||||
_cachedBlockchainHeight = await getNodeHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _cachedBlockchainHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() {
|
|
||||||
_cachedBlockchainHeight = 0;
|
|
||||||
_lastKnownBlockHeight = 0;
|
|
||||||
_initialSyncHeight = 0;
|
|
||||||
_updateSyncInfoTimer ??= Timer.periodic(Duration(milliseconds: 1200), (_) async {
|
|
||||||
if (isNewTransactionExist()) {
|
|
||||||
onNewTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
var syncHeight = getSyncingHeight();
|
|
||||||
|
|
||||||
if (syncHeight <= 0) {
|
|
||||||
syncHeight = getCurrentHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_initialSyncHeight <= 0) {
|
|
||||||
_initialSyncHeight = syncHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
final bchHeight = await getNodeHeightOrUpdate(syncHeight);
|
|
||||||
|
|
||||||
if (_lastKnownBlockHeight == syncHeight || syncHeight == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastKnownBlockHeight = syncHeight;
|
|
||||||
final track = bchHeight - _initialSyncHeight;
|
|
||||||
final diff = track - (bchHeight - syncHeight);
|
|
||||||
final ptc = diff <= 0 ? 0.0 : diff / track;
|
|
||||||
final left = bchHeight - syncHeight;
|
|
||||||
|
|
||||||
if (syncHeight < 0 || left < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. Actual new height; 2. Blocks left to finish; 3. Progress in percents;
|
|
||||||
onNewBlock?.call(syncHeight, left, ptc);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void stop() => _updateSyncInfoTimer?.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncListener setListeners(
|
|
||||||
void Function(int, int, double) onNewBlock, void Function() onNewTransaction) {
|
|
||||||
final listener = SyncListener(onNewBlock, onNewTransaction);
|
|
||||||
setListenerNative();
|
|
||||||
return listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onStartup() => onStartupNative();
|
|
||||||
|
|
||||||
void _storeSync(Object _) => storeSync();
|
|
||||||
|
|
||||||
bool _setupNodeSync(Map<String, Object?> args) {
|
|
||||||
final address = args['address'] as String;
|
|
||||||
final login = (args['login'] ?? '') as String;
|
|
||||||
final password = (args['password'] ?? '') as String;
|
|
||||||
final useSSL = args['useSSL'] as bool;
|
|
||||||
final isLightWallet = args['isLightWallet'] as bool;
|
|
||||||
|
|
||||||
return setupNodeSync(
|
|
||||||
address: address,
|
|
||||||
login: login,
|
|
||||||
password: password,
|
|
||||||
useSSL: useSSL,
|
|
||||||
isLightWallet: isLightWallet);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _isConnected(Object _) => isConnectedSync();
|
|
||||||
|
|
||||||
int _getNodeHeight(Object _) => getNodeHeightSync();
|
|
||||||
|
|
||||||
void startRefresh() => startRefreshSync();
|
|
||||||
|
|
||||||
Future<void> setupNode(
|
|
||||||
{required String address,
|
|
||||||
String? login,
|
|
||||||
String? password,
|
|
||||||
bool useSSL = false,
|
|
||||||
bool isLightWallet = false}) =>
|
|
||||||
compute<Map<String, Object?>, void>(_setupNodeSync, {
|
|
||||||
'address': address,
|
|
||||||
'login': login,
|
|
||||||
'password': password,
|
|
||||||
'useSSL': useSSL,
|
|
||||||
'isLightWallet': isLightWallet
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> store() => compute<int, void>(_storeSync, 0);
|
|
||||||
|
|
||||||
Future<bool> isConnected() => compute(_isConnected, 0);
|
|
||||||
|
|
||||||
Future<int> getNodeHeight() => compute(_getNodeHeight, 0);
|
|
||||||
|
|
||||||
void rescanBlockchainAsync() => rescanBlockchainAsyncNative();
|
|
||||||
|
|
||||||
String getSubaddressLabel(int accountIndex, int addressIndex) {
|
|
||||||
return convertUTF8ToString(pointer: getSubaddressLabelNative(accountIndex, addressIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future setTrustedDaemon(bool trusted) async => setTrustedDaemonNative(_boolToInt(trusted));
|
|
||||||
|
|
||||||
Future<bool> trustedDaemon() async => trustedDaemonNative() != 0;
|
|
|
@ -1,254 +0,0 @@
|
||||||
import 'dart:ffi';
|
|
||||||
import 'package:ffi/ffi.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:cw_monero/api/convert_utf8_to_string.dart';
|
|
||||||
import 'package:cw_monero/api/signatures.dart';
|
|
||||||
import 'package:cw_monero/api/types.dart';
|
|
||||||
import 'package:cw_monero/api/monero_api.dart';
|
|
||||||
import 'package:cw_monero/api/wallet.dart';
|
|
||||||
import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
|
|
||||||
import 'package:cw_monero/api/exceptions/wallet_creation_exception.dart';
|
|
||||||
import 'package:cw_monero/api/exceptions/wallet_restore_from_keys_exception.dart';
|
|
||||||
import 'package:cw_monero/api/exceptions/wallet_restore_from_seed_exception.dart';
|
|
||||||
|
|
||||||
final createWalletNative = moneroApi
|
|
||||||
.lookup<NativeFunction<create_wallet>>('create_wallet')
|
|
||||||
.asFunction<CreateWallet>();
|
|
||||||
|
|
||||||
final restoreWalletFromSeedNative = moneroApi
|
|
||||||
.lookup<NativeFunction<restore_wallet_from_seed>>(
|
|
||||||
'restore_wallet_from_seed')
|
|
||||||
.asFunction<RestoreWalletFromSeed>();
|
|
||||||
|
|
||||||
final restoreWalletFromKeysNative = moneroApi
|
|
||||||
.lookup<NativeFunction<restore_wallet_from_keys>>(
|
|
||||||
'restore_wallet_from_keys')
|
|
||||||
.asFunction<RestoreWalletFromKeys>();
|
|
||||||
|
|
||||||
final isWalletExistNative = moneroApi
|
|
||||||
.lookup<NativeFunction<is_wallet_exist>>('is_wallet_exist')
|
|
||||||
.asFunction<IsWalletExist>();
|
|
||||||
|
|
||||||
final loadWalletNative = moneroApi
|
|
||||||
.lookup<NativeFunction<load_wallet>>('load_wallet')
|
|
||||||
.asFunction<LoadWallet>();
|
|
||||||
|
|
||||||
final errorStringNative = moneroApi
|
|
||||||
.lookup<NativeFunction<error_string>>('error_string')
|
|
||||||
.asFunction<ErrorString>();
|
|
||||||
|
|
||||||
void createWalletSync(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String language,
|
|
||||||
int nettype = 0}) {
|
|
||||||
final pathPointer = path.toNativeUtf8();
|
|
||||||
final passwordPointer = password.toNativeUtf8();
|
|
||||||
final languagePointer = language.toNativeUtf8();
|
|
||||||
final errorMessagePointer = ''.toNativeUtf8();
|
|
||||||
final isWalletCreated = createWalletNative(pathPointer, passwordPointer,
|
|
||||||
languagePointer, nettype, errorMessagePointer) !=
|
|
||||||
0;
|
|
||||||
|
|
||||||
calloc.free(pathPointer);
|
|
||||||
calloc.free(passwordPointer);
|
|
||||||
calloc.free(languagePointer);
|
|
||||||
|
|
||||||
if (!isWalletCreated) {
|
|
||||||
throw WalletCreationException(
|
|
||||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
|
||||||
}
|
|
||||||
|
|
||||||
// setupNodeSync(address: "node.moneroworld.com:18089");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isWalletExistSync({required String path}) {
|
|
||||||
final pathPointer = path.toNativeUtf8();
|
|
||||||
final isExist = isWalletExistNative(pathPointer) != 0;
|
|
||||||
|
|
||||||
calloc.free(pathPointer);
|
|
||||||
|
|
||||||
return isExist;
|
|
||||||
}
|
|
||||||
|
|
||||||
void restoreWalletFromSeedSync(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String seed,
|
|
||||||
int nettype = 0,
|
|
||||||
int restoreHeight = 0}) {
|
|
||||||
final pathPointer = path.toNativeUtf8();
|
|
||||||
final passwordPointer = password.toNativeUtf8();
|
|
||||||
final seedPointer = seed.toNativeUtf8();
|
|
||||||
final errorMessagePointer = ''.toNativeUtf8();
|
|
||||||
final isWalletRestored = restoreWalletFromSeedNative(
|
|
||||||
pathPointer,
|
|
||||||
passwordPointer,
|
|
||||||
seedPointer,
|
|
||||||
nettype,
|
|
||||||
restoreHeight,
|
|
||||||
errorMessagePointer) !=
|
|
||||||
0;
|
|
||||||
|
|
||||||
calloc.free(pathPointer);
|
|
||||||
calloc.free(passwordPointer);
|
|
||||||
calloc.free(seedPointer);
|
|
||||||
|
|
||||||
if (!isWalletRestored) {
|
|
||||||
throw WalletRestoreFromSeedException(
|
|
||||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void restoreWalletFromKeysSync(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String language,
|
|
||||||
required String address,
|
|
||||||
required String viewKey,
|
|
||||||
required String spendKey,
|
|
||||||
int nettype = 0,
|
|
||||||
int restoreHeight = 0}) {
|
|
||||||
final pathPointer = path.toNativeUtf8();
|
|
||||||
final passwordPointer = password.toNativeUtf8();
|
|
||||||
final languagePointer = language.toNativeUtf8();
|
|
||||||
final addressPointer = address.toNativeUtf8();
|
|
||||||
final viewKeyPointer = viewKey.toNativeUtf8();
|
|
||||||
final spendKeyPointer = spendKey.toNativeUtf8();
|
|
||||||
final errorMessagePointer = ''.toNativeUtf8();
|
|
||||||
final isWalletRestored = restoreWalletFromKeysNative(
|
|
||||||
pathPointer,
|
|
||||||
passwordPointer,
|
|
||||||
languagePointer,
|
|
||||||
addressPointer,
|
|
||||||
viewKeyPointer,
|
|
||||||
spendKeyPointer,
|
|
||||||
nettype,
|
|
||||||
restoreHeight,
|
|
||||||
errorMessagePointer) !=
|
|
||||||
0;
|
|
||||||
|
|
||||||
calloc.free(pathPointer);
|
|
||||||
calloc.free(passwordPointer);
|
|
||||||
calloc.free(languagePointer);
|
|
||||||
calloc.free(addressPointer);
|
|
||||||
calloc.free(viewKeyPointer);
|
|
||||||
calloc.free(spendKeyPointer);
|
|
||||||
|
|
||||||
if (!isWalletRestored) {
|
|
||||||
throw WalletRestoreFromKeysException(
|
|
||||||
message: convertUTF8ToString(pointer: errorMessagePointer));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void loadWallet({
|
|
||||||
required String path,
|
|
||||||
required String password,
|
|
||||||
int nettype = 0}) {
|
|
||||||
final pathPointer = path.toNativeUtf8();
|
|
||||||
final passwordPointer = password.toNativeUtf8();
|
|
||||||
final loaded = loadWalletNative(pathPointer, passwordPointer, nettype) != 0;
|
|
||||||
calloc.free(pathPointer);
|
|
||||||
calloc.free(passwordPointer);
|
|
||||||
|
|
||||||
if (!loaded) {
|
|
||||||
throw WalletOpeningException(
|
|
||||||
message: convertUTF8ToString(pointer: errorStringNative()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _createWallet(Map<String, dynamic> args) {
|
|
||||||
final path = args['path'] as String;
|
|
||||||
final password = args['password'] as String;
|
|
||||||
final language = args['language'] as String;
|
|
||||||
|
|
||||||
createWalletSync(path: path, password: password, language: language);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _restoreFromSeed(Map<String, dynamic> args) {
|
|
||||||
final path = args['path'] as String;
|
|
||||||
final password = args['password'] as String;
|
|
||||||
final seed = args['seed'] as String;
|
|
||||||
final restoreHeight = args['restoreHeight'] as int;
|
|
||||||
|
|
||||||
restoreWalletFromSeedSync(
|
|
||||||
path: path, password: password, seed: seed, restoreHeight: restoreHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _restoreFromKeys(Map<String, dynamic> args) {
|
|
||||||
final path = args['path'] as String;
|
|
||||||
final password = args['password'] as String;
|
|
||||||
final language = args['language'] as String;
|
|
||||||
final restoreHeight = args['restoreHeight'] as int;
|
|
||||||
final address = args['address'] as String;
|
|
||||||
final viewKey = args['viewKey'] as String;
|
|
||||||
final spendKey = args['spendKey'] as String;
|
|
||||||
|
|
||||||
restoreWalletFromKeysSync(
|
|
||||||
path: path,
|
|
||||||
password: password,
|
|
||||||
language: language,
|
|
||||||
restoreHeight: restoreHeight,
|
|
||||||
address: address,
|
|
||||||
viewKey: viewKey,
|
|
||||||
spendKey: spendKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _openWallet(Map<String, String> args) async =>
|
|
||||||
loadWallet(path: args['path'] as String, password: args['password'] as String);
|
|
||||||
|
|
||||||
bool _isWalletExist(String path) => isWalletExistSync(path: path);
|
|
||||||
|
|
||||||
void openWallet({required String path, required String password, int nettype = 0}) async =>
|
|
||||||
loadWallet(path: path, password: password, nettype: nettype);
|
|
||||||
|
|
||||||
Future<void> openWalletAsync(Map<String, String> args) async =>
|
|
||||||
compute(_openWallet, args);
|
|
||||||
|
|
||||||
Future<void> createWallet(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String language,
|
|
||||||
int nettype = 0}) async =>
|
|
||||||
compute(_createWallet, {
|
|
||||||
'path': path,
|
|
||||||
'password': password,
|
|
||||||
'language': language,
|
|
||||||
'nettype': nettype
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> restoreFromSeed(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String seed,
|
|
||||||
int nettype = 0,
|
|
||||||
int restoreHeight = 0}) async =>
|
|
||||||
compute<Map<String, Object>, void>(_restoreFromSeed, {
|
|
||||||
'path': path,
|
|
||||||
'password': password,
|
|
||||||
'seed': seed,
|
|
||||||
'nettype': nettype,
|
|
||||||
'restoreHeight': restoreHeight
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<void> restoreFromKeys(
|
|
||||||
{required String path,
|
|
||||||
required String password,
|
|
||||||
required String language,
|
|
||||||
required String address,
|
|
||||||
required String viewKey,
|
|
||||||
required String spendKey,
|
|
||||||
int nettype = 0,
|
|
||||||
int restoreHeight = 0}) async =>
|
|
||||||
compute<Map<String, Object>, void>(_restoreFromKeys, {
|
|
||||||
'path': path,
|
|
||||||
'password': password,
|
|
||||||
'language': language,
|
|
||||||
'address': address,
|
|
||||||
'viewKey': viewKey,
|
|
||||||
'spendKey': spendKey,
|
|
||||||
'nettype': nettype,
|
|
||||||
'restoreHeight': restoreHeight
|
|
||||||
});
|
|
||||||
|
|
||||||
Future<bool> isWalletExist({required String path}) => compute(_isWalletExist, path);
|
|
|
@ -89,6 +89,11 @@ abstract class NanoWalletBase
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
final String type = (_derivationType == DerivationType.nano) ? "standard" : "hd";
|
final String type = (_derivationType == DerivationType.nano) ? "standard" : "hd";
|
||||||
|
|
||||||
|
// our "mnemonic" is actually a seedkey:
|
||||||
|
if (!_mnemonic.contains(' ')) {
|
||||||
|
_seedKey = _mnemonic;
|
||||||
|
}
|
||||||
|
|
||||||
if (_seedKey == null) {
|
if (_seedKey == null) {
|
||||||
if (_derivationType == DerivationType.nano) {
|
if (_derivationType == DerivationType.nano) {
|
||||||
_seedKey = bip39.mnemonicToEntropy(_mnemonic).toUpperCase();
|
_seedKey = bip39.mnemonicToEntropy(_mnemonic).toUpperCase();
|
||||||
|
|
|
@ -255,12 +255,18 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<NanoWallet> restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials) async {
|
Future<NanoWallet> restoreFromSeed(NanoRestoreWalletFromSeedCredentials credentials) async {
|
||||||
if (!bip39.validateMnemonic(credentials.mnemonic)) {
|
if (credentials.mnemonic.contains(' ')) {
|
||||||
throw nm.NanoMnemonicIsIncorrectException();
|
if (!bip39.validateMnemonic(credentials.mnemonic)) {
|
||||||
}
|
throw nm.NanoMnemonicIsIncorrectException();
|
||||||
|
}
|
||||||
|
|
||||||
if (!NanoMnemomics.validateMnemonic(credentials.mnemonic.split(' '))) {
|
if (!NanoMnemomics.validateMnemonic(credentials.mnemonic.split(' '))) {
|
||||||
throw nm.NanoMnemonicIsIncorrectException();
|
throw nm.NanoMnemonicIsIncorrectException();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (credentials.mnemonic.length != 64 && credentials.mnemonic.length != 128) {
|
||||||
|
throw Exception("Invalid seed length");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DerivationType derivationType = credentials.derivationType ?? DerivationType.nano;
|
DerivationType derivationType = credentials.derivationType ?? DerivationType.nano;
|
||||||
|
|
|
@ -850,11 +850,11 @@ Future setup({
|
||||||
getIt.registerFactoryParam<WalletRestorePage, WalletType, void>(
|
getIt.registerFactoryParam<WalletRestorePage, WalletType, void>(
|
||||||
(type, _) => WalletRestorePage(getIt.get<WalletRestoreViewModel>(param1: type)));
|
(type, _) => WalletRestorePage(getIt.get<WalletRestoreViewModel>(param1: type)));
|
||||||
|
|
||||||
getIt.registerFactoryParam<WalletRestoreChooseDerivationViewModel, WalletType, dynamic>(
|
getIt.registerFactoryParam<WalletRestoreChooseDerivationViewModel, dynamic, void>(
|
||||||
(credentials, _) =>
|
(credentials, _) =>
|
||||||
WalletRestoreChooseDerivationViewModel(credentials: credentials));
|
WalletRestoreChooseDerivationViewModel(credentials: credentials));
|
||||||
|
|
||||||
getIt.registerFactoryParam<WalletRestoreChooseDerivationPage, WalletType, dynamic>(
|
getIt.registerFactoryParam<WalletRestoreChooseDerivationPage, dynamic, void>(
|
||||||
(credentials, _) =>
|
(credentials, _) =>
|
||||||
WalletRestoreChooseDerivationPage(getIt.get<WalletRestoreChooseDerivationViewModel>(
|
WalletRestoreChooseDerivationPage(getIt.get<WalletRestoreChooseDerivationViewModel>(
|
||||||
param1: credentials,
|
param1: credentials,
|
||||||
|
|
|
@ -14,7 +14,7 @@ class WalletRestoreChooseDerivationPage extends BasePage {
|
||||||
@override
|
@override
|
||||||
Widget middle(BuildContext context) => Observer(
|
Widget middle(BuildContext context) => Observer(
|
||||||
builder: (_) => Text(
|
builder: (_) => Text(
|
||||||
"change me",
|
S.current.choose_derivation,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18.0,
|
fontSize: 18.0,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
@ -32,61 +32,63 @@ class WalletRestoreChooseDerivationPage extends BasePage {
|
||||||
future: walletRestoreChooseDerivationViewModel.derivations,
|
future: walletRestoreChooseDerivationViewModel.derivations,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return CircularProgressIndicator(); // Show loading spinner while waiting
|
return Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
} else if (snapshot.hasError) {
|
} else if (snapshot.hasError) {
|
||||||
return Text('Error: ${snapshot.error}'); // Show error if any
|
return Text('Error: ${snapshot.error}');
|
||||||
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
||||||
return Text('No derivations available'); // Show message if no derivations are available
|
return Text('No derivations available');
|
||||||
} else {
|
} else {
|
||||||
return ListView.separated(
|
return ListView.separated(
|
||||||
physics: NeverScrollableScrollPhysics(),
|
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
separatorBuilder: (_, __) => Container(padding: EdgeInsets.only(bottom: 8)),
|
separatorBuilder: (_, __) => SizedBox(),
|
||||||
itemCount: snapshot.data!.length,
|
itemCount: snapshot.data!.length,
|
||||||
itemBuilder: (__, index) {
|
itemBuilder: (__, index) {
|
||||||
final derivation = snapshot.data![index];
|
final derivation = snapshot.data![index];
|
||||||
return InkWell(
|
return Card(
|
||||||
onTap: () async {
|
margin: const EdgeInsets.all(8),
|
||||||
Navigator.pop(context, derivation.derivationType);
|
elevation: 3,
|
||||||
},
|
shape: RoundedRectangleBorder(
|
||||||
child: Container(
|
borderRadius: BorderRadius.circular(15),
|
||||||
margin: const EdgeInsets.only(left: 16, right: 16),
|
),
|
||||||
decoration: BoxDecoration(
|
child: InkWell(
|
||||||
borderRadius: BorderRadius.circular(30.0),
|
borderRadius: BorderRadius.circular(15),
|
||||||
border: Border.all(
|
onTap: () async {
|
||||||
color: getIt.get<SettingsStore>().currentTheme.type == ThemeType.bright
|
Navigator.pop(context, derivation.derivationType);
|
||||||
? Color.fromRGBO(255, 255, 255, 0.2)
|
},
|
||||||
: Colors.transparent,
|
child: ListTile(
|
||||||
width: 1,
|
contentPadding: EdgeInsets.all(16),
|
||||||
|
title: Center(
|
||||||
|
child: Text(
|
||||||
|
"${derivation.derivationType.toString().split('.').last}",
|
||||||
|
style:
|
||||||
|
Theme.of(context).primaryTextTheme.labelMedium!.copyWith(fontSize: 18),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
color: Theme.of(context).textTheme.titleLarge!.backgroundColor!,
|
subtitle: Column(
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
margin: const EdgeInsets.only(top: 16, left: 24, right: 24, bottom: 24),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
derivation.address,
|
derivation.address,
|
||||||
style: TextStyle(
|
style: Theme.of(context)
|
||||||
fontSize: 16,
|
.primaryTextTheme
|
||||||
fontFamily: 'Lato',
|
.labelMedium!
|
||||||
fontWeight: FontWeight.w400,
|
.copyWith(fontSize: 16),
|
||||||
color:
|
|
||||||
Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
|
|
||||||
height: 1,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"${S.current.confirmed}: ${derivation.balance}",
|
"${S.current.confirmed}: ${derivation.balance}",
|
||||||
style: TextStyle(
|
style: Theme.of(context)
|
||||||
fontSize: 18,
|
.primaryTextTheme
|
||||||
fontFamily: 'Lato',
|
.labelMedium!
|
||||||
fontWeight: FontWeight.w400,
|
.copyWith(fontSize: 16),
|
||||||
color:
|
),
|
||||||
Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
|
Text(
|
||||||
height: 2,
|
"${S.current.transactions}: ${derivation.height}",
|
||||||
),
|
style: Theme.of(context)
|
||||||
|
.primaryTextTheme
|
||||||
|
.labelMedium!
|
||||||
|
.copyWith(fontSize: 16),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
149
lib/src/screens/restore/wallet_restore_from_seed_key_form.dart
Normal file
149
lib/src/screens/restore/wallet_restore_from_seed_key_form.dart
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
import 'package:cake_wallet/entities/generate_name.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:cake_wallet/view_model/wallet_restore_view_model.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/seed_language/widgets/seed_language_picker.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/seed_widget.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/core/wallet_name_validator.dart';
|
||||||
|
|
||||||
|
class WalletRestoreFromSeedKeyForm extends StatefulWidget {
|
||||||
|
WalletRestoreFromSeedKeyForm(
|
||||||
|
{Key? key,
|
||||||
|
required this.displayLanguageSelector,
|
||||||
|
required this.displayBlockHeightSelector,
|
||||||
|
required this.type,
|
||||||
|
this.blockHeightFocusNode,
|
||||||
|
this.onHeightOrDateEntered,
|
||||||
|
this.onSeedChange,
|
||||||
|
this.onLanguageChange})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
final WalletType type;
|
||||||
|
final bool displayLanguageSelector;
|
||||||
|
final bool displayBlockHeightSelector;
|
||||||
|
final FocusNode? blockHeightFocusNode;
|
||||||
|
final Function(bool)? onHeightOrDateEntered;
|
||||||
|
final void Function(String)? onSeedChange;
|
||||||
|
final void Function(String)? onLanguageChange;
|
||||||
|
|
||||||
|
@override
|
||||||
|
WalletRestoreFromSeedKeyFormState createState() =>
|
||||||
|
WalletRestoreFromSeedKeyFormState('English');
|
||||||
|
}
|
||||||
|
|
||||||
|
class WalletRestoreFromSeedKeyFormState extends State<WalletRestoreFromSeedKeyForm> {
|
||||||
|
WalletRestoreFromSeedKeyFormState(this.language)
|
||||||
|
: seedWidgetStateKey = GlobalKey<SeedWidgetState>(),
|
||||||
|
blockchainHeightKey = GlobalKey<BlockchainHeightState>(),
|
||||||
|
formKey = GlobalKey<FormState>(),
|
||||||
|
languageController = TextEditingController(),
|
||||||
|
nameTextEditingController = TextEditingController();
|
||||||
|
|
||||||
|
final GlobalKey<SeedWidgetState> seedWidgetStateKey;
|
||||||
|
final GlobalKey<BlockchainHeightState> blockchainHeightKey;
|
||||||
|
final TextEditingController languageController;
|
||||||
|
final TextEditingController nameTextEditingController;
|
||||||
|
final GlobalKey<FormState> formKey;
|
||||||
|
String language;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_setLanguageLabel(language);
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.only(left: 24, right: 24),
|
||||||
|
child: Column(children: [
|
||||||
|
Form(
|
||||||
|
key: formKey,
|
||||||
|
child: Stack(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
children: [
|
||||||
|
BaseTextFormField(
|
||||||
|
controller: nameTextEditingController,
|
||||||
|
hintText: S.of(context).wallet_name,
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final rName = await generateName();
|
||||||
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
nameTextEditingController.text = rName;
|
||||||
|
nameTextEditingController.selection =
|
||||||
|
TextSelection.fromPosition(TextPosition(
|
||||||
|
offset: nameTextEditingController.text.length));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: Container(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(6.0),
|
||||||
|
color: Theme.of(context).hintColor,
|
||||||
|
),
|
||||||
|
width: 34,
|
||||||
|
height: 34,
|
||||||
|
child: Image.asset(
|
||||||
|
'assets/images/refresh_icon.png',
|
||||||
|
color: Theme.of(context)
|
||||||
|
.primaryTextTheme!
|
||||||
|
.headlineMedium!
|
||||||
|
.decorationColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
validator: WalletNameValidator(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
Container(height: 20),
|
||||||
|
SeedWidget(
|
||||||
|
key: seedWidgetStateKey,
|
||||||
|
language: language,
|
||||||
|
type: widget.type,
|
||||||
|
onSeedChange: widget.onSeedChange),
|
||||||
|
if (widget.displayLanguageSelector)
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
await showPopUp<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => SeedLanguagePicker(
|
||||||
|
selected: language, onItemSelected: _changeLanguage));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
padding: EdgeInsets.only(top: 20.0),
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: BaseTextFormField(
|
||||||
|
controller: languageController,
|
||||||
|
enableInteractiveSelection: false,
|
||||||
|
readOnly: true)))),
|
||||||
|
if (widget.displayBlockHeightSelector)
|
||||||
|
BlockchainHeightWidget(
|
||||||
|
focusNode: widget.blockHeightFocusNode,
|
||||||
|
key: blockchainHeightKey,
|
||||||
|
onHeightOrDateEntered: widget.onHeightOrDateEntered,
|
||||||
|
hasDatePicker: widget.type == WalletType.monero)
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _changeLanguage(String language) {
|
||||||
|
setState(() {
|
||||||
|
this.language = language;
|
||||||
|
seedWidgetStateKey.currentState!.changeSeedLanguage(language);
|
||||||
|
_setLanguageLabel(language);
|
||||||
|
widget.onLanguageChange?.call(language);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setLanguageLabel(String language) =>
|
||||||
|
languageController.text = '$language (Seed language)';
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/restore/wallet_restore_from_seed_key_form.dart';
|
||||||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||||
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
|
||||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||||
|
@ -29,6 +30,7 @@ class WalletRestorePage extends BasePage {
|
||||||
WalletRestorePage(this.walletRestoreViewModel)
|
WalletRestorePage(this.walletRestoreViewModel)
|
||||||
: walletRestoreFromSeedFormKey = GlobalKey<WalletRestoreFromSeedFormState>(),
|
: walletRestoreFromSeedFormKey = GlobalKey<WalletRestoreFromSeedFormState>(),
|
||||||
walletRestoreFromKeysFormKey = GlobalKey<WalletRestoreFromKeysFromState>(),
|
walletRestoreFromKeysFormKey = GlobalKey<WalletRestoreFromKeysFromState>(),
|
||||||
|
walletRestoreFromSeedKeyFormKey = GlobalKey<WalletRestoreFromSeedKeyFormState>(),
|
||||||
_pages = [],
|
_pages = [],
|
||||||
_blockHeightFocusNode = FocusNode(),
|
_blockHeightFocusNode = FocusNode(),
|
||||||
_controller = PageController(initialPage: 0) {
|
_controller = PageController(initialPage: 0) {
|
||||||
|
@ -71,6 +73,17 @@ class WalletRestorePage extends BasePage {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
break;
|
break;
|
||||||
|
case WalletRestoreMode.seedKey:
|
||||||
|
_pages.add(WalletRestoreFromSeedKeyForm(
|
||||||
|
displayBlockHeightSelector: walletRestoreViewModel.hasBlockchainHeightLanguageSelector,
|
||||||
|
displayLanguageSelector: walletRestoreViewModel.hasSeedLanguageSelector,
|
||||||
|
type: walletRestoreViewModel.type,
|
||||||
|
key: walletRestoreFromSeedKeyFormKey,
|
||||||
|
onSeedChange: (String seed) {
|
||||||
|
walletRestoreViewModel.isButtonEnabled = _isValidSeedKey();
|
||||||
|
},
|
||||||
|
));
|
||||||
|
break;
|
||||||
case WalletRestoreMode.keys:
|
case WalletRestoreMode.keys:
|
||||||
_pages.add(WalletRestoreFromKeysFrom(
|
_pages.add(WalletRestoreFromKeysFrom(
|
||||||
key: walletRestoreFromKeysFormKey,
|
key: walletRestoreFromKeysFormKey,
|
||||||
|
@ -101,6 +114,7 @@ class WalletRestorePage extends BasePage {
|
||||||
final List<Widget> _pages;
|
final List<Widget> _pages;
|
||||||
final GlobalKey<WalletRestoreFromSeedFormState> walletRestoreFromSeedFormKey;
|
final GlobalKey<WalletRestoreFromSeedFormState> walletRestoreFromSeedFormKey;
|
||||||
final GlobalKey<WalletRestoreFromKeysFromState> walletRestoreFromKeysFormKey;
|
final GlobalKey<WalletRestoreFromKeysFromState> walletRestoreFromKeysFormKey;
|
||||||
|
final GlobalKey<WalletRestoreFromSeedKeyFormState> walletRestoreFromSeedKeyFormKey;
|
||||||
final FocusNode _blockHeightFocusNode;
|
final FocusNode _blockHeightFocusNode;
|
||||||
DerivationType derivationType = DerivationType.unknown;
|
DerivationType derivationType = DerivationType.unknown;
|
||||||
|
|
||||||
|
@ -162,8 +176,14 @@ class WalletRestorePage extends BasePage {
|
||||||
Expanded(
|
Expanded(
|
||||||
child: PageView.builder(
|
child: PageView.builder(
|
||||||
onPageChanged: (page) {
|
onPageChanged: (page) {
|
||||||
walletRestoreViewModel.mode =
|
if (walletRestoreViewModel.type == WalletType.nano ||
|
||||||
page == 0 ? WalletRestoreMode.seed : WalletRestoreMode.keys;
|
walletRestoreViewModel.type == WalletType.banano) {
|
||||||
|
walletRestoreViewModel.mode =
|
||||||
|
page == 0 ? WalletRestoreMode.seed : WalletRestoreMode.seedKey;
|
||||||
|
} else {
|
||||||
|
walletRestoreViewModel.mode =
|
||||||
|
page == 0 ? WalletRestoreMode.seed : WalletRestoreMode.keys;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
itemCount: _pages.length,
|
itemCount: _pages.length,
|
||||||
|
@ -192,7 +212,7 @@ class WalletRestorePage extends BasePage {
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return LoadingPrimaryButton(
|
return LoadingPrimaryButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
_confirmForm(context);
|
await _confirmForm(context);
|
||||||
},
|
},
|
||||||
text: S.of(context).restore_recover,
|
text: S.of(context).restore_recover,
|
||||||
color: Theme.of(context).accentTextTheme!.titleSmall!.decorationColor!,
|
color: Theme.of(context).accentTextTheme!.titleSmall!.decorationColor!,
|
||||||
|
@ -228,12 +248,22 @@ class WalletRestorePage extends BasePage {
|
||||||
seedWords.length != WalletRestoreViewModelBase.electrumShortSeedMnemonicLength)) {
|
seedWords.length != WalletRestoreViewModelBase.electrumShortSeedMnemonicLength)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
final words =
|
final words =
|
||||||
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.words.toSet();
|
walletRestoreFromSeedFormKey.currentState!.seedWidgetStateKey.currentState!.words.toSet();
|
||||||
return seedWords.toSet().difference(words).toSet().isEmpty;
|
return seedWords.toSet().difference(words).toSet().isEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _isValidSeedKey() {
|
||||||
|
final seedKey =
|
||||||
|
walletRestoreFromSeedKeyFormKey.currentState!.seedWidgetStateKey.currentState!.text;
|
||||||
|
|
||||||
|
if (seedKey.length != 64 && seedKey.length != 128) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, dynamic> _credentials() {
|
Map<String, dynamic> _credentials() {
|
||||||
final credentials = <String, dynamic>{};
|
final credentials = <String, dynamic>{};
|
||||||
|
|
||||||
|
@ -248,7 +278,7 @@ class WalletRestorePage extends BasePage {
|
||||||
|
|
||||||
credentials['name'] =
|
credentials['name'] =
|
||||||
walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.text;
|
walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.text;
|
||||||
} else {
|
} else if (walletRestoreViewModel.mode == WalletRestoreMode.keys) {
|
||||||
credentials['address'] = walletRestoreFromKeysFormKey.currentState!.addressController.text;
|
credentials['address'] = walletRestoreFromKeysFormKey.currentState!.addressController.text;
|
||||||
credentials['viewKey'] = walletRestoreFromKeysFormKey.currentState!.viewKeyController.text;
|
credentials['viewKey'] = walletRestoreFromKeysFormKey.currentState!.viewKeyController.text;
|
||||||
credentials['spendKey'] = walletRestoreFromKeysFormKey.currentState!.spendKeyController.text;
|
credentials['spendKey'] = walletRestoreFromKeysFormKey.currentState!.spendKeyController.text;
|
||||||
|
@ -256,6 +286,9 @@ class WalletRestorePage extends BasePage {
|
||||||
walletRestoreFromKeysFormKey.currentState!.blockchainHeightKey.currentState!.height;
|
walletRestoreFromKeysFormKey.currentState!.blockchainHeightKey.currentState!.height;
|
||||||
credentials['name'] =
|
credentials['name'] =
|
||||||
walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.text;
|
walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.text;
|
||||||
|
} else if (walletRestoreViewModel.mode == WalletRestoreMode.seedKey) {
|
||||||
|
credentials['seedKey'] =
|
||||||
|
walletRestoreFromSeedKeyFormKey.currentState!.seedWidgetStateKey.currentState!.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
credentials['derivationType'] = this.derivationType;
|
credentials['derivationType'] = this.derivationType;
|
||||||
|
@ -263,22 +296,28 @@ class WalletRestorePage extends BasePage {
|
||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _confirmForm(BuildContext context) async {
|
Future<void> _confirmForm(BuildContext context) async {
|
||||||
// Dismissing all visible keyboard to provide context for navigation
|
// Dismissing all visible keyboard to provide context for navigation
|
||||||
FocusManager.instance.primaryFocus?.unfocus();
|
FocusManager.instance.primaryFocus?.unfocus();
|
||||||
final formContext = walletRestoreViewModel.mode == WalletRestoreMode.seed
|
|
||||||
? walletRestoreFromSeedFormKey.currentContext
|
late BuildContext? formContext;
|
||||||
: walletRestoreFromKeysFormKey.currentContext;
|
late GlobalKey<FormState>? formKey;
|
||||||
|
late String name;
|
||||||
|
if (walletRestoreViewModel.mode == WalletRestoreMode.seed) {
|
||||||
|
formContext = walletRestoreFromSeedFormKey.currentContext;
|
||||||
|
formKey = walletRestoreFromSeedFormKey.currentState!.formKey;
|
||||||
|
name = walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.value.text;
|
||||||
|
} else if (walletRestoreViewModel.mode == WalletRestoreMode.keys) {
|
||||||
|
formContext = walletRestoreFromKeysFormKey.currentContext;
|
||||||
|
formKey = walletRestoreFromKeysFormKey.currentState!.formKey;
|
||||||
|
name = walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.value.text;
|
||||||
|
} else if (walletRestoreViewModel.mode == WalletRestoreMode.seedKey) {
|
||||||
|
formContext = walletRestoreFromSeedKeyFormKey.currentContext;
|
||||||
|
formKey = walletRestoreFromSeedKeyFormKey.currentState!.formKey;
|
||||||
|
name = walletRestoreFromSeedKeyFormKey.currentState!.nameTextEditingController.value.text;
|
||||||
|
}
|
||||||
|
|
||||||
final formKey = walletRestoreViewModel.mode == WalletRestoreMode.seed
|
if (!formKey!.currentState!.validate()) {
|
||||||
? walletRestoreFromSeedFormKey.currentState!.formKey
|
|
||||||
: walletRestoreFromKeysFormKey.currentState!.formKey;
|
|
||||||
|
|
||||||
final name = walletRestoreViewModel.mode == WalletRestoreMode.seed
|
|
||||||
? walletRestoreFromSeedFormKey.currentState!.nameTextEditingController.value.text
|
|
||||||
: walletRestoreFromKeysFormKey.currentState!.nameTextEditingController.value.text;
|
|
||||||
|
|
||||||
if (!formKey.currentState!.validate()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,25 +326,26 @@ class WalletRestorePage extends BasePage {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
walletRestoreViewModel.state = IsExecutingState();
|
||||||
|
|
||||||
List<DerivationType> derivationTypes =
|
List<DerivationType> derivationTypes =
|
||||||
await walletRestoreViewModel.getDerivationType(_credentials());
|
await walletRestoreViewModel.getDerivationType(_credentials());
|
||||||
if (derivationTypes[0] == DerivationType.unknown || derivationTypes.length > 0) {
|
if (derivationTypes[0] == DerivationType.unknown || derivationTypes.length > 0) {
|
||||||
// push screen to choose the derivation type:
|
// push screen to choose the derivation type:
|
||||||
var derivationType =
|
var derivationType = await Navigator.of(context)
|
||||||
await Navigator.of(context).pushNamed(Routes.restoreWalletChooseDerivation, arguments: {
|
.pushNamed(Routes.restoreWalletChooseDerivation, arguments: _credentials())
|
||||||
"walletType": walletRestoreViewModel.type,
|
as DerivationType?;
|
||||||
"credentials": _credentials(),
|
|
||||||
}) as DerivationType?;
|
|
||||||
if (derivationType == null) {
|
if (derivationType == null) {
|
||||||
|
walletRestoreViewModel.state = InitialExecutionState();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.derivationType = derivationType;
|
this.derivationType = derivationType;
|
||||||
}
|
}
|
||||||
|
|
||||||
print(this.derivationType);
|
walletRestoreViewModel.state = InitialExecutionState();
|
||||||
|
|
||||||
// todo: re-enable
|
// todo: re-enable
|
||||||
// walletRestoreViewModel.create(options: _credentials());
|
walletRestoreViewModel.create(options: _credentials());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> showNameExistsAlert(BuildContext context) {
|
Future<void> showNameExistsAlert(BuildContext context) {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
enum WalletRestoreMode { seed, keys, txids }
|
enum WalletRestoreMode { seed, keys, txids, seedKey }
|
|
@ -26,7 +26,6 @@ abstract class WalletRestoreChooseDerivationViewModelBase with Store {
|
||||||
WalletRestoreChooseDerivationViewModelBase({required this.credentials})
|
WalletRestoreChooseDerivationViewModelBase({required this.credentials})
|
||||||
: mode = WalletRestoreMode.seed {}
|
: mode = WalletRestoreMode.seed {}
|
||||||
|
|
||||||
|
|
||||||
dynamic credentials;
|
dynamic credentials;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
|
@ -35,7 +34,7 @@ abstract class WalletRestoreChooseDerivationViewModelBase with Store {
|
||||||
Future<List<Derivation>> get derivations async {
|
Future<List<Derivation>> get derivations async {
|
||||||
var list = <Derivation>[];
|
var list = <Derivation>[];
|
||||||
|
|
||||||
switch (getIt.get<AppStore>().wallet!.type) {
|
switch ((await getIt.get<AppStore>().wallet!.type)) {
|
||||||
case WalletType.nano:
|
case WalletType.nano:
|
||||||
var seed = credentials['seed'] as String;
|
var seed = credentials['seed'] as String;
|
||||||
var bip39Info =
|
var bip39Info =
|
||||||
|
@ -43,14 +42,6 @@ abstract class WalletRestoreChooseDerivationViewModelBase with Store {
|
||||||
var standardInfo =
|
var standardInfo =
|
||||||
await NanoWalletService.getInfoFromSeedOrMnemonic(DerivationType.nano, mnemonic: seed);
|
await NanoWalletService.getInfoFromSeedOrMnemonic(DerivationType.nano, mnemonic: seed);
|
||||||
|
|
||||||
list.add(Derivation(
|
|
||||||
NanoUtil.getRawAsUsableString(bip39Info["balance"] as String, NanoUtil.rawPerNano),
|
|
||||||
bip39Info["address"] as String,
|
|
||||||
DerivationType.bip39,
|
|
||||||
int.parse(
|
|
||||||
bip39Info["confirmation_height"] as String,
|
|
||||||
),
|
|
||||||
));
|
|
||||||
list.add(Derivation(
|
list.add(Derivation(
|
||||||
NanoUtil.getRawAsUsableString(standardInfo["balance"] as String, NanoUtil.rawPerNano),
|
NanoUtil.getRawAsUsableString(standardInfo["balance"] as String, NanoUtil.rawPerNano),
|
||||||
standardInfo["address"] as String,
|
standardInfo["address"] as String,
|
||||||
|
@ -59,6 +50,16 @@ abstract class WalletRestoreChooseDerivationViewModelBase with Store {
|
||||||
standardInfo["confirmation_height"] as String,
|
standardInfo["confirmation_height"] as String,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
list.add(Derivation(
|
||||||
|
NanoUtil.getRawAsUsableString(bip39Info["balance"] as String, NanoUtil.rawPerNano),
|
||||||
|
bip39Info["address"] as String,
|
||||||
|
DerivationType.bip39,
|
||||||
|
int.parse(
|
||||||
|
bip39Info["confirmation_height"] as String,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -26,8 +26,10 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||||
Box<WalletInfo> walletInfoSource,
|
Box<WalletInfo> walletInfoSource,
|
||||||
{required WalletType type})
|
{required WalletType type})
|
||||||
: availableModes = (type == WalletType.monero || type == WalletType.haven)
|
: availableModes = (type == WalletType.monero || type == WalletType.haven)
|
||||||
? WalletRestoreMode.values
|
? [WalletRestoreMode.seed, WalletRestoreMode.keys, WalletRestoreMode.txids]
|
||||||
: [WalletRestoreMode.seed],
|
: (type == WalletType.nano || type == WalletType.banano)
|
||||||
|
? [WalletRestoreMode.seed, WalletRestoreMode.seedKey]
|
||||||
|
: [WalletRestoreMode.seed],
|
||||||
hasSeedLanguageSelector = type == WalletType.monero || type == WalletType.haven,
|
hasSeedLanguageSelector = type == WalletType.monero || type == WalletType.haven,
|
||||||
hasBlockchainHeightLanguageSelector = type == WalletType.monero || type == WalletType.haven,
|
hasBlockchainHeightLanguageSelector = type == WalletType.monero || type == WalletType.haven,
|
||||||
isButtonEnabled = false,
|
isButtonEnabled = false,
|
||||||
|
@ -121,7 +123,8 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<DerivationType>> getDerivationType(dynamic options) async {
|
Future<List<DerivationType>> getDerivationType(dynamic options) async {
|
||||||
final seed = options['seed'] as String?;
|
final seedKey = options['seedKey'] as String?;
|
||||||
|
final mnemonic = options['seed'] as String?;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
// case WalletType.bitcoin:
|
// case WalletType.bitcoin:
|
||||||
|
@ -131,7 +134,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
||||||
// return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials(
|
// return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials(
|
||||||
// name: name, mnemonic: seed, password: password);
|
// name: name, mnemonic: seed, password: password);
|
||||||
case WalletType.nano:
|
case WalletType.nano:
|
||||||
return await NanoWalletService.compareDerivationMethods(mnemonic: seed, seedKey: null);
|
return await NanoWalletService.compareDerivationMethods(mnemonic: mnemonic, seedKey: seedKey);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -678,5 +678,6 @@
|
||||||
"support_title_guides": "أدلة محفظة كعكة",
|
"support_title_guides": "أدلة محفظة كعكة",
|
||||||
"support_description_guides": "توثيق ودعم القضايا المشتركة",
|
"support_description_guides": "توثيق ودعم القضايا المشتركة",
|
||||||
"support_title_other_links": "روابط دعم أخرى",
|
"support_title_other_links": "روابط دعم أخرى",
|
||||||
"support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى"
|
"support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى",
|
||||||
}
|
"choose_derivation": "اختر اشتقاق المحفظة"
|
||||||
|
}
|
|
@ -674,5 +674,6 @@
|
||||||
"support_title_guides": "Ръководства за портфейл за торта",
|
"support_title_guides": "Ръководства за портфейл за торта",
|
||||||
"support_description_guides": "Документация и подкрепа за общи проблеми",
|
"support_description_guides": "Документация и подкрепа за общи проблеми",
|
||||||
"support_title_other_links": "Други връзки за поддръжка",
|
"support_title_other_links": "Други връзки за поддръжка",
|
||||||
"support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи"
|
"support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи",
|
||||||
}
|
"choose_derivation": "Изберете производно на портфейла"
|
||||||
|
}
|
|
@ -674,5 +674,6 @@
|
||||||
"support_title_guides": "Průvodce peněženkami dortu",
|
"support_title_guides": "Průvodce peněženkami dortu",
|
||||||
"support_description_guides": "Dokumentace a podpora běžných otázek",
|
"support_description_guides": "Dokumentace a podpora běžných otázek",
|
||||||
"support_title_other_links": "Další odkazy na podporu",
|
"support_title_other_links": "Další odkazy na podporu",
|
||||||
"support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody"
|
"support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody",
|
||||||
}
|
"choose_derivation": "Vyberte derivaci peněženky"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "Cake Wallet Guides",
|
"support_title_guides": "Cake Wallet Guides",
|
||||||
"support_description_guides": "Dokumentation und Hilfe für bekannte Probleme",
|
"support_description_guides": "Dokumentation und Hilfe für bekannte Probleme",
|
||||||
"support_title_other_links": "Andere Support-Links",
|
"support_title_other_links": "Andere Support-Links",
|
||||||
"support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden"
|
"support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden",
|
||||||
}
|
"choose_derivation": "Wählen Sie Brieftaschenableitung"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "Cake Wallet guides",
|
"support_title_guides": "Cake Wallet guides",
|
||||||
"support_description_guides": "Documentation and support for common issues",
|
"support_description_guides": "Documentation and support for common issues",
|
||||||
"support_title_other_links": "Other support links",
|
"support_title_other_links": "Other support links",
|
||||||
"support_description_other_links": "Join our communities or reach us our our partners through other methods"
|
"support_description_other_links": "Join our communities or reach us our our partners through other methods",
|
||||||
}
|
"choose_derivation": "Choose Wallet Derivation"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "Guías de billetera para pastel",
|
"support_title_guides": "Guías de billetera para pastel",
|
||||||
"support_description_guides": "Documentación y apoyo para problemas comunes",
|
"support_description_guides": "Documentación y apoyo para problemas comunes",
|
||||||
"support_title_other_links": "Otros enlaces de soporte",
|
"support_title_other_links": "Otros enlaces de soporte",
|
||||||
"support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos"
|
"support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos",
|
||||||
}
|
"choose_derivation": "Elija la derivación de la billetera"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "Guides de portefeuille à gâteau",
|
"support_title_guides": "Guides de portefeuille à gâteau",
|
||||||
"support_description_guides": "Documentation et soutien aux problèmes communs",
|
"support_description_guides": "Documentation et soutien aux problèmes communs",
|
||||||
"support_title_other_links": "Autres liens d'assistance",
|
"support_title_other_links": "Autres liens d'assistance",
|
||||||
"support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes"
|
"support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes",
|
||||||
}
|
"choose_derivation": "Choisissez la dérivation du portefeuille"
|
||||||
|
}
|
|
@ -660,5 +660,6 @@
|
||||||
"support_title_guides": "Jagorar Cake",
|
"support_title_guides": "Jagorar Cake",
|
||||||
"support_description_guides": "Tallafi da tallafi don batutuwa na yau da kullun",
|
"support_description_guides": "Tallafi da tallafi don batutuwa na yau da kullun",
|
||||||
"support_title_other_links": "Sauran hanyoyin tallafi",
|
"support_title_other_links": "Sauran hanyoyin tallafi",
|
||||||
"support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi"
|
"support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi",
|
||||||
}
|
"choose_derivation": "Zaɓi walatawa"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "केक वॉलेट गाइड",
|
"support_title_guides": "केक वॉलेट गाइड",
|
||||||
"support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन",
|
"support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन",
|
||||||
"support_title_other_links": "अन्य समर्थन लिंक",
|
"support_title_other_links": "अन्य समर्थन लिंक",
|
||||||
"support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें"
|
"support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें",
|
||||||
}
|
"choose_derivation": "वॉलेट व्युत्पत्ति चुनें"
|
||||||
|
}
|
|
@ -680,5 +680,6 @@
|
||||||
"support_title_guides": "Vodiči za torte",
|
"support_title_guides": "Vodiči za torte",
|
||||||
"support_description_guides": "Dokumentacija i podrška za uobičajena pitanja",
|
"support_description_guides": "Dokumentacija i podrška za uobičajena pitanja",
|
||||||
"support_title_other_links": "Ostale veze za podršku",
|
"support_title_other_links": "Ostale veze za podršku",
|
||||||
"support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama"
|
"support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama",
|
||||||
}
|
"choose_derivation": "Odaberite izvedbu novčanika"
|
||||||
|
}
|
|
@ -670,5 +670,6 @@
|
||||||
"support_title_guides": "Panduan Dompet Kue",
|
"support_title_guides": "Panduan Dompet Kue",
|
||||||
"support_description_guides": "Dokumentasi dan dukungan untuk masalah umum",
|
"support_description_guides": "Dokumentasi dan dukungan untuk masalah umum",
|
||||||
"support_title_other_links": "Tautan dukungan lainnya",
|
"support_title_other_links": "Tautan dukungan lainnya",
|
||||||
"support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain"
|
"support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain",
|
||||||
}
|
"choose_derivation": "Pilih dompet dompet"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "Guide del portafoglio per torte",
|
"support_title_guides": "Guide del portafoglio per torte",
|
||||||
"support_description_guides": "Documentazione e supporto per problemi comuni",
|
"support_description_guides": "Documentazione e supporto per problemi comuni",
|
||||||
"support_title_other_links": "Altri collegamenti di supporto",
|
"support_title_other_links": "Altri collegamenti di supporto",
|
||||||
"support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi"
|
"support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi",
|
||||||
}
|
"choose_derivation": "Scegli la derivazione del portafoglio"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "ケーキウォレットガイド",
|
"support_title_guides": "ケーキウォレットガイド",
|
||||||
"support_description_guides": "一般的な問題のドキュメントとサポート",
|
"support_description_guides": "一般的な問題のドキュメントとサポート",
|
||||||
"support_title_other_links": "その他のサポートリンク",
|
"support_title_other_links": "その他のサポートリンク",
|
||||||
"support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください"
|
"support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください",
|
||||||
}
|
"choose_derivation": "ウォレット派生を選択します"
|
||||||
|
}
|
|
@ -680,5 +680,6 @@
|
||||||
"support_title_guides": "케이크 지갑 가이드",
|
"support_title_guides": "케이크 지갑 가이드",
|
||||||
"support_description_guides": "일반적인 문제에 대한 문서화 및 지원",
|
"support_description_guides": "일반적인 문제에 대한 문서화 및 지원",
|
||||||
"support_title_other_links": "다른 지원 링크",
|
"support_title_other_links": "다른 지원 링크",
|
||||||
"support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오."
|
"support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오.",
|
||||||
}
|
"choose_derivation": "지갑 파생을 선택하십시오"
|
||||||
|
}
|
|
@ -680,5 +680,6 @@
|
||||||
"support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ",
|
"support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ",
|
||||||
"support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု",
|
"support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု",
|
||||||
"support_title_other_links": "အခြားအထောက်အပံ့လင့်များ",
|
"support_title_other_links": "အခြားအထောက်အပံ့လင့်များ",
|
||||||
"support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ"
|
"support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ",
|
||||||
}
|
"choose_derivation": "ပိုက်ဆံအိတ်ကိုရွေးချယ်ပါ"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "Cake -portemonnee gidsen",
|
"support_title_guides": "Cake -portemonnee gidsen",
|
||||||
"support_description_guides": "Documentatie en ondersteuning voor gemeenschappelijke problemen",
|
"support_description_guides": "Documentatie en ondersteuning voor gemeenschappelijke problemen",
|
||||||
"support_title_other_links": "Andere ondersteuningslinks",
|
"support_title_other_links": "Andere ondersteuningslinks",
|
||||||
"support_description_other_links": "Word lid van onze gemeenschappen of bereik ons onze partners via andere methoden"
|
"support_description_other_links": "Word lid van onze gemeenschappen of bereik ons onze partners via andere methoden",
|
||||||
}
|
"choose_derivation": "Kies portemonnee -afleiding"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "Przewodniki portfela ciasta",
|
"support_title_guides": "Przewodniki portfela ciasta",
|
||||||
"support_description_guides": "Dokumentacja i wsparcie dla typowych problemów",
|
"support_description_guides": "Dokumentacja i wsparcie dla typowych problemów",
|
||||||
"support_title_other_links": "Inne linki wsparcia",
|
"support_title_other_links": "Inne linki wsparcia",
|
||||||
"support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod"
|
"support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod",
|
||||||
}
|
"choose_derivation": "Wybierz wyprowadzenie portfela"
|
||||||
|
}
|
|
@ -681,5 +681,6 @@
|
||||||
"support_title_guides": "Guias da carteira de bolo",
|
"support_title_guides": "Guias da carteira de bolo",
|
||||||
"support_description_guides": "Documentação e suporte para problemas comuns",
|
"support_description_guides": "Documentação e suporte para problemas comuns",
|
||||||
"support_title_other_links": "Outros links de suporte",
|
"support_title_other_links": "Outros links de suporte",
|
||||||
"support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos"
|
"support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos",
|
||||||
}
|
"choose_derivation": "Escolha a derivação da carteira"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "Корт -гиды",
|
"support_title_guides": "Корт -гиды",
|
||||||
"support_description_guides": "Документация и поддержка общих вопросов",
|
"support_description_guides": "Документация и поддержка общих вопросов",
|
||||||
"support_title_other_links": "Другие ссылки на поддержку",
|
"support_title_other_links": "Другие ссылки на поддержку",
|
||||||
"support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов"
|
"support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов",
|
||||||
}
|
"choose_derivation": "Выберите вывод кошелька"
|
||||||
|
}
|
|
@ -680,5 +680,6 @@
|
||||||
"support_title_guides": "คู่มือกระเป๋าเงินเค้ก",
|
"support_title_guides": "คู่มือกระเป๋าเงินเค้ก",
|
||||||
"support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป",
|
"support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป",
|
||||||
"support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ",
|
"support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ",
|
||||||
"support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ"
|
"support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ",
|
||||||
}
|
"choose_derivation": "เลือก Wallet Derivation"
|
||||||
|
}
|
|
@ -680,5 +680,6 @@
|
||||||
"support_title_guides": "Kek Cüzdan Kılavuzları",
|
"support_title_guides": "Kek Cüzdan Kılavuzları",
|
||||||
"support_description_guides": "Ortak sorunlara belge ve destek",
|
"support_description_guides": "Ortak sorunlara belge ve destek",
|
||||||
"support_title_other_links": "Diğer destek bağlantıları",
|
"support_title_other_links": "Diğer destek bağlantıları",
|
||||||
"support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın"
|
"support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın",
|
||||||
}
|
"choose_derivation": "Cüzdan türevini seçin"
|
||||||
|
}
|
|
@ -682,5 +682,6 @@
|
||||||
"support_title_guides": "Поклики для гаманців тортів",
|
"support_title_guides": "Поклики для гаманців тортів",
|
||||||
"support_description_guides": "Документація та підтримка загальних питань",
|
"support_description_guides": "Документація та підтримка загальних питань",
|
||||||
"support_title_other_links": "Інші посилання на підтримку",
|
"support_title_other_links": "Інші посилання на підтримку",
|
||||||
"support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами"
|
"support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами",
|
||||||
}
|
"choose_derivation": "Виберіть деривацію гаманця"
|
||||||
|
}
|
|
@ -674,5 +674,6 @@
|
||||||
"support_title_guides": "کیک پرس گائڈز",
|
"support_title_guides": "کیک پرس گائڈز",
|
||||||
"support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد",
|
"support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد",
|
||||||
"support_title_other_links": "دوسرے سپورٹ لنکس",
|
"support_title_other_links": "دوسرے سپورٹ لنکس",
|
||||||
"support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں"
|
"support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں",
|
||||||
}
|
"choose_derivation": "پرس سے ماخوذ منتخب کریں"
|
||||||
|
}
|
|
@ -676,5 +676,6 @@
|
||||||
"support_title_guides": "Akara oyinbo Awọn Itọsọna Awọki oyinbo",
|
"support_title_guides": "Akara oyinbo Awọn Itọsọna Awọki oyinbo",
|
||||||
"support_description_guides": "Iwe ati atilẹyin fun awọn ọran ti o wọpọ",
|
"support_description_guides": "Iwe ati atilẹyin fun awọn ọran ti o wọpọ",
|
||||||
"support_title_other_links": "Awọn ọna asopọ atilẹyin miiran",
|
"support_title_other_links": "Awọn ọna asopọ atilẹyin miiran",
|
||||||
"support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran"
|
"support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran",
|
||||||
}
|
"choose_derivation": "Yan awọn apamọwọ apamọwọ"
|
||||||
|
}
|
|
@ -681,5 +681,6 @@
|
||||||
"support_title_guides": "蛋糕钱包指南",
|
"support_title_guides": "蛋糕钱包指南",
|
||||||
"support_description_guides": "对常见问题的文档和支持",
|
"support_description_guides": "对常见问题的文档和支持",
|
||||||
"support_title_other_links": "其他支持链接",
|
"support_title_other_links": "其他支持链接",
|
||||||
"support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴"
|
"support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴",
|
||||||
}
|
"choose_derivation": "选择钱包推导"
|
||||||
|
}
|
Loading…
Reference in a new issue