mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-08 20:09:24 +00:00
509b92e97f
* - Update and Fix Conflicts with main * Add Balances for ERC20 tokens * Fix conflicts with main * Add erc20 abi json * Add send erc20 tokens initial function * add missing getHeightByDate in Haven [skip ci] * Allow contacts and wallets from the same tag * Add Shiba Inu icon * Add send ERC-20 tokens initial flow * Add missing import in generated file * Add initial approach for transaction sending for ERC-20 tokens * Refactor signing/sending transactions * Add initial flow for transactions subscription * Refactor signing/sending transactions * Add home settings icon * Fix conflicts with main * Initial flow for home settings * Add logic flow for adding erc20 tokens * Fix initial UI * Finalize UI for Tokens * Integrate UI with Ethereum flow * Add "Enable/Disable" feature for ERC20 tokens * Add initial Erc20 tokens * Add Sorting and Pin Native Token features * Fix price sorting * Sort tokens list as well when Sort criteria changes * - Improve sorting balances flow - Add initial add token from search bar flow * Fix Accounts Popup UI * Fix Pin native token * Fix Enabling/Disabling tokens Fix sorting by fiat once app is opened Improve token availability mechanism * Fix deleting token Fix renaming tokens * Fix issue with search * Add more tokens * - Fix scroll issue - Add ERC20 tokens placeholder image in picker * - Separate and organize default erc20 tokens - Fix scrolling - Add token placeholder images in picker - Sort disabled tokens alphabetically * Change BNB token initial availability [skip ci] * Fix Conflicts with main * Fix Conflicts with main * Add Verse ERC20 token to the initial tokens list * Add rename wallet to Ethereum * Integrate EtherScan API for fetching address transactions Generate Ethereum specific secrets in Ethereum package * Adjust transactions fiat price for ERC20 tokens * Free Up GitHub Actions Ubuntu Runner Disk Space * Free Up GitHub Actions Ubuntu Runner Disk space (trial 2) * Fix Transaction Fee display * Save transaction history * Enhance loading time for erc20 tokens transactions * Minor Fixes and Enhancements * Fix sending erc20 fix block explorer issue * Fix int overflow * Fix transaction amount conversions * Minor: `slow` -> `Slow` [skip-ci] * initial changes * more base config stuff * config changes * successfully builds! * save * successfully add nano wallet * save * seed generation * receive screen + node screen working * tx history working and fiat fixes * balance working * derivation updates * nano-unfinished * sends working * remove fees from send screen, send and receive transactions working * fixes + auto receive incoming txs * fix for scanning QR codes * save * update translations * fixes * more fixes * more strings * small fix * fix github actions workflow * potential fix * potential fix * ci/cd fix * change rep working * seed generation fixes * fixes * save * change rep screen functional * save * banano changes * fixes, start adding ui for PoW * pow node changes * update translations * fix * account changing barely working * save * disable account generation * small fix * save * UI work * save * fixes after merge main * fixes * remove monero stuff, work on derivation ui * lots of fixes + finish up seed derivation * last minute fixes * node related fixes * more fixes * small fix * more fixes * fixes * pretty big refactor for pow, still some bugs * finally works! * get transactions after send * fix * merge conflict fixes * save * fix pow node showing up twice * done * initial changes * small fix * more merge fixes * fixes * more fixes * fix * save * fix manage pow nodes setting appearing on other wallets * fix contact bug * fixes * fiat fixes * save * save * save * save * updates * cleanup * restore fix * fixes * remove deprecated alert * fix * small fix * remove outdated warning * electrum restore fixes * fixes * fixes * fix * derivation fixes * nano fixes pt.1 * nano fixes pt.2 * bip39 fixes * pownode refactor * nodes pages fixes * observer fix * ssl fix * remove old references * remove unused imports * code cleanup * small fix * small potential fix * save * derivation fixes * deterministic fix * fix pt.2 * derivation class fixes * review fixes from nano that also apply here * formatting * stuff that should've stayed deleted * post merge fixes * remove problematic imports and duplicate changes * Delete lib/nano/nano.dart * move wallet restore page proxy code to the view model * fix dashboard page indicators being the same color * debatably better refactoring of derivationInfo, migration needed * additional refactor improvements * blanket comment some stuff out to narrow down this issue * refactor fixes * fix nano exchange * fix , bug, i.e. replace , with . when making a nano transaction * fix nano sending, update restore page wording, and other minor fixes * write migration for existing bitcoin and nano wallets * merge fixes * minor fixes * use default derivation type when restoring from qr code * fixes for restoring * fixes * fixes * merge fix * Fix issues with Creating Electrum and Restoring Bip39 * updates & fixes * Add missing case for no transactions BIP39 wallet restore * Make the default BIP39 the 84 derivation path * Add Samourai Deposit * litecoin mnemonic error fix * Bip39 passphrase support (#1412) * save * passphrase working * fix for when loading wallets + translation update * minor fix * Fix Nano * minor fix [skip ci] --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com> * change error state seed conditions into throwables [skip ci] * litecoin fixes * Bip39 minor enhancements (#1416) * minor enhancements * rename bitcoin_derivations -> electrum_derivations * Remove duplicate derivations handle default case * minor fix * Enable passphrase for Litecoin * obscure text of passphrase --------- Co-authored-by: OmarHatem <omarh.ismail1@gmail.com> Co-authored-by: Justin Ehrenhofer <justin.ehrenhofer@gmail.com> Co-authored-by: fossephate <fosse@book.local>
396 lines
12 KiB
Dart
396 lines
12 KiB
Dart
part of 'nano.dart';
|
|
|
|
class CWNanoAccountList extends NanoAccountList {
|
|
CWNanoAccountList(this._wallet);
|
|
final Object _wallet;
|
|
|
|
@override
|
|
@computed
|
|
ObservableList<NanoAccount> get accounts {
|
|
final nanoWallet = _wallet as NanoWallet;
|
|
final accounts = nanoWallet.walletAddresses.accountList.accounts
|
|
.map((acc) => NanoAccount(id: acc.id, label: acc.label, balance: acc.balance))
|
|
.toList();
|
|
return ObservableList<NanoAccount>.of(accounts);
|
|
}
|
|
|
|
@override
|
|
void update(Object wallet) {
|
|
final nanoWallet = wallet as NanoWallet;
|
|
nanoWallet.walletAddresses.accountList.update(null);
|
|
}
|
|
|
|
@override
|
|
void refresh(Object wallet) {
|
|
final nanoWallet = wallet as NanoWallet;
|
|
nanoWallet.walletAddresses.accountList.refresh();
|
|
}
|
|
|
|
@override
|
|
Future<List<NanoAccount>> getAll(Object wallet) async {
|
|
final nanoWallet = wallet as NanoWallet;
|
|
return (await nanoWallet.walletAddresses.accountList.getAll())
|
|
.map((acc) => NanoAccount(id: acc.id, label: acc.label, balance: acc.balance))
|
|
.toList();
|
|
}
|
|
|
|
@override
|
|
Future<void> addAccount(Object wallet, {required String label}) async {
|
|
final nanoWallet = wallet as NanoWallet;
|
|
await nanoWallet.walletAddresses.accountList.addAccount(label: label);
|
|
}
|
|
|
|
@override
|
|
Future<void> setLabelAccount(Object wallet,
|
|
{required int accountIndex, required String label}) async {
|
|
final nanoWallet = wallet as NanoWallet;
|
|
await nanoWallet.walletAddresses.accountList
|
|
.setLabelAccount(accountIndex: accountIndex, label: label);
|
|
}
|
|
}
|
|
|
|
class CWNano extends Nano {
|
|
@override
|
|
NanoAccountList getAccountList(Object wallet) {
|
|
return CWNanoAccountList(wallet);
|
|
}
|
|
|
|
@override
|
|
Account getCurrentAccount(Object wallet) {
|
|
final nanoWallet = wallet as NanoWallet;
|
|
final acc = nanoWallet.walletAddresses.account;
|
|
return Account(id: acc!.id, label: acc.label, balance: acc.balance);
|
|
}
|
|
|
|
@override
|
|
void setCurrentAccount(Object wallet, int id, String label, String? balance) {
|
|
final nanoWallet = wallet as NanoWallet;
|
|
nanoWallet.walletAddresses.account = NanoAccount(id: id, label: label, balance: balance);
|
|
nanoWallet.regenerateAddress();
|
|
}
|
|
|
|
@override
|
|
List<String> getNanoWordList(String language) {
|
|
return NanoMnemomics.WORDLIST;
|
|
}
|
|
|
|
@override
|
|
WalletService createNanoWalletService(Box<WalletInfo> walletInfoSource) {
|
|
return NanoWalletService(walletInfoSource);
|
|
}
|
|
|
|
@override
|
|
Map<String, String> getKeys(Object wallet) {
|
|
final nanoWallet = wallet as NanoWallet;
|
|
final keys = nanoWallet.keys;
|
|
return <String, String>{
|
|
"seedKey": keys.seedKey,
|
|
};
|
|
}
|
|
|
|
@override
|
|
WalletCredentials createNanoNewWalletCredentials({
|
|
required String name,
|
|
String? password,
|
|
}) =>
|
|
NanoNewWalletCredentials(
|
|
name: name,
|
|
password: password,
|
|
derivationType: DerivationType.nano,
|
|
);
|
|
|
|
@override
|
|
WalletCredentials createNanoRestoreWalletFromSeedCredentials({
|
|
required String name,
|
|
required String password,
|
|
required String mnemonic,
|
|
required DerivationType derivationType,
|
|
}) {
|
|
if (mnemonic.split(" ").length == 12 && derivationType != DerivationType.bip39) {
|
|
throw Exception("Invalid mnemonic for derivation type!");
|
|
}
|
|
|
|
return NanoRestoreWalletFromSeedCredentials(
|
|
name: name,
|
|
password: password,
|
|
mnemonic: mnemonic,
|
|
derivationType: derivationType,
|
|
);
|
|
}
|
|
|
|
@override
|
|
WalletCredentials createNanoRestoreWalletFromKeysCredentials({
|
|
required String name,
|
|
required String password,
|
|
required String seedKey,
|
|
required DerivationType derivationType,
|
|
}) {
|
|
if (seedKey.length == 128 && derivationType != DerivationType.bip39) {
|
|
throw Exception("Invalid seed key length for derivation type!");
|
|
}
|
|
|
|
return NanoRestoreWalletFromKeysCredentials(
|
|
name: name,
|
|
password: password,
|
|
seedKey: seedKey,
|
|
derivationType: derivationType,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Object createNanoTransactionCredentials(List<Output> outputs) {
|
|
return NanoTransactionCredentials(
|
|
outputs
|
|
.map((out) => OutputInfo(
|
|
fiatAmount: out.fiatAmount,
|
|
cryptoAmount: out.cryptoAmount,
|
|
address: out.address,
|
|
note: out.note,
|
|
sendAll: out.sendAll,
|
|
extractedAddress: out.extractedAddress,
|
|
isParsedAddress: out.isParsedAddress,
|
|
formattedCryptoAmount: out.formattedCryptoAmount,
|
|
))
|
|
.toList(),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Future<void> changeRep(Object wallet, String address) async {
|
|
if ((wallet as NanoWallet).transactionHistory.transactions.isEmpty) {
|
|
throw Exception("Can't change representative without an existing transaction history");
|
|
}
|
|
return wallet.changeRep(address);
|
|
}
|
|
|
|
@override
|
|
Future<bool> updateTransactions(Object wallet) async {
|
|
return (wallet as NanoWallet).updateTransactions();
|
|
}
|
|
|
|
@override
|
|
BigInt getTransactionAmountRaw(TransactionInfo transactionInfo) {
|
|
return (transactionInfo as NanoTransactionInfo).amountRaw;
|
|
}
|
|
|
|
@override
|
|
String getRepresentative(Object wallet) {
|
|
return (wallet as NanoWallet).representative;
|
|
}
|
|
|
|
@override
|
|
Future<List<N2Node>> getN2Reps(Object wallet) async {
|
|
return (wallet as NanoWallet).getN2Reps();
|
|
}
|
|
|
|
@override
|
|
bool isRepOk(Object wallet) {
|
|
return (wallet as NanoWallet).isRepOk;
|
|
}
|
|
}
|
|
|
|
class CWNanoUtil extends NanoUtil {
|
|
@override
|
|
bool isValidBip39Seed(String seed) {
|
|
return NanoDerivations.isValidBip39Seed(seed);
|
|
}
|
|
|
|
// number util:
|
|
|
|
static const int maxDecimalDigits = 6; // Max digits after decimal
|
|
BigInt rawPerNano = BigInt.parse("1000000000000000000000000000000");
|
|
BigInt rawPerNyano = BigInt.parse("1000000000000000000000000");
|
|
BigInt rawPerBanano = BigInt.parse("100000000000000000000000000000");
|
|
BigInt rawPerXMR = BigInt.parse("1000000000000");
|
|
BigInt convertXMRtoNano = BigInt.parse("1000000000000000000");
|
|
|
|
@override
|
|
String getRawAsUsableString(String? raw, BigInt rawPerCur) {
|
|
return NanoAmounts.getRawAsUsableString(raw, rawPerCur);
|
|
}
|
|
|
|
@override
|
|
String getRawAccuracy(String? raw, BigInt rawPerCur) {
|
|
return NanoAmounts.getRawAccuracy(raw, rawPerCur);
|
|
}
|
|
|
|
@override
|
|
String getAmountAsRaw(String amount, BigInt rawPerCur) {
|
|
return NanoAmounts.getAmountAsRaw(amount, rawPerCur);
|
|
}
|
|
|
|
@override
|
|
Future<AccountInfoResponse?> getInfoFromSeedOrMnemonic(
|
|
DerivationType derivationType, {
|
|
String? seedKey,
|
|
String? mnemonic,
|
|
required Node node,
|
|
}) async {
|
|
NanoClient nanoClient = NanoClient();
|
|
nanoClient.connect(node);
|
|
late String publicAddress;
|
|
|
|
if (seedKey != null) {
|
|
if (seedKey.length == 64) {
|
|
try {
|
|
mnemonic = NanoDerivations.standardSeedToMnemonic(seedKey);
|
|
} catch (e) {
|
|
print("not a valid 'nano' seed key");
|
|
}
|
|
}
|
|
if (derivationType == DerivationType.bip39) {
|
|
publicAddress = await NanoDerivations.hdSeedToAddress(seedKey, index: 0);
|
|
} else if (derivationType == DerivationType.nano) {
|
|
publicAddress = await NanoDerivations.standardSeedToAddress(seedKey, index: 0);
|
|
}
|
|
}
|
|
|
|
if (derivationType == DerivationType.bip39) {
|
|
if (mnemonic != null) {
|
|
seedKey = await NanoDerivations.hdMnemonicListToSeed(mnemonic.split(' '));
|
|
publicAddress = await NanoDerivations.hdSeedToAddress(seedKey, index: 0);
|
|
}
|
|
}
|
|
|
|
if (derivationType == DerivationType.nano) {
|
|
if (mnemonic != null) {
|
|
seedKey = await NanoDerivations.standardMnemonicToSeed(mnemonic);
|
|
publicAddress = await NanoDerivations.standardSeedToAddress(seedKey, index: 0);
|
|
}
|
|
}
|
|
|
|
AccountInfoResponse? accountInfo = await nanoClient.getAccountInfo(publicAddress);
|
|
if (accountInfo == null) {
|
|
accountInfo = AccountInfoResponse(
|
|
frontier: "", balance: "0", representative: "", confirmationHeight: 0);
|
|
}
|
|
accountInfo.address = publicAddress;
|
|
return accountInfo;
|
|
}
|
|
|
|
@override
|
|
Future<List<DerivationType>> compareDerivationMethods({
|
|
String? mnemonic,
|
|
String? privateKey,
|
|
required Node node,
|
|
}) async {
|
|
String? seedKey = privateKey;
|
|
|
|
if (mnemonic?.split(' ').length == 12) {
|
|
return [DerivationType.bip39];
|
|
}
|
|
if (seedKey?.length == 128) {
|
|
return [DerivationType.bip39];
|
|
} else if (seedKey?.length == 64) {
|
|
try {
|
|
mnemonic = NanoDerivations.standardSeedToMnemonic(seedKey!);
|
|
} catch (e) {
|
|
print("not a valid 'nano' seed key");
|
|
}
|
|
}
|
|
|
|
late String publicAddressStandard;
|
|
late String publicAddressBip39;
|
|
|
|
try {
|
|
NanoClient nanoClient = NanoClient();
|
|
nanoClient.connect(node);
|
|
|
|
if (mnemonic != null) {
|
|
seedKey = await NanoDerivations.hdMnemonicListToSeed(mnemonic.split(' '));
|
|
publicAddressBip39 = await NanoDerivations.hdSeedToAddress(seedKey, index: 0);
|
|
|
|
seedKey = await NanoDerivations.standardMnemonicToSeed(mnemonic);
|
|
publicAddressStandard = await NanoDerivations.standardSeedToAddress(seedKey, index: 0);
|
|
} else if (seedKey != null) {
|
|
try {
|
|
publicAddressBip39 = await NanoDerivations.hdSeedToAddress(seedKey, index: 0);
|
|
} catch (e) {
|
|
return [DerivationType.nano];
|
|
}
|
|
try {
|
|
publicAddressStandard = await NanoDerivations.standardSeedToAddress(seedKey, index: 0);
|
|
} catch (e) {
|
|
return [DerivationType.bip39];
|
|
}
|
|
}
|
|
|
|
// check if account has a history:
|
|
AccountInfoResponse? bip39Info;
|
|
AccountInfoResponse? standardInfo;
|
|
|
|
try {
|
|
bip39Info = await nanoClient.getAccountInfo(publicAddressBip39);
|
|
} catch (e) {
|
|
bip39Info = null;
|
|
}
|
|
try {
|
|
standardInfo = await nanoClient.getAccountInfo(publicAddressStandard);
|
|
} catch (e) {
|
|
standardInfo = null;
|
|
}
|
|
|
|
// one of these is *probably* null:
|
|
if (bip39Info == null && standardInfo != null) {
|
|
return [DerivationType.nano];
|
|
} else if (standardInfo == null && bip39Info != null) {
|
|
return [DerivationType.bip39];
|
|
}
|
|
|
|
// we don't know for sure:
|
|
return [DerivationType.nano, DerivationType.bip39];
|
|
} catch (e) {
|
|
return [DerivationType.nano, DerivationType.bip39];
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<List<DerivationInfo>> getDerivationsFromMnemonic({
|
|
String? mnemonic,
|
|
String? seedKey,
|
|
required Node node,
|
|
}) async {
|
|
List<DerivationInfo> list = [];
|
|
|
|
List<DerivationType> possibleDerivationTypes = await compareDerivationMethods(
|
|
mnemonic: mnemonic,
|
|
privateKey: seedKey,
|
|
node: node,
|
|
);
|
|
if (possibleDerivationTypes.length == 1) {
|
|
return [DerivationInfo(derivationType: possibleDerivationTypes.first)];
|
|
}
|
|
|
|
AccountInfoResponse? bip39Info = await nanoUtil!.getInfoFromSeedOrMnemonic(
|
|
DerivationType.bip39,
|
|
mnemonic: mnemonic,
|
|
seedKey: seedKey,
|
|
node: node,
|
|
);
|
|
AccountInfoResponse? standardInfo = await nanoUtil!.getInfoFromSeedOrMnemonic(
|
|
DerivationType.nano,
|
|
mnemonic: mnemonic,
|
|
seedKey: seedKey,
|
|
node: node,
|
|
);
|
|
|
|
if (standardInfo?.confirmationHeight != null && standardInfo!.confirmationHeight > 0) {
|
|
list.add(DerivationInfo(
|
|
derivationType: DerivationType.nano,
|
|
balance: nanoUtil!.getRawAsUsableString(standardInfo.balance, nanoUtil!.rawPerNano),
|
|
address: standardInfo.address!,
|
|
transactionsCount: standardInfo.confirmationHeight,
|
|
));
|
|
}
|
|
|
|
if (bip39Info?.confirmationHeight != null && bip39Info!.confirmationHeight > 0) {
|
|
list.add(DerivationInfo(
|
|
derivationType: DerivationType.bip39,
|
|
balance: nanoUtil!.getRawAsUsableString(bip39Info.balance, nanoUtil!.rawPerNano),
|
|
address: bip39Info.address!,
|
|
transactionsCount: bip39Info.confirmationHeight,
|
|
));
|
|
}
|
|
return list;
|
|
}
|
|
}
|