Zano with passphrase (#1971)

* CW-685 Add passphrase restore for xmr/wow (#1552)

* CW-685 Add passphrase restore for xmr/wow

* add support for polyseed passphrase

* disable 14 word seed passphrase (not supported in wownero-seed)
fix: Getting grayed screen on latest passphrase build after having restored a 14-word wownero seed (+passphrase) and attempting to restore a XMR seed, legacy or otherwise.

* fix pointer when restoring depracated wownero seed

* Fix polyseed encryption

* changes from review

* remove unused code

* add passphrase back to the screen
add passphrase to qr code backup export

* fix settings leaking through currencies on seed restore

* fix monero.com builds, make passphrase a getter on WalletBase

* add support for weird polyseed

* store passphrase for weird polyseed

* show encrypted seed only when passphrase is not empty

* force set restore height

* fix build issues

* fix build errors

* fix configure script

* print -> printV

* Update lib/view_model/wallet_keys_view_model.dart [skip ci]

* Update lib/view_model/wallet_keys_view_model.dart [skip ci]

* Update tool/configure.dart [skip ci]

* Update lib/view_model/wallet_new_vm.dart

* reuse existing passphrase field

* remove unused passphrase field

* make workflow run on pullrequests only [skip ci] [skip slack]

---------

Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* Zano (#1793)

* my experiments

* Inital code for Zano integration

* Added missing android log lib

* added dummy wallet & some zano implementation

* fixing api for zano

* fixed zano build script

* attempt tp fix namespace problem

* added copy script for Zano files

* changes for zano wallet

* last updates

* zano.dart test app

* wallet recovery

* added pending transfer, some cleanup of unused

* some cleanup

* send + receive qr code

* last upd

* updated build_zano.sh

* updated zano ApiCalls, removed dummy

* updated zano ApiCalls, removed dummy

* added logging for get status/get info

* restored old wallet.dart

* restoring original versions of files

* restoring original versions of files

* restored get_height_by_date.dart, removed unnecessary calls for zano get height

* restoring original versions

* added multiple destinations, send all flag; some refactoring

* logging

* removed the duplicate

* fixed syncing sync status, decimal division, safe null json parsing

* some fixes after merge

* added multibalance/asset support for zano (ui)

* adding/removing from whitelist

* transfers in different assets

* transfers for multiple destinations and send all, some refactoring

* whitelists, some refactoring

* added different digits (decimal points) for formatters, some refactoring

* open, create, restore wallet refactoring; whitelists

* whitelists

* getting and updating transaction list; restoring a wallet from QR code

* several attempts to close wallet

* some refactoring

* added seed phrase

* changed fields to BigInt, some fixes

* modified build scripts for android

* build scripts

* restored accidently removed cw_haven.dart

* inital ios integration(zano libs built)

* update in script

* latest changes

* Applied a patch for iOS build (Boost and Zano scripts)

* Removed zano.dart (script-generated) and some unnecessary files

* Revert "Removed zano.dart (script-generated) and some unnecessary files"

This reverts commit 367c86398ef2616006a2cbd2339ef2f30ed2800e.

* Removed zano.dart (generated by scripts), some files restored to initial versions

* added timer library

* changed paths in build_zano.sh

* build_zano.sh

* edit_token_page.dart - removed flag skipZanoAddressValidation

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* lib/core/address_validator.dart - updated zano address regex
lib/src/screens/dashboard/edit_token_page.dart - using AddressValidator().call

* fix zano build issues on android

* remove contrib/depends to save space

* move async call to a synchronouse one

* call sync call in isolate to make it async
generate framework for iOS as well
fix UR issues

* zano changes from monero_c repo

* update monero_c hash

* fix invalid zano imports, add support for linux, speed up CI builds

* update monero_c hash

* bump monero_c commit (yes, again, I know)

* fix wallet resttore, fix hardcoded IP

* fix regex, don't throw error when opening wallet, fix tx history, fix async calls, move stuff to isolate

* fix api calls in async transaction creation

* update build scripts

* fix some build issues

* update dependencies

* fix dependencies

* update ci scripts

* Improve multithread use of zano api

* Fix build issue

* fix zano node selection, move other zano calls to separate isolate

* update moneroc hash
WIP fixes for zano

* update monero_c

* fix monero.com builds

* sync wallet after connecting

* update monero_c

* Fix windows builds

* update monero_c

* update monero_c

* unshallow submodule

* cherry pick CW-867 Wownero fixes (#1881)

* fix wownero syntax error

* remove print statements in zano

* update zano node URL

* [PATCH] Apply new CI script (https://github.com/cake-tech/cake_wallet/pull/1948)

* drop env -i to fix cmake build errors on newer system

* [skip ci] Revert "[PATCH] Apply new CI script (https://github.com/cake-tech/cake_wallet/pull/1948)"

This reverts commit 5acb5bfe57c4b2aeb7aa40bd684a3319a68f98bc.

* [run tests] [skip slack] Fix env in build

* Dynamically detect number of cores used to build monero_c, since it appears that zano requires more memory to link (and it reliably fails for first couple builds due to OOM on CI/VM with memory constrains).
Drop unshallowing of all modules
[run tests]

* Changes from review [run tests]

* drop zano on linux (missing symbols)
fix wownero on linux
add aarch64-linux-gnu
[run tests]

* - remove duplicate entry in addToken()
- use walletPassword in createZanoNewWalletCredentials
- remove createZanoRestoreWalletFromKeysCredentials
[run tests]

* [skip ci] update dockerfile

* fix parameter issue

---------

Co-authored-by: leo <leonid.ivanov@gmail.com>
Co-authored-by: cr.zoidberg <crypto.zoidberg@gmail.com>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* - Add Zano Aliases
- Enable simpleswap [skip ci]
- Fix settings migration versions

* push missing file [skip ci]

* Zano pr with CW-685 passphrase (#1969)

* my experiments

* Inital code for Zano integration

* Added missing android log lib

* added dummy wallet & some zano implementation

* fixing api for zano

* fixed zano build script

* attempt tp fix namespace problem

* added copy script for Zano files

* changes for zano wallet

* last updates

* zano.dart test app

* wallet recovery

* added pending transfer, some cleanup of unused

* some cleanup

* send + receive qr code

* last upd

* updated build_zano.sh

* updated zano ApiCalls, removed dummy

* updated zano ApiCalls, removed dummy

* added logging for get status/get info

* restored old wallet.dart

* restoring original versions of files

* restoring original versions of files

* restored get_height_by_date.dart, removed unnecessary calls for zano get height

* restoring original versions

* added multiple destinations, send all flag; some refactoring

* logging

* removed the duplicate

* fixed syncing sync status, decimal division, safe null json parsing

* some fixes after merge

* added multibalance/asset support for zano (ui)

* adding/removing from whitelist

* transfers in different assets

* transfers for multiple destinations and send all, some refactoring

* whitelists, some refactoring

* added different digits (decimal points) for formatters, some refactoring

* open, create, restore wallet refactoring; whitelists

* whitelists

* getting and updating transaction list; restoring a wallet from QR code

* several attempts to close wallet

* some refactoring

* added seed phrase

* CW-685 Add passphrase restore for xmr/wow

* add support for polyseed passphrase

* disable 14 word seed passphrase (not supported in wownero-seed)
fix: Getting grayed screen on latest passphrase build after having restored a 14-word wownero seed (+passphrase) and attempting to restore a XMR seed, legacy or otherwise.

* fix pointer when restoring depracated wownero seed

* Fix polyseed encryption

* changed fields to BigInt, some fixes

* modified build scripts for android

* build scripts

* restored accidently removed cw_haven.dart

* inital ios integration(zano libs built)

* update in script

* latest changes

* changes from review

* remove unused code

* add passphrase back to the screen
add passphrase to qr code backup export

* fix settings leaking through currencies on seed restore

* fix monero.com builds, make passphrase a getter on WalletBase

* add support for weird polyseed

* store passphrase for weird polyseed

* show encrypted seed only when passphrase is not empty

* force set restore height

* Applied a patch for iOS build (Boost and Zano scripts)

* Removed zano.dart (script-generated) and some unnecessary files

* Revert "Removed zano.dart (script-generated) and some unnecessary files"

This reverts commit 367c86398ef2616006a2cbd2339ef2f30ed2800e.

* Removed zano.dart (generated by scripts), some files restored to initial versions

* fix build issues

* fix build errors

* added timer library

* changed paths in build_zano.sh

* build_zano.sh

* edit_token_page.dart - removed flag skipZanoAddressValidation

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* lib/core/address_validator.dart - updated zano address regex
lib/src/screens/dashboard/edit_token_page.dart - using AddressValidator().call

* fix zano build issues on android

* remove contrib/depends to save space

* move async call to a synchronouse one

* call sync call in isolate to make it async
generate framework for iOS as well
fix UR issues

* zano changes from monero_c repo

* update monero_c hash

* fix invalid zano imports, add support for linux, speed up CI builds

* update monero_c hash

* bump monero_c commit (yes, again, I know)

* fix wallet resttore, fix hardcoded IP

* fix regex, don't throw error when opening wallet, fix tx history, fix async calls, move stuff to isolate

* fix api calls in async transaction creation

* fix configure script

* update build scripts

* fix some build issues

* update dependencies

* fix dependencies

* update ci scripts

* Improve multithread use of zano api

* Fix build issue

* fix zano node selection, move other zano calls to separate isolate

* update moneroc hash
WIP fixes for zano

* update monero_c

* fix monero.com builds

* sync wallet after connecting

* update monero_c

* Fix windows builds

* update monero_c

* print -> printV

* update monero_c

* unshallow submodule

* cherry pick CW-867 Wownero fixes (#1881)

* fix wownero syntax error

* remove print statements in zano

* update zano node URL

* [PATCH] Apply new CI script (https://github.com/cake-tech/cake_wallet/pull/1948)

* drop env -i to fix cmake build errors on newer system

* Update lib/view_model/wallet_keys_view_model.dart [skip ci]

* Update lib/view_model/wallet_keys_view_model.dart [skip ci]

* Update tool/configure.dart [skip ci]

* Update lib/view_model/wallet_new_vm.dart

* [skip ci] Revert "[PATCH] Apply new CI script (https://github.com/cake-tech/cake_wallet/pull/1948)"

This reverts commit 5acb5bfe57c4b2aeb7aa40bd684a3319a68f98bc.

* [run tests] [skip slack] Fix env in build

* Dynamically detect number of cores used to build monero_c, since it appears that zano requires more memory to link (and it reliably fails for first couple builds due to OOM on CI/VM with memory constrains).
Drop unshallowing of all modules
[run tests]

* Changes from review [run tests]

* drop zano on linux (missing symbols)
fix wownero on linux
add aarch64-linux-gnu
[run tests]

* - remove duplicate entry in addToken()
- use walletPassword in createZanoNewWalletCredentials
- remove createZanoRestoreWalletFromKeysCredentials
[run tests]

* [skip ci] update dockerfile

* reuse existing passphrase field

* add passphrase support for zano

* Drop aarch64-linux-gnu for now.

* fix passphrase display, fix gray screen

* catch errors in polyseed encryption, encrypt only polyseed, fix coin in wownero

* update monero_c
update wownero to 0.11.3.0

* Show passphrase only when non-empty, fix passphrase being displayed as view key private.

* fix NanoAccountListPage showing up instead of MoneroAccountListPage for wownero

* build zano dependencies on android

* fix parameter issue

* minor merge leftover [skip ci]

* minor cleanup [skip ci]

* fix zano alias
update eth url for ens lookup
change $MAKE_JOB_COUNT to $NPROC

* minor cleanup [skip ci]

* fix zano alias

* Disable passphrase for creation of xmr/wow/zano
minor fixes

* fix zano on iOS

* - Fix get token data
- Enable unavailable balance
- Enable confirmations count
- Adjust explorer link

---------

Co-authored-by: leo <leonid.ivanov@gmail.com>
Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com>
Co-authored-by: cr.zoidberg <crypto.zoidberg@gmail.com>
Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

---------

Co-authored-by: cyan <cyjan@mrcyjanek.net>
Co-authored-by: Konstantin Ullrich <konstantinullrich12@gmail.com>
Co-authored-by: leo <leonid.ivanov@gmail.com>
Co-authored-by: cr.zoidberg <crypto.zoidberg@gmail.com>
This commit is contained in:
Omar Hatem
2025-01-24 20:33:24 +02:00
committed by GitHub
co-authored by leo Konstantin Ullrich cr.zoidberg cyan
parent 9cda2c99e7
commit df3a26dc15
169 changed files with 6113 additions and 212 deletions
+9 -2
View File
@@ -2,9 +2,9 @@ import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/core/validator.dart';
import 'package:cake_wallet/solana/solana.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/erc20_token.dart';
const BEFORE_REGEX = '(^|\\s)';
const AFTER_REGEX = '(\$|\\s)';
@@ -19,7 +19,9 @@ class AddressValidator extends TextValidator {
? BitcoinNetwork.mainnet
: LitecoinNetwork.mainnet,
)
: null,
: type == CryptoCurrency.zano
? zano?.validateAddress
: null,
pattern: getPattern(type),
length: getLength(type));
@@ -132,6 +134,8 @@ class AddressValidator extends TextValidator {
pattern = 'D([1-9a-km-zA-HJ-NP-Z]){33}';
case CryptoCurrency.btcln:
pattern = '(lnbc|LNBC)([0-9]{1,}[a-zA-Z0-9]+)';
case CryptoCurrency.zano:
pattern = r'([1-9A-HJ-NP-Za-km-z]{90,200})|(@[\w\d-.]+)';
default:
return '';
}
@@ -271,6 +275,7 @@ class AddressValidator extends TextValidator {
return [64];
case CryptoCurrency.btcln:
case CryptoCurrency.kaspa:
case CryptoCurrency.zano:
default:
return null;
}
@@ -310,6 +315,8 @@ class AddressValidator extends TextValidator {
pattern = '[1-9A-HJ-NP-Za-km-z]+';
case CryptoCurrency.trx:
pattern = '(T|t)[1-9A-HJ-NP-Za-km-z]{33}';
case CryptoCurrency.zano:
pattern = '([1-9A-HJ-NP-Za-km-z]{90,200})|(@[\w\d-.]+)';
default:
if (type.tag == CryptoCurrency.eth.title) {
pattern = '0x[0-9a-zA-Z]{42}';
+2
View File
@@ -76,6 +76,8 @@ class DecimalAmountValidator extends TextValidator {
return '^([0-9]+([.\,][0-9]{1,12})?|[.\,][0-9]{1,12})\$';
case CryptoCurrency.btc:
return '^([0-9]+([.\,][0-9]{1,8})?|[.\,][0-9]{1,8})\$';
case CryptoCurrency.zano:
return '^([0-9]+([.\,][0-9]{1,12})?|[.\,][0-9]{1,18})\$';
default:
return '^([0-9]+([.\,][0-9]{1,12})?|[.\,][0-9]{1,12})\$';
}
+5 -1
View File
@@ -9,6 +9,7 @@ import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/solana/solana.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cake_wallet/utils/language_list.dart';
import 'package:cw_core/wallet_type.dart';
@@ -21,7 +22,8 @@ class SeedValidator extends Validator<MnemonicItem> {
final String language;
final List<String> _words;
static List<String> getWordList({required WalletType type, required String language}) {
static List<String> getWordList(
{required WalletType type, required String language}) {
switch (type) {
case WalletType.bitcoin:
return getBitcoinWordList(language);
@@ -46,6 +48,8 @@ class SeedValidator extends Validator<MnemonicItem> {
return tron!.getTronWordList(language);
case WalletType.wownero:
return wownero!.getWowneroWordList(language);
case WalletType.zano:
return zano!.getWordList(language);
case WalletType.none:
return [];
}
+1
View File
@@ -89,6 +89,7 @@ class WalletCreationService {
case WalletType.haven:
case WalletType.nano:
case WalletType.banano:
case WalletType.zano:
return false;
}
}
+4 -1
View File
@@ -245,6 +245,7 @@ import 'package:cake_wallet/view_model/wallet_seed_view_model.dart';
import 'package:cake_wallet/view_model/wallet_unlock_loadable_view_model.dart';
import 'package:cake_wallet/view_model/wallet_unlock_verifiable_view_model.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_type.dart';
@@ -1087,6 +1088,8 @@ Future<void> setup({
return tron!.createTronWalletService(_walletInfoSource, SettingsStoreBase.walletPasswordDirectInput);
case WalletType.wownero:
return wownero!.createWowneroWalletService(_walletInfoSource, _unspentCoinsInfoSource);
case WalletType.zano:
return zano!.createZanoWalletService(_walletInfoSource);
case WalletType.none:
throw Exception('Unexpected token: ${param1.toString()} for generating of WalletService');
}
@@ -1415,4 +1418,4 @@ Future<void> setup({
getIt.registerFactory(() => SeedVerificationPage(getIt.get<WalletSeedViewModel>()));
_isSetupFinished = true;
}
}
+60 -5
View File
@@ -44,6 +44,7 @@ const solanaDefaultNodeUri = 'solana-mainnet.core.chainstack.com';
const tronDefaultNodeUri = 'api.trongrid.io';
const newCakeWalletBitcoinUri = 'btc-electrum.cakewallet.com:50002';
const wowneroDefaultNodeUri = 'node3.monerodevs.org:34568';
const zanoDefaultNodeUri = '37.27.100.59:10500';
const moneroWorldNodeUri = '.moneroworld.com';
Future<void> defaultSettingsMigration(
@@ -260,7 +261,11 @@ Future<void> defaultSettingsMigration(
await removeMoneroWorld(sharedPreferences: sharedPreferences, nodes: nodes);
break;
case 41:
_deselectExchangeProvider(sharedPreferences, "Quantex");
_changeExchangeProviderAvailability(
sharedPreferences,
providerName: "Quantex",
enabled: false,
);
await _addSethNode(nodes, sharedPreferences);
await updateTronNodesWithNowNodes(sharedPreferences: sharedPreferences, nodes: nodes);
break;
@@ -269,8 +274,16 @@ Future<void> defaultSettingsMigration(
break;
case 43:
_fixNodesUseSSLFlag(nodes);
_deselectExchangeProvider(sharedPreferences, "THORChain");
_deselectExchangeProvider(sharedPreferences, "SimpleSwap");
_changeExchangeProviderAvailability(
sharedPreferences,
providerName: "THORChain",
enabled: false,
);
_changeExchangeProviderAvailability(
sharedPreferences,
providerName: "SimpleSwap",
enabled: false,
);
break;
case 44:
_fixNodesUseSSLFlag(nodes);
@@ -311,6 +324,7 @@ Future<void> defaultSettingsMigration(
type: WalletType.ethereum,
useSSL: true,
);
_changeDefaultNode(
nodes: nodes,
sharedPreferences: sharedPreferences,
@@ -373,6 +387,15 @@ Future<void> defaultSettingsMigration(
useSSL: true,
);
break;
case 47:
await addZanoNodeList(nodes: nodes);
await changeZanoCurrentNodeToDefault(sharedPreferences: sharedPreferences, nodes: nodes);
_changeExchangeProviderAvailability(
sharedPreferences,
providerName: "SimpleSwap",
enabled: true,
);
break;
default:
break;
}
@@ -469,12 +492,13 @@ Future<void> updateWalletTypeNodesWithNewNode({
);
}
void _deselectExchangeProvider(SharedPreferences sharedPreferences, String providerName) {
void _changeExchangeProviderAvailability(SharedPreferences sharedPreferences,
{required String providerName, required bool enabled}) {
final Map<String, dynamic> exchangeProvidersSelection =
json.decode(sharedPreferences.getString(PreferencesKey.exchangeProvidersSelection) ?? "{}")
as Map<String, dynamic>;
exchangeProvidersSelection[providerName] = false;
exchangeProvidersSelection[providerName] = enabled;
sharedPreferences.setString(
PreferencesKey.exchangeProvidersSelection,
@@ -703,6 +727,12 @@ Node? getBitcoinCashDefaultElectrumServer({required Box<Node> nodes}) {
nodes.values.firstWhereOrNull((node) => node.type == WalletType.bitcoinCash);
}
Node? getZanoDefaultNode({required Box<Node> nodes}) {
return nodes.values.firstWhereOrNull(
(Node node) => node.uriRaw == zanoDefaultNodeUri)
?? nodes.values.firstWhereOrNull((node) => node.type == WalletType.zano);
}
Node getMoneroDefaultNode({required Box<Node> nodes}) {
var nodeUri = newCakeWalletMoneroUri;
@@ -1199,6 +1229,7 @@ Future<void> checkCurrentNodes(
final currentSolanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
final currentTronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey);
final currentWowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey);
final currentZanoNodeId = sharedPreferences.getInt(PreferencesKey.currentZanoNodeIdKey);
final currentMoneroNode =
nodeSource.values.firstWhereOrNull((node) => node.key == currentMoneroNodeId);
final currentBitcoinElectrumServer =
@@ -1223,6 +1254,8 @@ Future<void> checkCurrentNodes(
nodeSource.values.firstWhereOrNull((node) => node.key == currentTronNodeId);
final currentWowneroNodeServer =
nodeSource.values.firstWhereOrNull((node) => node.key == currentWowneroNodeId);
final currentZanoNode = nodeSource.values.firstWhereOrNull((node) => node.key == currentZanoNodeId);
if (currentMoneroNode == null) {
final newCakeWalletNode = Node(uri: newCakeWalletMoneroUri, type: WalletType.monero);
await nodeSource.add(newCakeWalletNode);
@@ -1306,6 +1339,12 @@ Future<void> checkCurrentNodes(
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentWowneroNodeIdKey, node.key as int);
}
if (currentZanoNode == null) {
final node = Node(uri: zanoDefaultNodeUri, type: WalletType.zano);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, node.key as int);
}
}
Future<void> resetBitcoinElectrumServer(
@@ -1381,6 +1420,15 @@ Future<void> addWowneroNodeList({required Box<Node> nodes}) async {
}
}
Future<void> addZanoNodeList({required Box<Node> nodes}) async {
final nodeList = await loadDefaultZanoNodes();
for (var node in nodeList) {
if (nodes.values.firstWhereOrNull((element) => element.uriRaw == node.uriRaw) == null) {
await nodes.add(node);
}
}
}
Future<void> changeWowneroCurrentNodeToDefault(
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
final node = getWowneroDefaultNode(nodes: nodes);
@@ -1389,6 +1437,13 @@ Future<void> changeWowneroCurrentNodeToDefault(
await sharedPreferences.setInt(PreferencesKey.currentWowneroNodeIdKey, nodeId);
}
Future<void> changeZanoCurrentNodeToDefault(
{required SharedPreferences sharedPreferences, required Box<Node> nodes}) async {
final node = getZanoDefaultNode(nodes: nodes);
final nodeId = node?.key as int? ?? 0;
await sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, nodeId);
}
Future<void> addNanoNodeList({required Box<Node> nodes}) async {
final nodeList = await loadDefaultNanoNodes();
for (var node in nodeList) {
+1 -1
View File
@@ -20,7 +20,7 @@ class EnsRecord {
}
if (_client == null) {
_client = Web3Client("https://ethereum.publicnode.com", Client());
_client = Web3Client("https://ethereum-rpc.publicnode.com", Client());
}
try {
+19 -1
View File
@@ -200,6 +200,23 @@ Future<List<Node>> loadDefaultWowneroNodes() async {
return nodes;
}
Future<List<Node>> loadDefaultZanoNodes() async {
final nodesRaw = await rootBundle.loadString('assets/zano_node_list.yml');
final loadedNodes = loadYaml(nodesRaw) as YamlList;
final nodes = <Node>[];
for (final raw in loadedNodes) {
if (raw is Map) {
final node = Node.fromMap(Map<String, Object>.from(raw));
node.type = WalletType.zano;
nodes.add(node);
}
}
return nodes;
}
Future<void> resetToDefault(Box<Node> nodeSource) async {
final moneroNodes = await loadDefaultNodes();
final bitcoinElectrumServerList = await loadBitcoinElectrumServerList();
@@ -211,6 +228,7 @@ Future<void> resetToDefault(Box<Node> nodeSource) async {
final polygonNodes = await loadDefaultPolygonNodes();
final solanaNodes = await loadDefaultSolanaNodes();
final tronNodes = await loadDefaultTronNodes();
final zanoNodes = await loadDefaultZanoNodes();
final nodes = moneroNodes +
bitcoinElectrumServerList +
@@ -220,7 +238,7 @@ Future<void> resetToDefault(Box<Node> nodeSource) async {
bitcoinCashElectrumServerList +
nanoNodes +
polygonNodes +
solanaNodes + tronNodes;
solanaNodes + tronNodes + zanoNodes;
await nodeSource.clear();
await nodeSource.addAll(nodes);
@@ -6,6 +6,7 @@ import 'package:cake_wallet/entities/parsed_address.dart';
import 'package:cake_wallet/entities/unstoppable_domain_address.dart';
import 'package:cake_wallet/entities/emoji_string_extension.dart';
import 'package:cake_wallet/entities/wellknown_record.dart';
import 'package:cake_wallet/entities/zano_alias.dart';
import 'package:cake_wallet/exchange/provider/thorchain_exchange.provider.dart';
import 'package:cake_wallet/mastodon/mastodon_api.dart';
import 'package:cake_wallet/nostr/nostr_api.dart';
@@ -137,6 +138,16 @@ class AddressResolver {
try {
// twitter handle example: @username
if (text.startsWith('@') && !text.substring(1).contains('@')) {
if (currency == CryptoCurrency.zano && settingsStore.lookupsZanoAlias) {
final formattedName = text.substring(1);
final zanoAddress = await ZanoAlias.fetchZanoAliasAddress(formattedName);
if (zanoAddress != null) {
return ParsedAddress.zanoAddress(
address: zanoAddress,
name: text,
);
}
}
if (settingsStore.lookupsTwitter) {
final formattedName = text.substring(1);
final twitterUser = await TwitterApi.lookupUserByName(userName: formattedName);
+10 -1
View File
@@ -13,7 +13,8 @@ enum ParseFrom {
mastodon,
nostr,
thorChain,
wellKnown
wellKnown,
zanoAlias,
}
class ParsedAddress {
@@ -143,6 +144,14 @@ class ParsedAddress {
);
}
factory ParsedAddress.zanoAddress({required String address, required String name}) {
return ParsedAddress(
addresses: [address],
name: name,
parseFrom: ParseFrom.zanoAlias,
);
}
factory ParsedAddress.fetchWellKnownAddress({required String address, required String name}) {
return ParsedAddress(
addresses: [address],
+3
View File
@@ -5,6 +5,7 @@ class PreferencesKey {
static const currentBitcoinElectrumSererIdKey = 'current_node_id_btc';
static const currentLitecoinElectrumSererIdKey = 'current_node_id_ltc';
static const currentHavenNodeIdKey = 'current_node_id_xhv';
static const currentZanoNodeIdKey = 'current_node_id_zano';
static const currentEthereumNodeIdKey = 'current_node_id_eth';
static const currentPolygonNodeIdKey = 'current_node_id_matic';
static const currentNanoNodeIdKey = 'current_node_id_nano';
@@ -45,6 +46,7 @@ class PreferencesKey {
static const ethereumTransactionPriority = 'current_fee_priority_ethereum';
static const polygonTransactionPriority = 'current_fee_priority_polygon';
static const bitcoinCashTransactionPriority = 'current_fee_priority_bitcoin_cash';
static const zanoTransactionPriority = 'current_fee_priority_zano';
static const wowneroTransactionPriority = 'current_fee_priority_wownero';
static const customBitcoinFeeRate = 'custom_electrum_fee_rate';
static const silentPaymentsCardDisplay = 'silentPaymentsCardDisplay';
@@ -71,6 +73,7 @@ class PreferencesKey {
static const defaultNanoRep = 'default_nano_representative';
static const defaultBananoRep = 'default_banano_representative';
static const lookupsTwitter = 'looks_up_twitter';
static const lookupsZanoAlias = 'looks_up_zano_alias';
static const lookupsMastodon = 'looks_up_mastodon';
static const lookupsYatService = 'looks_up_yat';
static const lookupsUnstoppableDomains = 'looks_up_unstoppable_domain';
@@ -5,6 +5,7 @@ import 'package:cake_wallet/haven/haven.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/polygon/polygon.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/wallet_type.dart';
@@ -32,6 +33,8 @@ List<TransactionPriority> priorityForWalletType(WalletType type) {
case WalletType.solana:
case WalletType.tron:
return [];
case WalletType.zano:
return zano!.getTransactionPriorities();
default:
return [];
}
+2
View File
@@ -76,6 +76,7 @@ class ProvidersHelper {
];
case WalletType.none:
case WalletType.haven:
case WalletType.zano:
return [];
}
}
@@ -109,6 +110,7 @@ class ProvidersHelper {
case WalletType.none:
case WalletType.haven:
case WalletType.wownero:
case WalletType.zano:
return [];
}
}
+28
View File
@@ -0,0 +1,28 @@
import 'dart:convert';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:http/http.dart' as http;
class ZanoAlias {
static Future<String?> fetchZanoAliasAddress(String alias) async {
try {
final uri = Uri.parse("http://37.27.100.59:10500/json_rpc");
final response = await http.post(
uri,
body: json.encode({
"id": 0,
"jsonrpc": "2.0",
"method": "get_alias_details",
"params": {"alias": alias}
}),
);
final jsonParsed = json.decode(response.body) as Map<String, dynamic>;
return jsonParsed['result']['alias_details']['address'] as String?;
} catch (e) {
printV('Zano Alias error: ${e.toString()}');
}
return null;
}
}
+1 -1
View File
@@ -215,7 +215,7 @@ Future<void> initializeAppConfigs() async {
secureStorage: secureStorage,
anonpayInvoiceInfo: anonpayInvoiceInfo,
havenSeedStore: havenSeedStore,
initialMigrationVersion: 46,
initialMigrationVersion: 47,
);
}
+4 -2
View File
@@ -242,10 +242,11 @@ class CWMonero extends Monero {
WalletCredentials createMoneroRestoreWalletFromSeedCredentials(
{required String name,
required String password,
required String passphrase,
required int height,
required String mnemonic}) =>
MoneroRestoreWalletFromSeedCredentials(
name: name, password: password, height: height, mnemonic: mnemonic);
name: name, password: password, passphrase: passphrase, height: height, mnemonic: mnemonic);
@override
WalletCredentials createMoneroNewWalletCredentials({
@@ -265,7 +266,8 @@ class CWMonero extends Monero {
'privateSpendKey': keys.privateSpendKey,
'privateViewKey': keys.privateViewKey,
'publicSpendKey': keys.publicSpendKey,
'publicViewKey': keys.publicViewKey
'publicViewKey': keys.publicViewKey,
'passphrase': keys.passphrase
};
}
+1
View File
@@ -15,6 +15,7 @@ bool isBIP39Wallet(WalletType walletType) {
case WalletType.monero:
case WalletType.wownero:
case WalletType.haven:
case WalletType.zano:
case WalletType.none:
return false;
}
@@ -1,6 +1,5 @@
import 'package:cw_core/utils/print_verbose.dart';
import 'package:mobx/mobx.dart';
import 'package:cw_core/node.dart';
import 'package:cake_wallet/store/app_store.dart';
ReactionDisposer? _onCurrentNodeChangeReaction;
@@ -46,6 +46,7 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
final solanaIcon = Image.asset('assets/images/sol_icon.png', height: 24, width: 24);
final tronIcon = Image.asset('assets/images/trx_icon.png', height: 24, width: 24);
final wowneroIcon = Image.asset('assets/images/wownero_icon.png', height: 24, width: 24);
final zanoIcon = Image.asset('assets/images/zano_icon.png', height: 24, width: 24);
final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24);
Image _newWalletImage(BuildContext context) => Image.asset(
@@ -158,6 +159,8 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
return bitcoinIcon;
case WalletType.monero:
return moneroIcon;
case WalletType.wownero:
return wowneroIcon;
case WalletType.litecoin:
return litecoinIcon;
case WalletType.haven:
@@ -176,8 +179,8 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
return solanaIcon;
case WalletType.tron:
return tronIcon;
case WalletType.wownero:
return wowneroIcon;
case WalletType.zano:
return zanoIcon;
default:
return nonWalletTypeIcon;
}
+22 -5
View File
@@ -2,6 +2,7 @@ import 'package:cake_wallet/core/address_validator.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/address_text_field.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/src/widgets/checkbox_widget.dart';
@@ -12,6 +13,7 @@ import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
@@ -242,7 +244,21 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> {
},
);
} else {
await actionCall();
try {
await actionCall();
} catch (e) {
showPopUp<void>(
context: context,
builder: (dialogContext) {
return AlertWithOneAction(
alertTitle: "Unable to add token",
alertContent: "$e",
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop(),
);
},
);
}
if (mounted) {
Navigator.pop(context);
}
@@ -269,11 +285,12 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> {
final token = await widget.homeSettingsViewModel.getToken(_contractAddressController.text);
if (token != null) {
if (_tokenNameController.text.isEmpty) _tokenNameController.text = token.name;
if (_tokenSymbolController.text.isEmpty) _tokenSymbolController.text = token.title;
final isZano = widget.homeSettingsViewModel.walletType == WalletType.zano;
if (_tokenNameController.text.isEmpty || isZano) _tokenNameController.text = token.name;
if (_tokenSymbolController.text.isEmpty || isZano) _tokenSymbolController.text = token.title;
if (_tokenIconPathController.text.isEmpty)
_tokenIconPathController.text = token.iconPath ?? '';
if (_tokenDecimalController.text.isEmpty)
if (_tokenDecimalController.text.isEmpty || isZano)
_tokenDecimalController.text = token.decimals.toString();
}
}
@@ -305,7 +322,7 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> {
placeholder: S.of(context).token_contract_address,
options: [AddressTextFieldOption.paste],
buttonColor: Theme.of(context).hintColor,
validator: AddressValidator(type: widget.homeSettingsViewModel.nativeToken),
validator: widget.homeSettingsViewModel.walletType == WalletType.zano ? null : AddressValidator(type: widget.homeSettingsViewModel.nativeToken).call,
onPushPasteButton: (_) {
_pasteText();
},
@@ -37,7 +37,8 @@ class MenuWidgetState extends State<MenuWidget> {
this.polygonIcon = Image.asset('assets/images/matic_icon.png'),
this.solanaIcon = Image.asset('assets/images/sol_icon.png'),
this.tronIcon = Image.asset('assets/images/trx_icon.png'),
this.wowneroIcon = Image.asset('assets/images/wownero_icon.png');
this.wowneroIcon = Image.asset('assets/images/wownero_icon.png'),
this.zanoIcon = Image.asset('assets/images/zano_icon.png');
final largeScreen = 731;
@@ -62,6 +63,7 @@ class MenuWidgetState extends State<MenuWidget> {
Image solanaIcon;
Image tronIcon;
Image wowneroIcon;
Image zanoIcon;
@override
void initState() {
@@ -245,6 +247,8 @@ class MenuWidgetState extends State<MenuWidget> {
return tronIcon;
case WalletType.wownero:
return wowneroIcon;
case WalletType.zano:
return zanoIcon;
default:
throw Exception('No icon for ${type.toString()}');
}
@@ -202,7 +202,7 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo
);
return Container();
}),
if (widget.privacySettingsViewModel.hasPassphraseOption)
if (widget.privacySettingsViewModel.hasPassphraseOption(widget.isFromRestore))
Padding(
padding: EdgeInsets.all(24),
child: Form(
@@ -219,7 +219,7 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo
}),
child: Icon(
Icons.remove_red_eye,
color: obscurePassphrase ? Colors.black54 : Colors.black26,
// color: obscurePassphrase ? Colors.black54 : Colors.black26,
),
),
),
@@ -241,7 +241,7 @@ class _AdvancedPrivacySettingsBodyState extends State<_AdvancedPrivacySettingsBo
}),
child: Icon(
Icons.remove_red_eye,
color: obscurePassphrase ? Colors.black54 : Colors.black26,
// color: obscurePassphrase ? Colors.black54 : Colors.black26,
),
),
),
@@ -92,6 +92,7 @@ class _AddressListState extends State<AddressList> {
walletAddressListViewModel: widget.addressListViewModel,
trailingButtonTap: () async {
if (widget.addressListViewModel.type == WalletType.monero ||
widget.addressListViewModel.type == WalletType.wownero ||
widget.addressListViewModel.type == WalletType.haven) {
await showPopUp<void>(
context: context, builder: (_) => getIt.get<MoneroAccountListPage>());
@@ -58,7 +58,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
repeatedPasswordTextEditingController = displayWalletPassword
? TextEditingController()
: null,
seedTypeController = TextEditingController();
seedTypeController = TextEditingController();
final GlobalKey<SeedWidgetState> seedWidgetStateKey;
final GlobalKey<BlockchainHeightState> blockchainHeightKey;
@@ -75,7 +75,8 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
@override
void initState() {
_setSeedType(widget.seedSettingsViewModel.moneroSeedType);
// _setSeedType(widget.seedTypeViewModel.moneroSeedType);
_setSeedType(MoneroSeedType.defaultSeedType);
_setLanguageLabel(language);
if (passwordTextEditingController != null) {
@@ -99,7 +100,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
}
@override
void dispose() {
void dispose() {
moneroSeedTypeReaction();
if (passwordListener != null) {
@@ -200,9 +201,9 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
items: _getItems(),
selectedAtIndex: isPolyseed
? 1
: seedTypeController.value.text.contains("14")
? 2
: 0,
: seedTypeController.value.text.contains("14") && widget.type == WalletType.wownero
? 2
: 0,
mainAxisAlignment: MainAxisAlignment.start,
onItemSelected: _changeSeedType,
isSeparated: false,
@@ -274,6 +274,7 @@ class WalletRestorePage extends BasePage {
final seedWords = seedPhrase.split(' ');
if (seedWords.length == 14 && walletRestoreViewModel.type == WalletType.wownero) return true;
if (seedWords.length == 26 && walletRestoreViewModel.type == WalletType.zano) return true;
if ((walletRestoreViewModel.type == WalletType.monero ||
walletRestoreViewModel.type == WalletType.wownero ||
@@ -66,6 +66,11 @@ Future<String> extractAddressFromParsed(
content = S.of(context).extracted_address_content('${parsedAddress.name} (ThorChain)');
address = parsedAddress.addresses.first;
break;
case ParseFrom.zanoAlias:
title = S.of(context).address_detected;
content = S.of(context).extracted_address_content('${parsedAddress.name} (Zano Alias)');
address = parsedAddress.addresses.first;
break;
case ParseFrom.yatRecord:
if (parsedAddress.name.isEmpty) {
title = S.of(context).yat_error;
@@ -49,6 +49,10 @@ class DomainLookupsPage extends BasePage {
title: '.well-known',
value: _privacySettingsViewModel.looksUpWellKnown,
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsWellKnown(value)),
SettingsSwitcherCell(
title: 'Zano Aliases',
value: _privacySettingsViewModel.lookupsZanoAlias,
onValueChange: (_, bool value) => _privacySettingsViewModel.setLookupsZanoAlias(value)),
//if (!isHaven) it does not work correctly
],
@@ -131,6 +131,7 @@ class WalletListBodyState extends State<WalletListBody> {
final solanaIcon = Image.asset('assets/images/sol_icon.png', height: 24, width: 24);
final tronIcon = Image.asset('assets/images/trx_icon.png', height: 24, width: 24);
final wowneroIcon = Image.asset('assets/images/wownero_icon.png', height: 24, width: 24);
final zanoIcon = Image.asset('assets/images/zano_icon.png', height: 24, width: 24);
final scrollController = ScrollController();
final double tileHeight = 60;
Flushbar<void>? _progressBar;
@@ -401,6 +402,41 @@ class WalletListBodyState extends State<WalletListBody> {
);
}
Image _imageFor({required WalletType type, bool? isTestnet}) {
switch (type) {
case WalletType.bitcoin:
if (isTestnet == true) {
return tBitcoinIcon;
}
return bitcoinIcon;
case WalletType.monero:
return moneroIcon;
case WalletType.litecoin:
return litecoinIcon;
case WalletType.haven:
return havenIcon;
case WalletType.ethereum:
return ethereumIcon;
case WalletType.bitcoinCash:
return bitcoinCashIcon;
case WalletType.nano:
case WalletType.banano:
return nanoIcon;
case WalletType.polygon:
return polygonIcon;
case WalletType.solana:
return solanaIcon;
case WalletType.tron:
return tronIcon;
case WalletType.wownero:
return wowneroIcon;
case WalletType.zano:
return zanoIcon;
case WalletType.none:
return nonWalletTypeIcon;
}
}
Future<void> _loadWallet(WalletListItem wallet) async {
if (SettingsStoreBase.walletPasswordDirectInput) {
Navigator.of(context).pushNamed(Routes.walletUnlockLoadable,
+51 -1
View File
@@ -23,6 +23,10 @@ import 'package:cake_wallet/entities/seed_type.dart';
import 'package:cake_wallet/entities/sort_balance_types.dart';
import 'package:cake_wallet/entities/wallet_list_order_types.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/wallet_type_utils.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cake_wallet/exchange/provider/trocador_exchange_provider.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/polygon/polygon.dart';
@@ -110,6 +114,7 @@ abstract class SettingsStoreBase with Store {
required this.defaultNanoRep,
required this.defaultBananoRep,
required this.lookupsTwitter,
required this.lookupsZanoAlias,
required this.lookupsMastodon,
required this.lookupsYatService,
required this.lookupsUnstoppableDomains,
@@ -132,6 +137,7 @@ abstract class SettingsStoreBase with Store {
TransactionPriority? initialEthereumTransactionPriority,
TransactionPriority? initialPolygonTransactionPriority,
TransactionPriority? initialBitcoinCashTransactionPriority,
TransactionPriority? initialZanoTransactionPriority,
Country? initialCakePayCountry})
: nodes = ObservableMap<WalletType, Node>.of(nodes),
powNodes = ObservableMap<WalletType, Node>.of(powNodes),
@@ -215,6 +221,9 @@ abstract class SettingsStoreBase with Store {
priority[WalletType.bitcoinCash] = initialBitcoinCashTransactionPriority;
}
if (initialZanoTransactionPriority != null) {
priority[WalletType.zano] = initialZanoTransactionPriority;
}
if (initialCakePayCountry != null) {
selectedCakePayCountry = initialCakePayCountry;
}
@@ -268,6 +277,9 @@ abstract class SettingsStoreBase with Store {
case WalletType.polygon:
key = PreferencesKey.polygonTransactionPriority;
break;
case WalletType.zano:
key = PreferencesKey.zanoTransactionPriority;
break;
default:
key = null;
}
@@ -436,6 +448,10 @@ abstract class SettingsStoreBase with Store {
(_) => lookupsTwitter,
(bool looksUpTwitter) =>
_sharedPreferences.setBool(PreferencesKey.lookupsTwitter, looksUpTwitter));
reaction(
(_) => lookupsZanoAlias,
(bool lookupsZanoAlias) =>
_sharedPreferences.setBool(PreferencesKey.lookupsZanoAlias, lookupsZanoAlias));
reaction(
(_) => lookupsMastodon,
@@ -763,6 +779,9 @@ abstract class SettingsStoreBase with Store {
@observable
bool lookupsTwitter;
@observable
bool lookupsZanoAlias;
@observable
bool lookupsMastodon;
@@ -878,6 +897,7 @@ abstract class SettingsStoreBase with Store {
TransactionPriority? polygonTransactionPriority;
TransactionPriority? bitcoinCashTransactionPriority;
TransactionPriority? wowneroTransactionPriority;
TransactionPriority? zanoTransactionPriority;
if (sharedPreferences.getInt(PreferencesKey.havenTransactionPriority) != null) {
havenTransactionPriority = monero?.deserializeMoneroTransactionPriority(
@@ -903,6 +923,10 @@ abstract class SettingsStoreBase with Store {
wowneroTransactionPriority = wownero?.deserializeWowneroTransactionPriority(
raw: sharedPreferences.getInt(PreferencesKey.wowneroTransactionPriority)!);
}
if (sharedPreferences.getInt(PreferencesKey.zanoTransactionPriority) != null) {
zanoTransactionPriority = monero?.deserializeMoneroTransactionPriority(
raw: sharedPreferences.getInt(PreferencesKey.zanoTransactionPriority)!);
}
moneroTransactionPriority ??= monero?.getDefaultTransactionPriority();
bitcoinTransactionPriority ??= bitcoin?.getMediumTransactionPriority();
@@ -912,6 +936,7 @@ abstract class SettingsStoreBase with Store {
bitcoinCashTransactionPriority ??= bitcoinCash?.getDefaultTransactionPriority();
wowneroTransactionPriority ??= wownero?.getDefaultTransactionPriority();
polygonTransactionPriority ??= polygon?.getDefaultTransactionPriority();
zanoTransactionPriority ??= zano?.getDefaultTransactionPriority();
final currentBalanceDisplayMode = BalanceDisplayMode.deserialize(
raw: sharedPreferences.getInt(PreferencesKey.currentBalanceDisplayModeKey)!);
@@ -969,6 +994,7 @@ abstract class SettingsStoreBase with Store {
final defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
final defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? "";
final lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true;
final lookupsZanoAlias = sharedPreferences.getBool(PreferencesKey.lookupsZanoAlias) ?? true;
final lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true;
final lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true;
final lookupsUnstoppableDomains =
@@ -1011,6 +1037,8 @@ abstract class SettingsStoreBase with Store {
final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
final tronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey);
final wowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey);
final zanoNodeId = sharedPreferences.getInt(PreferencesKey.currentZanoNodeIdKey);
final moneroNode = nodeSource.get(nodeId);
final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId);
final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId);
@@ -1023,6 +1051,7 @@ abstract class SettingsStoreBase with Store {
final solanaNode = nodeSource.get(solanaNodeId);
final tronNode = nodeSource.get(tronNodeId);
final wowneroNode = nodeSource.get(wowneroNodeId);
final zanoNode = nodeSource.get(zanoNodeId);
final packageInfo = await PackageInfo.fromPlatform();
final deviceName = await _getDeviceName() ?? '';
final shouldShowYatPopup = sharedPreferences.getBool(PreferencesKey.shouldShowYatPopup) ?? true;
@@ -1104,6 +1133,10 @@ abstract class SettingsStoreBase with Store {
nodes[WalletType.wownero] = wowneroNode;
}
if (zanoNode != null) {
nodes[WalletType.zano] = zanoNode;
}
final savedSyncMode = SyncMode.all.firstWhere((element) {
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 0);
});
@@ -1249,6 +1282,7 @@ abstract class SettingsStoreBase with Store {
defaultNanoRep: defaultNanoRep,
defaultBananoRep: defaultBananoRep,
lookupsTwitter: lookupsTwitter,
lookupsZanoAlias: lookupsZanoAlias,
lookupsMastodon: lookupsMastodon,
lookupsYatService: lookupsYatService,
lookupsUnstoppableDomains: lookupsUnstoppableDomains,
@@ -1265,6 +1299,7 @@ abstract class SettingsStoreBase with Store {
hasEnabledMwebBefore: hasEnabledMwebBefore,
initialMoneroTransactionPriority: moneroTransactionPriority,
initialWowneroTransactionPriority: wowneroTransactionPriority,
initialZanoTransactionPriority: zanoTransactionPriority,
initialBitcoinTransactionPriority: bitcoinTransactionPriority,
initialHavenTransactionPriority: havenTransactionPriority,
initialLitecoinTransactionPriority: litecoinTransactionPriority,
@@ -1339,6 +1374,10 @@ abstract class SettingsStoreBase with Store {
priority[WalletType.bitcoinCash] = bitcoinCash!.deserializeBitcoinCashTransactionPriority(
sharedPreferences.getInt(PreferencesKey.bitcoinCashTransactionPriority)!);
}
if (zano != null && sharedPreferences.getInt(PreferencesKey.zanoTransactionPriority) != null) {
priority[WalletType.zano] = zano!.deserializeMoneroTransactionPriority(
raw: sharedPreferences.getInt(PreferencesKey.zanoTransactionPriority)!);
}
final generateSubaddresses =
sharedPreferences.getInt(PreferencesKey.autoGenerateSubaddressStatusKey);
@@ -1418,6 +1457,7 @@ abstract class SettingsStoreBase with Store {
defaultNanoRep = sharedPreferences.getString(PreferencesKey.defaultNanoRep) ?? "";
defaultBananoRep = sharedPreferences.getString(PreferencesKey.defaultBananoRep) ?? "";
lookupsTwitter = sharedPreferences.getBool(PreferencesKey.lookupsTwitter) ?? true;
lookupsZanoAlias = sharedPreferences.getBool(PreferencesKey.lookupsZanoAlias) ?? true;
lookupsMastodon = sharedPreferences.getBool(PreferencesKey.lookupsMastodon) ?? true;
lookupsYatService = sharedPreferences.getBool(PreferencesKey.lookupsYatService) ?? true;
lookupsUnstoppableDomains =
@@ -1448,6 +1488,7 @@ abstract class SettingsStoreBase with Store {
final solanaNodeId = sharedPreferences.getInt(PreferencesKey.currentSolanaNodeIdKey);
final tronNodeId = sharedPreferences.getInt(PreferencesKey.currentTronNodeIdKey);
final wowneroNodeId = sharedPreferences.getInt(PreferencesKey.currentWowneroNodeIdKey);
final zanoNodeId = sharedPreferences.getInt(PreferencesKey.currentZanoNodeIdKey);
final moneroNode = nodeSource.get(nodeId);
final bitcoinElectrumServer = nodeSource.get(bitcoinElectrumServerId);
final litecoinElectrumServer = nodeSource.get(litecoinElectrumServerId);
@@ -1455,10 +1496,12 @@ abstract class SettingsStoreBase with Store {
final ethereumNode = nodeSource.get(ethereumNodeId);
final polygonNode = nodeSource.get(polygonNodeId);
final bitcoinCashNode = nodeSource.get(bitcoinCashElectrumServerId);
final nanoNode = nodeSource.get(nanoNodeId);
final nanoNode = nodeSource.get(nanoNodeId);
final solanaNode = nodeSource.get(solanaNodeId);
final tronNode = nodeSource.get(tronNodeId);
final wowneroNode = nodeSource.get(wowneroNodeId);
final zanoNode = nodeSource.get(zanoNodeId);
if (moneroNode != null) {
nodes[WalletType.monero] = moneroNode;
}
@@ -1501,6 +1544,11 @@ abstract class SettingsStoreBase with Store {
if (wowneroNode != null) {
nodes[WalletType.wownero] = wowneroNode;
}
if (zanoNode != null) {
nodes[WalletType.zano] = zanoNode;
}
// MIGRATED:
@@ -1639,6 +1687,8 @@ abstract class SettingsStoreBase with Store {
case WalletType.wownero:
await _sharedPreferences.setInt(PreferencesKey.currentWowneroNodeIdKey, node.key as int);
break;
case WalletType.zano:
await _sharedPreferences.setInt(PreferencesKey.currentZanoNodeIdKey, node.key as int);
default:
break;
}
@@ -54,11 +54,11 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
case WalletType.wownero:
case WalletType.none:
case WalletType.haven:
case WalletType.zano:
return false;
}
}
bool get isMoneroSeedTypeOptionsEnabled => [
WalletType.monero,
WalletType.wownero,
@@ -71,13 +71,16 @@ abstract class AdvancedPrivacySettingsViewModelBase with Store {
bool get isNanoSeedTypeOptionsEnabled => [WalletType.nano].contains(type);
bool get hasPassphraseOption => [
bool hasPassphraseOption(bool isRestore) => [
WalletType.bitcoin,
WalletType.litecoin,
WalletType.bitcoinCash,
WalletType.ethereum,
WalletType.polygon,
WalletType.tron,
if (isRestore) WalletType.monero,
if (isRestore) WalletType.wownero,
if (isRestore) WalletType.zano,
].contains(type);
@computed
@@ -111,7 +111,8 @@ abstract class BalanceViewModelBase with Store {
bool get isHomeScreenSettingsEnabled =>
isEVMCompatibleChain(wallet.type) ||
wallet.type == WalletType.solana ||
wallet.type == WalletType.tron;
wallet.type == WalletType.tron ||
wallet.type == WalletType.zano;
@computed
bool get hasAccounts => wallet.type == WalletType.monero || wallet.type == WalletType.wownero;
@@ -306,6 +307,7 @@ abstract class BalanceViewModelBase with Store {
switch (type) {
case WalletType.monero:
case WalletType.wownero:
case WalletType.zano:
return true;
default:
return false;
@@ -13,6 +13,7 @@ import 'package:cake_wallet/solana/solana.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/erc20_token.dart';
import 'package:cw_core/utils/print_verbose.dart';
@@ -39,6 +40,8 @@ abstract class HomeSettingsViewModelBase with Store {
final ObservableSet<CryptoCurrency> tokens;
WalletType get walletType => _balanceViewModel.wallet.type;
@observable
bool isAddingToken;
@@ -108,6 +111,10 @@ abstract class HomeSettingsViewModelBase with Store {
await tron!.addTronToken(_balanceViewModel.wallet, token, contractAddress);
}
if (_balanceViewModel.wallet.type == WalletType.zano) {
await zano!.addZanoAssetById(_balanceViewModel.wallet, contractAddress);
}
_updateTokensList();
_updateFiatPrices(token);
} finally {
@@ -134,6 +141,9 @@ abstract class HomeSettingsViewModelBase with Store {
if (_balanceViewModel.wallet.type == WalletType.tron) {
await tron!.deleteTronToken(_balanceViewModel.wallet, token);
}
if (_balanceViewModel.wallet.type == WalletType.zano) {
await zano!.deleteZanoAsset(_balanceViewModel.wallet, token);
}
_updateTokensList();
} finally {
isDeletingToken = false;
@@ -340,6 +350,10 @@ abstract class HomeSettingsViewModelBase with Store {
return await tron!.getTronToken(_balanceViewModel.wallet, contractAddress);
}
if (_balanceViewModel.wallet.type == WalletType.zano) {
return await zano!.getZanoAsset(_balanceViewModel.wallet, contractAddress);
}
return null;
}
@@ -378,6 +392,10 @@ abstract class HomeSettingsViewModelBase with Store {
tron!.addTronToken(_balanceViewModel.wallet, token, address);
}
if (_balanceViewModel.wallet.type == WalletType.zano) {
await zano!.changeZanoAssetAvailability(_balanceViewModel.wallet, token);
}
_refreshTokensList();
}
@@ -432,6 +450,13 @@ abstract class HomeSettingsViewModelBase with Store {
.toList()
..sort(_sortFunc));
}
if (_balanceViewModel.wallet.type == WalletType.zano) {
tokens.addAll(zano!.getZanoAssets(_balanceViewModel.wallet)
.where((element) => _matchesSearchText(element))
.toList()
..sort(_sortFunc));
}
}
@action
@@ -476,6 +501,10 @@ abstract class HomeSettingsViewModelBase with Store {
return polygon!.getTokenAddress(asset);
}
if (_balanceViewModel.wallet.type == WalletType.zano) {
return zano!.getZanoAssetAddress(asset);
}
// We return null if it's neither Tron, Polygon, Ethereum or Solana wallet (which is actually impossible because we only display home settings for either of these three wallets).
return null;
}
@@ -8,6 +8,7 @@ import 'package:cake_wallet/reactions/wallet_connect.dart';
import 'package:cake_wallet/solana/solana.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/transaction_info.dart';
@@ -63,6 +64,7 @@ class TransactionListItem extends ActionListItem with Keyable {
switch (balanceViewModel.wallet.type) {
case WalletType.monero:
case WalletType.haven:
case WalletType.zano:
if (transaction.confirmations >= 0 && transaction.confirmations < 10) {
return ' (${transaction.confirmations}/10)';
}
@@ -201,7 +203,6 @@ class TransactionListItem extends ActionListItem with Keyable {
price: price,
);
break;
case WalletType.tron:
final asset = tron!.assetOfTransaction(balanceViewModel.wallet, transaction);
final price = balanceViewModel.fiatConvertationStore.prices[asset];
@@ -211,6 +212,13 @@ class TransactionListItem extends ActionListItem with Keyable {
price: price,
);
break;
case WalletType.zano:
final asset = zano!.assetOfTransaction(balanceViewModel.wallet, transaction);
final price = balanceViewModel.fiatConvertationStore.prices[asset];
amount = calculateFiatAmountRaw(
cryptoAmount: zano!.formatterIntAmountToDouble(amount: transaction.amount, currency: asset, forFee: false),
price: price);
break;
default:
break;
}
@@ -311,6 +311,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
case WalletType.monero:
case WalletType.wownero:
case WalletType.haven:
case WalletType.zano:
return transactionPriority == monero!.getMoneroTransactionPrioritySlow();
case WalletType.bitcoin:
return transactionPriority == bitcoin!.getBitcoinTransactionPrioritySlow();
@@ -750,6 +751,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
depositCurrency = CryptoCurrency.wow;
receiveCurrency = CryptoCurrency.xmr;
break;
case WalletType.zano:
depositCurrency = CryptoCurrency.zano;
receiveCurrency = CryptoCurrency.xmr;
break;
case WalletType.none:
break;
}
@@ -824,6 +829,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
case WalletType.monero:
case WalletType.haven:
case WalletType.wownero:
case WalletType.zano:
_settingsStore.priority[wallet.type] = monero!.getMoneroTransactionPriorityAutomatic();
break;
case WalletType.bitcoin:
@@ -85,6 +85,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
case WalletType.litecoin:
case WalletType.bitcoinCash:
case WalletType.bitcoin:
case WalletType.zano:
return false;
}
}
@@ -88,6 +88,9 @@ abstract class NodeListViewModelBase with Store {
case WalletType.wownero:
node = getWowneroDefaultNode(nodes: _nodeSource);
break;
case WalletType.zano:
node = getZanoDefaultNode(nodes: _nodeSource)!;
break;
default:
throw Exception('Unexpected wallet type: ${_appStore.wallet!.type}');
}
@@ -9,6 +9,7 @@ import 'package:cake_wallet/view_model/restore/restore_mode.dart';
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/monero/monero.dart';
@@ -110,6 +111,7 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
height: restoreWallet.height ?? 0,
mnemonic: restoreWallet.mnemonicSeed ?? '',
password: password,
passphrase: restoreWallet.passphrase ?? '',
);
case WalletType.bitcoin:
case WalletType.litecoin:
@@ -180,6 +182,15 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
height: restoreWallet.height ?? 0,
mnemonic: restoreWallet.mnemonicSeed ?? '',
password: password,
passphrase: restoreWallet.passphrase ?? '',
);
case WalletType.zano:
return zano!.createZanoRestoreWalletFromSeedCredentials(
name: name,
password: password,
height: height,
mnemonic: restoreWallet.mnemonicSeed ?? '',
passphrase: restoreWallet.passphrase ?? '',
);
default:
throw Exception('Unexpected type: ${type.toString()}');
@@ -41,6 +41,9 @@ class WalletRestoreFromQRCode {
'wownero': WalletType.wownero,
'wownero-wallet': WalletType.wownero,
'wownero_wallet': WalletType.wownero,
'zano': WalletType.zano,
'zano-wallet': WalletType.zano,
'zano_wallet': WalletType.zano,
};
static bool _containsAssetSpecifier(String code) => _extractWalletType(code) != null;
+11
View File
@@ -10,6 +10,7 @@ import 'package:cake_wallet/solana/solana.dart';
import 'package:cake_wallet/src/screens/send/widgets/extract_address_from_parsed.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/utils/print_verbose.dart';
import 'package:flutter/material.dart';
@@ -112,6 +113,9 @@ abstract class OutputBase with Store {
case WalletType.wownero:
_amount = wownero!.formatterWowneroParseAmount(amount: _cryptoAmount);
break;
case WalletType.zano:
_amount = zano!.formatterParseAmount(amount: _cryptoAmount, currency: cryptoCurrencyHandler());
break;
default:
break;
}
@@ -180,6 +184,10 @@ abstract class OutputBase with Store {
if (_wallet.type == WalletType.polygon) {
return polygon!.formatterPolygonAmountToDouble(amount: BigInt.from(fee));
}
if (_wallet.type == WalletType.zano) {
return zano!.formatterIntAmountToDouble(amount: fee, currency: cryptoCurrencyHandler(), forFee: true);
}
} catch (e) {
printV(e.toString());
}
@@ -308,6 +316,9 @@ abstract class OutputBase with Store {
case WalletType.wownero:
maximumFractionDigits = 11;
break;
case WalletType.zano:
maximumFractionDigits = 12;
break;
default:
break;
}
+8 -2
View File
@@ -20,6 +20,7 @@ import 'package:cake_wallet/view_model/dashboard/balance_view_model.dart';
import 'package:cake_wallet/view_model/hardware_wallet/ledger_view_model.dart';
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_list_view_model.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/exceptions.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/transaction_priority.dart';
@@ -61,7 +62,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
selectedCryptoCurrency = wallet.currency;
hasMultipleTokens = isEVMCompatibleChain(wallet.type) ||
wallet.type == WalletType.solana ||
wallet.type == WalletType.tron;
wallet.type == WalletType.tron ||
wallet.type == WalletType.zano;
}
UnspentCoinsListViewModel unspentCoinsListViewModel;
@@ -81,7 +83,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
selectedCryptoCurrency = appStore.wallet!.currency,
hasMultipleTokens = isEVMCompatibleChain(appStore.wallet!.type) ||
appStore.wallet!.type == WalletType.solana ||
appStore.wallet!.type == WalletType.tron,
appStore.wallet!.type == WalletType.tron ||
appStore.wallet!.type == WalletType.zano,
outputs = ObservableList<Output>(),
_settingsStore = appStore.settingsStore,
fiatFromSettings = appStore.settingsStore.fiatCurrency,
@@ -576,6 +579,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
.createSolanaTransactionCredentials(outputs, currency: selectedCryptoCurrency);
case WalletType.tron:
return tron!.createTronTransactionCredentials(outputs, currency: selectedCryptoCurrency);
case WalletType.zano:
return zano!.createZanoTransactionCredentials(
outputs: outputs, priority: priority!, currency: selectedCryptoCurrency);
default:
throw Exception('Unexpected wallet type: ${wallet.type}');
}
@@ -1,4 +1,3 @@
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/entities/auto_generate_subaddress_status.dart';
import 'package:cake_wallet/entities/exchange_api_mode.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
@@ -79,6 +78,9 @@ abstract class PrivacySettingsViewModelBase with Store {
@computed
bool get lookupTwitter => _settingsStore.lookupsTwitter;
@computed
bool get lookupsZanoAlias => _settingsStore.lookupsZanoAlias;
@computed
bool get looksUpMastodon => _settingsStore.lookupsMastodon;
@@ -127,6 +129,9 @@ abstract class PrivacySettingsViewModelBase with Store {
@action
void setLookupsTwitter(bool value) => _settingsStore.lookupsTwitter = value;
@action
void setLookupsZanoAlias(bool value) => _settingsStore.lookupsZanoAlias = value;
@action
void setLookupsMastodon(bool value) => _settingsStore.lookupsMastodon = value;
@@ -81,6 +81,9 @@ abstract class TransactionDetailsViewModelBase with Store {
case WalletType.wownero:
_addWowneroListItems(tx, dateFormat);
break;
case WalletType.zano:
_addZanoListItems(tx, dateFormat);
break;
default:
break;
}
@@ -181,6 +184,8 @@ abstract class TransactionDetailsViewModelBase with Store {
return 'https://tronscan.org/#/transaction/${txId}';
case WalletType.wownero:
return 'https://explore.wownero.com/tx/${txId}';
case WalletType.zano:
return 'https://explorer.zano.org/transaction/${txId}';
case WalletType.none:
return '';
}
@@ -211,6 +216,8 @@ abstract class TransactionDetailsViewModelBase with Store {
return S.current.view_transaction_on + 'tronscan.org';
case WalletType.wownero:
return S.current.view_transaction_on + 'Wownero.com';
case WalletType.zano:
return S.current.view_transaction_on + 'explorer.zano.org';
case WalletType.none:
return '';
}
@@ -776,4 +783,20 @@ abstract class TransactionDetailsViewModelBase with Store {
items.addAll(_items);
}
void _addZanoListItems(TransactionInfo tx, DateFormat dateFormat) {
final comment = tx.additionalInfo['comment'] as String?;
items.addAll([
StandartListItem(title: S.current.transaction_details_transaction_id, value: tx.id),
StandartListItem(title: 'Asset ID', value: tx.additionalInfo['assetId'] as String? ?? "Unknown asset id"),
StandartListItem(
title: S.current.transaction_details_date, value: dateFormat.format(tx.date)),
StandartListItem(title: S.current.transaction_details_height, value: '${tx.height}'),
StandartListItem(title: S.current.transaction_details_amount, value: tx.amountFormatted()),
if (tx.feeFormatted()?.isNotEmpty ?? false)
StandartListItem(title: S.current.transaction_details_fee, value: tx.feeFormatted()!),
if (comment != null)
StandartListItem(title: S.current.transaction_details_title, value: comment),
]);
}
}
@@ -17,6 +17,7 @@ import 'package:cake_wallet/store/dashboard/fiat_conversion_store.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/store/yat/yat_store.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cake_wallet/utils/list_item.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_account_list_header.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_hidden_list_header.dart';
@@ -205,6 +206,23 @@ class WowneroURI extends PaymentURI {
}
}
class ZanoURI extends PaymentURI {
ZanoURI({required String amount, required String address})
: super(amount: amount, address: address);
@override
String toString() {
var base = 'zano:' + address;
if (amount.isNotEmpty) {
base += '?amount=${amount.replaceAll(',', '.')}';
}
return base;
}
}
abstract class WalletAddressListViewModelBase
extends WalletChangeListenerViewModel with Store {
WalletAddressListViewModelBase({
@@ -298,11 +316,12 @@ abstract class WalletAddressListViewModelBase
return TronURI(amount: amount, address: address.address);
case WalletType.wownero:
return WowneroURI(amount: amount, address: address.address);
case WalletType.zano:
return ZanoURI(amount: amount, address: address.address);
case WalletType.none:
throw Exception('Unexpected type: ${type.toString()}');
}
}
@computed
ObservableList<ListItem> get items => ObservableList<ListItem>()
..addAll(_baseItems)
@@ -479,6 +498,12 @@ abstract class WalletAddressListViewModelBase
.contains((addressList[i] as WalletAddressListItem).address);
}
if (wallet.type == WalletType.zano) {
final primaryAddress = zano!.getAddress(wallet);
addressList.add(WalletAddressListItem(isPrimary: true, name: null, address: primaryAddress));
}
if (searchText.isNotEmpty) {
return ObservableList.of(addressList.where((item) {
if (item is WalletAddressListItem) {
+11 -1
View File
@@ -6,11 +6,13 @@ import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.d
import 'package:cake_wallet/src/widgets/text_info_box.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cw_monero/monero_wallet.dart';
import 'package:cw_wownero/wownero_wallet.dart';
import 'package:flutter/foundation.dart';
import 'package:mobx/mobx.dart';
import 'package:polyseed/polyseed.dart';
@@ -255,6 +257,12 @@ abstract class WalletKeysViewModelBase with Store {
),
]);
}
if (_appStore.wallet!.type == WalletType.zano) {
items.addAll([
StandartListItem(title: S.current.wallet_seed, value: _appStore.wallet!.seed!),
]);
}
}
Future<int?> _currentHeight() async {
@@ -296,6 +304,8 @@ abstract class WalletKeysViewModelBase with Store {
return 'tron-wallet';
case WalletType.wownero:
return 'wownero-wallet';
case WalletType.zano:
return 'zano-wallet';
default:
throw Exception('Unexpected wallet type: ${_wallet.type.toString()}');
}
@@ -328,7 +338,7 @@ abstract class WalletKeysViewModelBase with Store {
return {
if (legacySeed.isNotEmpty) 'seed': legacySeed,
if (restoreHeightResult != null) ...{'height': restoreHeightResult},
if (_wallet.passphrase != null) 'passphrase': _wallet.passphrase!
if ((_wallet.passphrase ?? '') != '') 'passphrase': _wallet.passphrase!
};
}
+14 -1
View File
@@ -1,5 +1,13 @@
import 'package:cake_wallet/core/new_wallet_arguments.dart';
import 'package:cake_wallet/ethereum/ethereum.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/solana/solana.dart';
import 'package:cake_wallet/tron/tron.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/bitcoin_cash/bitcoin_cash.dart';
import 'package:cake_wallet/core/wallet_creation_service.dart';
@@ -152,9 +160,14 @@ abstract class WalletNewVMBase extends WalletCreationVM with Store {
case WalletType.wownero:
return wownero!.createWowneroNewWalletCredentials(
name: name,
password: walletPassword,
language: options!.first as String,
isPolyseed: options.last as bool,
password: walletPassword,
);
case WalletType.zano:
return zano!.createZanoNewWalletCredentials(
name: name,
password: walletPassword,
);
case WalletType.none:
throw Exception('Unexpected type: ${type.toString()}');
+11 -1
View File
@@ -15,6 +15,7 @@ import 'package:cake_wallet/view_model/restore/restore_mode.dart';
import 'package:cake_wallet/view_model/seed_settings_view_model.dart';
import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
import 'package:cake_wallet/wownero/wownero.dart';
import 'package:cake_wallet/zano/zano.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
@@ -61,6 +62,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
case WalletType.bitcoin:
case WalletType.litecoin:
case WalletType.bitcoinCash:
case WalletType.zano:
case WalletType.none:
availableModes = [WalletRestoreMode.seed];
break;
@@ -97,7 +99,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
switch (type) {
case WalletType.monero:
return monero!.createMoneroRestoreWalletFromSeedCredentials(
name: name, height: height, mnemonic: seed, password: password);
name: name, height: height, mnemonic: seed, password: password, passphrase: passphrase??'');
case WalletType.bitcoin:
case WalletType.litecoin:
return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials(
@@ -160,8 +162,16 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
name: name,
mnemonic: seed,
password: password,
passphrase: passphrase??'',
height: height,
);
case WalletType.zano:
return zano!.createZanoRestoreWalletFromSeedCredentials(
name: name,
password: password,
height: height,
passphrase: passphrase??'',
mnemonic: seed);
case WalletType.none:
break;
}
+4 -2
View File
@@ -222,10 +222,11 @@ class CWWownero extends Wownero {
WalletCredentials createWowneroRestoreWalletFromSeedCredentials(
{required String name,
required String password,
required String passphrase,
required int height,
required String mnemonic}) =>
WowneroRestoreWalletFromSeedCredentials(
name: name, password: password, height: height, mnemonic: mnemonic);
name: name, password: password, passphrase: passphrase, height: height, mnemonic: mnemonic);
@override
WalletCredentials createWowneroNewWalletCredentials(
@@ -244,7 +245,8 @@ class CWWownero extends Wownero {
'privateSpendKey': keys.privateSpendKey,
'privateViewKey': keys.privateViewKey,
'publicSpendKey': keys.publicSpendKey,
'publicViewKey': keys.publicViewKey
'publicViewKey': keys.publicViewKey,
'passphrase': keys.passphrase
};
}
+134
View File
@@ -0,0 +1,134 @@
part of 'zano.dart';
class CWZano extends Zano {
List<ZanoAsset> getZanoAssets(WalletBase wallet) => (wallet as ZanoWallet).zanoAssets.values.toList();
@override
Future<CryptoCurrency> addZanoAssetById(WalletBase wallet, String assetId) async => await (wallet as ZanoWallet).addZanoAssetById(assetId);
@override
Future<void> changeZanoAssetAvailability(WalletBase wallet, CryptoCurrency token) async => await (wallet as ZanoWallet).changeZanoAssetAvailability(token as ZanoAsset);
@override
Future<void> deleteZanoAsset(WalletBase wallet, CryptoCurrency token) async => await (wallet as ZanoWallet).deleteZanoAsset(token as ZanoAsset);
@override
Future<ZanoAsset?> getZanoAsset(WalletBase wallet, String assetId) async {
final zanoWallet = wallet as ZanoWallet;
return await zanoWallet.getZanoAsset(assetId);
}
// @override
// TransactionHistoryBase getTransactionHistory(Object wallet) {
// final zanoWallet = wallet as ZanoWallet;
// return zanoWallet.transactionHistory;
// }
@override
TransactionPriority getDefaultTransactionPriority() {
return MoneroTransactionPriority.automatic;
}
@override
TransactionPriority deserializeMoneroTransactionPriority({required int raw}) {
return MoneroTransactionPriority.deserialize(raw: raw);
}
@override
List<TransactionPriority> getTransactionPriorities() {
return MoneroTransactionPriority.all;
}
@override
List<String> getWordList(String language) {
assert(language.toLowerCase() == LanguageList.english.toLowerCase());
return EnglishMnemonics.words;
}
@override
WalletCredentials createZanoRestoreWalletFromSeedCredentials(
{required String name, required String password, required int height, required String passphrase, required String mnemonic}) {
return ZanoRestoreWalletFromSeedCredentials(name: name, password: password, passphrase: passphrase, height: height, mnemonic: mnemonic);
}
@override
WalletCredentials createZanoNewWalletCredentials({required String name, required String? password}) {
return ZanoNewWalletCredentials(name: name, password: password);
}
// @override
// Map<String, String> getKeys(Object wallet) {
// final zanoWallet = wallet as ZanoWallet;
// final keys = zanoWallet.keys;
// return <String, String>{
// 'privateSpendKey': keys.privateSpendKey,
// 'privateViewKey': keys.privateViewKey,
// 'publicSpendKey': keys.publicSpendKey,
// 'publicViewKey': keys.publicViewKey
// };
// }
@override
Object createZanoTransactionCredentials({required List<Output> outputs, required TransactionPriority priority, required CryptoCurrency currency}) {
return ZanoTransactionCredentials(
outputs: 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(),
priority: priority as MoneroTransactionPriority,
currency: currency,
);
}
@override
double formatterIntAmountToDouble({required int amount, required CryptoCurrency currency, required bool forFee}) {
// fee always counted in zano with default decimal points
if (forFee) return ZanoFormatter.intAmountToDouble(amount);
if (currency is ZanoAsset) return ZanoFormatter.intAmountToDouble(amount, currency.decimalPoint);
return ZanoFormatter.intAmountToDouble(amount);
}
@override
int formatterParseAmount({required String amount, required CryptoCurrency currency}) {
if (currency is ZanoAsset) return ZanoFormatter.parseAmount(amount, currency.decimalPoint);
return ZanoFormatter.parseAmount(amount);
}
// @override
// int getTransactionInfoAccountId(TransactionInfo tx) {
// final zanoTransactionInfo = tx as ZanoTransactionInfo;
// return zanoTransactionInfo.accountIndex;
// }
@override
WalletService createZanoWalletService(Box<WalletInfo> walletInfoSource) {
return ZanoWalletService(walletInfoSource);
}
@override
CryptoCurrency assetOfTransaction(WalletBase wallet, TransactionInfo transaction) {
transaction as ZanoTransactionInfo;
if (transaction.tokenSymbol == CryptoCurrency.zano.title) {
return CryptoCurrency.zano;
}
wallet as ZanoWallet;
final asset = wallet.zanoAssets.values.firstWhereOrNull((element) => element?.ticker == transaction.tokenSymbol);
return asset ?? CryptoCurrency.zano;
}
String getZanoAssetAddress(CryptoCurrency asset) => (asset as ZanoAsset).assetId;
@override
String getAddress(WalletBase wallet) => (wallet as ZanoWallet).walletAddresses.address;
@override
bool validateAddress(String address) => ZanoUtils.validateAddress(address);
}