mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-10 21:04:53 +00:00
derivation updates
This commit is contained in:
parent
490618ebd6
commit
33c99cb2a5
7 changed files with 168 additions and 68 deletions
|
@ -13,6 +13,9 @@ import 'package:web3dart/contracts/erc20.dart';
|
|||
import 'package:cw_core/node.dart';
|
||||
|
||||
class NanoClient {
|
||||
// bit of a hack since we need access to a node in a weird location:
|
||||
static const String BACKUP_NODE_URI = "rpc.nano.to";
|
||||
|
||||
final _httpClient = Client();
|
||||
StreamSubscription<Transfer>? subscription;
|
||||
Node? _node;
|
||||
|
@ -97,23 +100,4 @@ class NanoClient {
|
|||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Future<int> _getDecimalPlacesForContract(DeployedContract contract) async {
|
||||
// final String abi = await rootBundle.loadString("assets/abi_json/erc20_abi.json");
|
||||
// final contractAbi = ContractAbi.fromJson(abi, "ERC20");
|
||||
//
|
||||
// final contract = DeployedContract(
|
||||
// contractAbi,
|
||||
// EthereumAddress.fromHex(_erc20Currencies[erc20Currency]!),
|
||||
// );
|
||||
// final decimalsFunction = contract.function('decimals');
|
||||
// final decimals = await _client!.call(
|
||||
// contract: contract,
|
||||
// function: decimalsFunction,
|
||||
// params: [],
|
||||
// );
|
||||
//
|
||||
// int exponent = int.parse(decimals.first.toString());
|
||||
// return exponent;
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import 'package:cw_nano/nano_client.dart';
|
|||
import 'package:cw_nano/nano_transaction_history.dart';
|
||||
import 'package:cw_nano/nano_transaction_info.dart';
|
||||
import 'package:cw_nano/nano_util.dart';
|
||||
import 'package:cw_nano/nano_wallet_info.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'dart:async';
|
||||
import 'package:cw_nano/nano_wallet_addresses.dart';
|
||||
|
@ -27,20 +28,17 @@ part 'nano_wallet.g.dart';
|
|||
|
||||
class NanoWallet = NanoWalletBase with _$NanoWallet;
|
||||
|
||||
enum DerivationType { bip39, nano }
|
||||
|
||||
abstract class NanoWalletBase
|
||||
extends WalletBase<NanoBalance, NanoTransactionHistory, NanoTransactionInfo> with Store {
|
||||
NanoWalletBase({
|
||||
required WalletInfo walletInfo,
|
||||
required NanoWalletInfo walletInfo,
|
||||
required String mnemonic,
|
||||
required String password,
|
||||
required DerivationType derivationType,
|
||||
NanoBalance? initialBalance,
|
||||
}) : syncStatus = NotConnectedSyncStatus(),
|
||||
_password = password,
|
||||
_mnemonic = mnemonic,
|
||||
_derivationType = derivationType,
|
||||
_derivationType = walletInfo.derivationType,
|
||||
_isTransactionUpdating = false,
|
||||
_client = NanoClient(),
|
||||
walletAddresses = NanoWalletAddresses(walletInfo),
|
||||
|
@ -86,8 +84,6 @@ abstract class NanoWalletBase
|
|||
|
||||
await walletAddresses.init();
|
||||
await transactionHistory.init();
|
||||
|
||||
// walletAddresses.address = _privateKey.address.toString();
|
||||
await save();
|
||||
}
|
||||
|
||||
|
@ -127,7 +123,58 @@ abstract class NanoWalletBase
|
|||
@override
|
||||
Future<PendingTransaction> createTransaction(Object credentials) async {
|
||||
print("g");
|
||||
throw UnimplementedError();
|
||||
print(credentials);
|
||||
// throw UnimplementedError();
|
||||
|
||||
// final _credentials = credentials as EthereumTransactionCredentials;
|
||||
// final outputs = _credentials.outputs;
|
||||
// final hasMultiDestination = outputs.length > 1;
|
||||
// final _erc20Balance = balance[_credentials.currency]!;
|
||||
// BigInt totalAmount = BigInt.zero;
|
||||
// int exponent =
|
||||
// _credentials.currency is Erc20Token ? (_credentials.currency as Erc20Token).decimal : 18;
|
||||
// BigInt amountToEthereumMultiplier = BigInt.from(pow(10, exponent));
|
||||
|
||||
// if (hasMultiDestination) {
|
||||
// if (outputs.any((item) => item.sendAll || (item.formattedCryptoAmount ?? 0) <= 0)) {
|
||||
// throw EthereumTransactionCreationException(_credentials.currency);
|
||||
// }
|
||||
|
||||
// final totalOriginalAmount = EthereumFormatter.parseEthereumAmountToDouble(
|
||||
// outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)));
|
||||
// totalAmount = BigInt.from(totalOriginalAmount) * amountToEthereumMultiplier;
|
||||
|
||||
// if (_erc20Balance.balance < totalAmount) {
|
||||
// throw EthereumTransactionCreationException(_credentials.currency);
|
||||
// }
|
||||
// } else {
|
||||
// final output = outputs.first;
|
||||
// final BigInt allAmount = _erc20Balance.balance - BigInt.from(feeRate(_credentials.priority!));
|
||||
// final totalOriginalAmount =
|
||||
// EthereumFormatter.parseEthereumAmountToDouble(output.formattedCryptoAmount ?? 0);
|
||||
// totalAmount = output.sendAll
|
||||
// ? allAmount
|
||||
// : BigInt.from(totalOriginalAmount) * amountToEthereumMultiplier;
|
||||
|
||||
// if (_erc20Balance.balance < totalAmount) {
|
||||
// throw EthereumTransactionCreationException(_credentials.currency);
|
||||
// }
|
||||
// }
|
||||
|
||||
// final pendingEthereumTransaction = await _client.signTransaction(
|
||||
// privateKey: _privateKey,
|
||||
// toAddress: _credentials.outputs.first.address,
|
||||
// amount: totalAmount.toString(),
|
||||
// gas: _priorityFees[_credentials.priority!.raw],
|
||||
// priority: _credentials.priority!,
|
||||
// currency: _credentials.currency,
|
||||
// exponent: exponent,
|
||||
// contractAddress: _credentials.currency is Erc20Token
|
||||
// ? (_credentials.currency as Erc20Token).contractAddress
|
||||
// : null,
|
||||
// );
|
||||
|
||||
// return pendingEthereumTransaction;
|
||||
}
|
||||
|
||||
Future<void> updateTransactions() async {
|
||||
|
@ -178,9 +225,10 @@ abstract class NanoWalletBase
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> rescan({required int height}) {
|
||||
print("k");
|
||||
throw UnimplementedError("rescan");
|
||||
Future<void> rescan({required int height}) async {
|
||||
fetchTransactions();
|
||||
_updateBalance();
|
||||
return;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -235,17 +283,20 @@ abstract class NanoWalletBase
|
|||
derivationType = DerivationType.nano;
|
||||
}
|
||||
|
||||
return NanoWallet(
|
||||
final nanoWalletInfo = NanoWalletInfo(
|
||||
walletInfo: walletInfo,
|
||||
derivationType: derivationType,
|
||||
);
|
||||
|
||||
return NanoWallet(
|
||||
walletInfo: nanoWalletInfo,
|
||||
password: password,
|
||||
mnemonic: mnemonic,
|
||||
initialBalance: balance,
|
||||
derivationType: derivationType,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _updateBalance() async {
|
||||
// this.balance.update(CryptoCurrency.nano, (value) => (await _client.getBalance(_publicAddress)));
|
||||
balance[currency] = await _client.getBalance(_publicAddress);
|
||||
await save();
|
||||
}
|
||||
|
|
23
cw_nano/lib/nano_wallet_info.dart
Normal file
23
cw_nano/lib/nano_wallet_info.dart
Normal file
|
@ -0,0 +1,23 @@
|
|||
import 'package:cw_core/wallet_info.dart';
|
||||
|
||||
enum DerivationType { bip39, nano }
|
||||
|
||||
class NanoWalletInfo extends WalletInfo {
|
||||
DerivationType derivationType;
|
||||
|
||||
NanoWalletInfo({required WalletInfo walletInfo, required this.derivationType})
|
||||
: super(
|
||||
walletInfo.id,
|
||||
walletInfo.name,
|
||||
walletInfo.type,
|
||||
walletInfo.isRecovery,
|
||||
walletInfo.restoreHeight,
|
||||
walletInfo.timestamp,
|
||||
walletInfo.dirPath,
|
||||
walletInfo.path,
|
||||
walletInfo.address,
|
||||
walletInfo.yatEid,
|
||||
walletInfo.yatLastUsedAddressRaw,
|
||||
walletInfo.showIntroCakePayCard,
|
||||
);
|
||||
}
|
|
@ -1,15 +1,18 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/pathForWallet.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cw_nano/nano_balance.dart';
|
||||
import 'package:cw_nano/nano_client.dart';
|
||||
import 'package:cw_nano/nano_mnemonic.dart';
|
||||
// import 'package:cw_nano/nano_mnemonics.dart';
|
||||
import 'package:cw_nano/nano_util.dart';
|
||||
import 'package:cw_nano/nano_wallet.dart';
|
||||
import 'package:cw_nano/nano_wallet_creation_credentials.dart';
|
||||
import 'package:cw_nano/nano_wallet_info.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
|
||||
|
@ -62,11 +65,16 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
|||
Future<WalletBase> create(NanoNewWalletCredentials credentials) async {
|
||||
print("nano_wallet_service create");
|
||||
final mnemonic = bip39.generateMnemonic();
|
||||
final wallet = NanoWallet(
|
||||
|
||||
final nanoWalletInfo = NanoWalletInfo(
|
||||
walletInfo: credentials.walletInfo!,
|
||||
derivationType: DerivationType.nano,
|
||||
);
|
||||
|
||||
final wallet = NanoWallet(
|
||||
walletInfo: nanoWalletInfo,
|
||||
mnemonic: mnemonic,
|
||||
password: credentials.password!,
|
||||
derivationType: DerivationType.bip39,
|
||||
);
|
||||
return wallet;
|
||||
}
|
||||
|
@ -102,35 +110,69 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
|||
}
|
||||
|
||||
Future<DerivationType> compareDerivationMethods({String? mnemonic, String? seedKey}) async {
|
||||
// TODO:
|
||||
return DerivationType.nano;
|
||||
if (seedKey?.length == 128) {
|
||||
return DerivationType.bip39;
|
||||
}
|
||||
if (mnemonic?.split(' ').length == 12) {
|
||||
return DerivationType.bip39;
|
||||
}
|
||||
|
||||
try {
|
||||
NanoClient nanoClient = NanoClient();
|
||||
// TODO: figure out how to load the current node uri in this context:
|
||||
nanoClient.connect(Node(
|
||||
uri: NanoClient.BACKUP_NODE_URI,
|
||||
type: WalletType.nano,
|
||||
));
|
||||
|
||||
late String publicAddressStandard;
|
||||
late String publicAddressBip39;
|
||||
|
||||
if (seedKey == null) {
|
||||
seedKey = bip39.mnemonicToEntropy(mnemonic).toUpperCase();
|
||||
}
|
||||
|
||||
publicAddressBip39 = await NanoUtil.hdSeedToAddress(seedKey, 0);
|
||||
publicAddressStandard = await NanoUtil.seedToAddress(seedKey, 0);
|
||||
|
||||
// check if either has a balance:
|
||||
|
||||
NanoBalance bip39Balance = await nanoClient.getBalance(publicAddressBip39);
|
||||
NanoBalance standardBalance = await nanoClient.getBalance(publicAddressStandard);
|
||||
|
||||
// TODO: this is super basic implementation, and if both addresses have balances
|
||||
// it might not be the one that the user wants, though it is unlikely
|
||||
if (bip39Balance.currentBalance > standardBalance.currentBalance) {
|
||||
return DerivationType.bip39;
|
||||
} else {
|
||||
return DerivationType.nano;
|
||||
}
|
||||
} catch (e) {
|
||||
return DerivationType.nano;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<NanoWallet> restoreFromKeys(NanoRestoreWalletFromKeysCredentials credentials) async {
|
||||
throw UnimplementedError("restoreFromKeys");
|
||||
|
||||
DerivationType derivationType = DerivationType.bip39;
|
||||
// TODO: mnemonic can't be derived from the seedKey in the nanostandard derivation
|
||||
// which complicates things
|
||||
|
||||
if (credentials.seedKey.length == 128) {
|
||||
derivationType = DerivationType.bip39;
|
||||
} else {
|
||||
// we don't know for sure, but probably the nano standard:
|
||||
derivationType = await compareDerivationMethods(seedKey: credentials.seedKey);
|
||||
}
|
||||
|
||||
String? mnemonic;
|
||||
|
||||
final wallet = await NanoWallet(
|
||||
password: credentials.password!,
|
||||
mnemonic: mnemonic ?? "", // we can't derive the mnemonic from the key in all cases
|
||||
walletInfo: credentials.walletInfo!,
|
||||
derivationType: derivationType,
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
await wallet.save();
|
||||
return wallet;
|
||||
// DerivationType derivationType = await compareDerivationMethods(seedKey: credentials.seedKey);
|
||||
// String? mnemonic;
|
||||
// final nanoWalletInfo = NanoWalletInfo(
|
||||
// walletInfo: credentials.walletInfo!,
|
||||
// derivationType: derivationType,
|
||||
// );
|
||||
// final wallet = await NanoWallet(
|
||||
// password: credentials.password!,
|
||||
// mnemonic: mnemonic ?? "", // we can't derive the mnemonic from the key in all cases
|
||||
// walletInfo: nanoWalletInfo,
|
||||
// );
|
||||
// await wallet.init();
|
||||
// await wallet.save();
|
||||
// return wallet;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -143,20 +185,17 @@ class NanoWalletService extends WalletService<NanoNewWalletCredentials,
|
|||
throw NanoMnemonicIsIncorrectException();
|
||||
}
|
||||
|
||||
DerivationType derivationType = DerivationType.bip39;
|
||||
DerivationType derivationType = await compareDerivationMethods(mnemonic: credentials.mnemonic);
|
||||
|
||||
if (credentials.mnemonic.split(' ').length == 12) {
|
||||
derivationType = DerivationType.bip39;
|
||||
} else {
|
||||
// we don't know for sure, but probably the nano standard:
|
||||
derivationType = await compareDerivationMethods(mnemonic: credentials.mnemonic);
|
||||
}
|
||||
final nanoWalletInfo = NanoWalletInfo(
|
||||
walletInfo: credentials.walletInfo!,
|
||||
derivationType: derivationType,
|
||||
);
|
||||
|
||||
final wallet = await NanoWallet(
|
||||
password: credentials.password!,
|
||||
mnemonic: credentials.mnemonic,
|
||||
walletInfo: credentials.walletInfo!,
|
||||
derivationType: derivationType,
|
||||
walletInfo: nanoWalletInfo,
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:cw_nano/nano_wallet.dart';
|
||||
import 'package:cw_nano/nano_wallet_info.dart';
|
||||
import 'package:cw_nano/nano_wallet_service.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
|||
import 'package:cake_wallet/nano/nano.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cw_nano/nano_wallet.dart';
|
||||
import 'package:cw_nano/nano_wallet_info.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
|
|
|
@ -581,6 +581,7 @@ Future<void> generateNano(bool hasImplementation) async {
|
|||
const nanoCWHeaders = """
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_nano/nano_wallet_info.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
|
|
Loading…
Reference in a new issue