Merge branch 'main' into CW-432-Add-Bitcoin-Cash-BCH

This commit is contained in:
Serhii 2023-08-25 15:27:30 +03:00
commit f7470addfe
322 changed files with 6381 additions and 4217 deletions

View file

@ -18,7 +18,7 @@ jobs:
- name: Flutter action
uses: subosito/flutter-action@v1
with:
flutter-version: '3.3.x'
flutter-version: '3.10.x'
channel: stable
- name: Install package dependencies

View file

@ -28,7 +28,7 @@ jobs:
- name: Flutter action
uses: subosito/flutter-action@v1
with:
flutter-version: '3.7.x'
flutter-version: '3.10.x'
channel: stable
- name: Install package dependencies
@ -55,7 +55,7 @@ jobs:
/opt/android/cake_wallet/cw_monero/android/.cxx
/opt/android/cake_wallet/cw_monero/ios/External
/opt/android/cake_wallet/cw_shared_external/ios/External
key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh') }}
key: ${{ hashFiles('**/build_monero.sh', '**/build_haven.sh', '**/monero_api.cpp') }}
- if: ${{ steps.cache-externals.outputs.cache-hit != 'true' }}
name: Generate Externals

2
.gitignore vendored
View file

@ -144,4 +144,4 @@ assets/images/app_logo.png
macos/Runner/Info.plist
macos/Runner/DebugProfile.entitlements
macos/Runner/Release.entitlements
macos/Runner/Release.entitlements

View file

@ -27,6 +27,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

View file

@ -1,8 +1,2 @@
Monero background syncing! See https://guides.cakewallet.com/docs/monero/#background-syncing
Cake 2FA access control settings! See https://guides.cakewallet.com/docs/advanced-features/authentication/#cake-2fa-presets-and-access-control-settings
Support Monero node proxy
UI improvements when sending to Address Book entry
Allow renaming Monero account names
Send templates now support multiple recipients (try using to make Monero change)
Onramper improvements
Scan node QR codes (for Umbrel)
Bug fixes
Fiat Onramp improvements

View file

@ -1,9 +1,2 @@
Ethereum! Store ETH and ERC-20 tokens
Monero background syncing! See https://guides.cakewallet.com/docs/monero/#background-syncing
Cake 2FA access control settings! See https://guides.cakewallet.com/docs/advanced-features/authentication/#cake-2fa-presets-and-access-control-settings
Support Monero node proxy
UI improvements when sending to Address Book entry
Allow renaming Monero/Haven account names
Send templates now support multiple recipients (try using to make Monero change)
Onramper improvements
Scan node QR codes (for Umbrel)
Bug fixes
Fiat Onramp improvements

View file

@ -1,4 +1,4 @@
class BitcoinTransactionNoInputsException implements Exception {
@override
String toString() => 'Not enough inputs available';
String toString() => 'Not enough inputs available. Please select more under Coin Control';
}

View file

@ -755,5 +755,5 @@ packages:
source: hosted
version: "3.1.1"
sdks:
dart: ">=2.19.0 <4.0.0"
dart: ">=2.19.0 <3.0.0"
flutter: ">=3.0.0"

View file

@ -13,16 +13,16 @@ dependencies:
flutter:
sdk: flutter
path_provider: ^2.0.11
http: ^0.13.4
http: ^1.1.0
mobx: ^2.0.7+4
flutter_mobx: ^2.0.6+1
intl: ^0.17.0
intl: ^0.18.0
cw_core:
path: ../cw_core
bitcoin_flutter:
git:
url: https://github.com/cake-tech/bitcoin_flutter.git
ref: cake-update-v2
ref: cake-update-v3
bitbox:
git:
url: https://github.com/Serhii-Borodenko/cw_bitbox.git

View file

@ -2,24 +2,31 @@ import 'package:cw_core/balance.dart';
import 'package:cw_core/monero_amount_format.dart';
class MoneroBalance extends Balance {
MoneroBalance({required this.fullBalance, required this.unlockedBalance})
MoneroBalance({required this.fullBalance, required this.unlockedBalance, this.frozenBalance = 0})
: formattedFullBalance = moneroAmountToString(amount: fullBalance),
formattedUnlockedBalance =
moneroAmountToString(amount: unlockedBalance),
formattedUnlockedBalance = moneroAmountToString(amount: unlockedBalance),
frozenFormatted = moneroAmountToString(amount: frozenBalance),
super(unlockedBalance, fullBalance);
MoneroBalance.fromString(
{required this.formattedFullBalance,
required this.formattedUnlockedBalance})
required this.formattedUnlockedBalance,
this.frozenFormatted = '0.0'})
: fullBalance = moneroParseAmount(amount: formattedFullBalance),
unlockedBalance = moneroParseAmount(amount: formattedUnlockedBalance),
frozenBalance = moneroParseAmount(amount: frozenFormatted),
super(moneroParseAmount(amount: formattedUnlockedBalance),
moneroParseAmount(amount: formattedFullBalance));
final int fullBalance;
final int unlockedBalance;
final int frozenBalance;
final String formattedFullBalance;
final String formattedUnlockedBalance;
final String frozenFormatted;
@override
String get formattedFrozenBalance => frozenFormatted == '0.0' ? '' : frozenFormatted;
@override
String get formattedAvailableBalance => formattedUnlockedBalance;

View file

@ -13,7 +13,9 @@ class UnspentCoinsInfo extends HiveObject {
required this.noteRaw,
required this.address,
required this.vout,
required this.value});
required this.value,
this.keyImage = null
});
static const typeId = UNSPENT_COINS_INFO_TYPE_ID;
static const boxName = 'Unspent';
@ -43,6 +45,9 @@ class UnspentCoinsInfo extends HiveObject {
@HiveField(7, defaultValue: 0)
int vout;
@HiveField(8, defaultValue: null)
String? keyImage;
String get note => noteRaw ?? '';
set note(String value) => noteRaw = value;

View file

@ -42,7 +42,9 @@ abstract class WalletBase<
set syncStatus(SyncStatus status);
String get seed;
String? get seed;
String? get privateKey => null;
Object get keys;

View file

@ -665,5 +665,5 @@ packages:
source: hosted
version: "3.1.1"
sdks:
dart: ">=2.19.0 <4.0.0"
dart: ">=2.19.0 <3.0.0"
flutter: ">=3.0.0"

View file

@ -12,12 +12,12 @@ environment:
dependencies:
flutter:
sdk: flutter
http: ^0.13.4
http: ^1.1.0
file: ^6.1.4
path_provider: ^2.0.11
mobx: ^2.0.7+4
flutter_mobx: ^2.0.6+1
intl: ^0.17.0
intl: ^0.18.0
encrypt: ^5.0.1
dev_dependencies:

View file

@ -9,7 +9,7 @@ import 'package:cw_ethereum/pending_ethereum_transaction.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart';
import 'package:web3dart/web3dart.dart';
import 'package:web3dart/contracts/erc20.dart';
import 'package:erc20/erc20.dart';
import 'package:cw_core/node.dart';
import 'package:cw_ethereum/ethereum_transaction_priority.dart';
import 'package:cw_ethereum/.secrets.g.dart' as secrets;
@ -72,7 +72,7 @@ class EthereumClient {
to: EthereumAddress.fromHex(toAddress),
maxGas: gas,
gasPrice: price,
maxPriorityFeePerGas: EtherAmount.fromUnitAndValue(EtherUnit.gwei, priority.tip),
maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip),
value: _isEthereum ? EtherAmount.inWei(BigInt.parse(amount)) : EtherAmount.zero(),
);
@ -83,7 +83,7 @@ class EthereumClient {
if (_isEthereum) {
_sendTransaction = () async => await sendTransaction(signedTransaction);
} else {
final erc20 = Erc20(
final erc20 = ERC20(
client: _client!,
address: EthereumAddress.fromHex(contractAddress!),
);
@ -153,7 +153,7 @@ I/flutter ( 4474): Gas Used: 53000
Future<ERC20Balance> fetchERC20Balances(
EthereumAddress userAddress, String contractAddress) async {
final erc20 = Erc20(address: EthereumAddress.fromHex(contractAddress), client: _client!);
final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!);
final balance = await erc20.balanceOf(userAddress);
int exponent = (await erc20.decimals()).toInt();
@ -163,7 +163,7 @@ I/flutter ( 4474): Gas Used: 53000
Future<Erc20Token?> getErc20Token(String contractAddress) async {
try {
final erc20 = Erc20(address: EthereumAddress.fromHex(contractAddress), client: _client!);
final erc20 = ERC20(address: EthereumAddress.fromHex(contractAddress), client: _client!);
final name = await erc20.name();
final symbol = await erc20.symbol();
final decimal = await erc20.decimals();

View file

@ -44,12 +44,14 @@ abstract class EthereumWalletBase
with Store {
EthereumWalletBase({
required WalletInfo walletInfo,
required String mnemonic,
String? mnemonic,
String? privateKey,
required String password,
ERC20Balance? initialBalance,
}) : syncStatus = NotConnectedSyncStatus(),
_password = password,
_mnemonic = mnemonic,
_hexPrivateKey = privateKey,
_isTransactionUpdating = false,
_client = EthereumClient(),
walletAddresses = EthereumWalletAddresses(walletInfo),
@ -66,12 +68,13 @@ abstract class EthereumWalletBase
_sharedPrefs.complete(SharedPreferences.getInstance());
}
final String _mnemonic;
final String? _mnemonic;
final String? _hexPrivateKey;
final String _password;
late final Box<Erc20Token> erc20TokensBox;
late final EthPrivateKey _privateKey;
late final EthPrivateKey _ethPrivateKey;
late EthereumClient _client;
@ -99,8 +102,12 @@ abstract class EthereumWalletBase
erc20TokensBox = await CakeHive.openBox<Erc20Token>(Erc20Token.boxName);
await walletAddresses.init();
await transactionHistory.init();
_privateKey = await getPrivateKey(_mnemonic, _password);
walletAddresses.address = _privateKey.address.toString();
_ethPrivateKey = await getPrivateKey(
mnemonic: _mnemonic,
privateKey: _hexPrivateKey,
password: _password,
);
walletAddresses.address = _ethPrivateKey.address.toString();
await save();
}
@ -108,8 +115,7 @@ abstract class EthereumWalletBase
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
try {
if (priority is EthereumTransactionPriority) {
final priorityFee =
EtherAmount.fromUnitAndValue(EtherUnit.gwei, priority.tip).getInWei.toInt();
final priorityFee = EtherAmount.fromInt(EtherUnit.gwei, priority.tip).getInWei.toInt();
return (_gasPrice! + priorityFee) * (_estimatedGas ?? 0);
}
@ -142,7 +148,7 @@ abstract class EthereumWalletBase
throw Exception("Ethereum Node connection failed");
}
_client.setListeners(_privateKey.address, _onNewTransaction);
_client.setListeners(_ethPrivateKey.address, _onNewTransaction);
_setTransactionUpdateTimer();
@ -202,7 +208,7 @@ abstract class EthereumWalletBase
}
final pendingEthereumTransaction = await _client.signTransaction(
privateKey: _privateKey,
privateKey: _ethPrivateKey,
toAddress: _credentials.outputs.first.isParsedAddress
? _credentials.outputs.first.extractedAddress!
: _credentials.outputs.first.address,
@ -240,7 +246,7 @@ abstract class EthereumWalletBase
@override
Future<Map<String, EthereumTransactionInfo>> fetchTransactions() async {
final address = _privateKey.address.hex;
final address = _ethPrivateKey.address.hex;
final transactions = await _client.fetchTransactions(address);
final List<Future<List<EthereumTransactionModel>>> erc20TokensTransactions = [];
@ -300,7 +306,10 @@ abstract class EthereumWalletBase
}
@override
String get seed => _mnemonic;
String? get seed => _mnemonic;
@override
String get privateKey => HEX.encode(_ethPrivateKey.privateKey);
@action
@override
@ -327,6 +336,7 @@ abstract class EthereumWalletBase
String toJSON() => json.encode({
'mnemonic': _mnemonic,
'private_key': privateKey,
'balance': balance[currency]!.toJSON(),
});
@ -338,13 +348,15 @@ abstract class EthereumWalletBase
final path = await pathForWallet(name: name, type: walletInfo.type);
final jsonSource = await read(path: path, password: password);
final data = json.decode(jsonSource) as Map;
final mnemonic = data['mnemonic'] as String;
final mnemonic = data['mnemonic'] as String?;
final privateKey = data['private_key'] as String?;
final balance = ERC20Balance.fromJSON(data['balance'] as String) ?? ERC20Balance(BigInt.zero);
return EthereumWallet(
walletInfo: walletInfo,
password: password,
mnemonic: mnemonic,
privateKey: privateKey,
initialBalance: balance,
);
}
@ -357,7 +369,7 @@ abstract class EthereumWalletBase
}
Future<ERC20Balance> _fetchEthBalance() async {
final balance = await _client.getBalance(_privateKey.address);
final balance = await _client.getBalance(_ethPrivateKey.address);
return ERC20Balance(balance.getInWei);
}
@ -366,7 +378,7 @@ abstract class EthereumWalletBase
try {
if (token.enabled) {
balance[token] = await _client.fetchERC20Balances(
_privateKey.address,
_ethPrivateKey.address,
token.contractAddress,
);
} else {
@ -376,8 +388,15 @@ abstract class EthereumWalletBase
}
}
Future<EthPrivateKey> getPrivateKey(String mnemonic, String password) async {
final seed = bip39.mnemonicToSeed(mnemonic);
Future<EthPrivateKey> getPrivateKey(
{String? mnemonic, String? privateKey, required String password}) async {
assert(mnemonic != null || privateKey != null);
if (privateKey != null) {
return EthPrivateKey.fromHex(privateKey);
}
final seed = bip39.mnemonicToSeed(mnemonic!);
final root = bip32.BIP32.fromSeed(seed);
@ -413,7 +432,7 @@ abstract class EthereumWalletBase
if (_token.enabled) {
balance[_token] = await _client.fetchERC20Balances(
_privateKey.address,
_ethPrivateKey.address,
_token.contractAddress,
);
} else {

View file

@ -8,16 +8,22 @@ class EthereumNewWalletCredentials extends WalletCredentials {
class EthereumRestoreWalletFromSeedCredentials extends WalletCredentials {
EthereumRestoreWalletFromSeedCredentials(
{required String name, required String password, required this.mnemonic, WalletInfo? walletInfo})
{required String name,
required String password,
required this.mnemonic,
WalletInfo? walletInfo})
: super(name: name, password: password, walletInfo: walletInfo);
final String mnemonic;
}
class EthereumRestoreWalletFromWIFCredentials extends WalletCredentials {
EthereumRestoreWalletFromWIFCredentials(
{required String name, required String password, required this.wif, WalletInfo? walletInfo})
class EthereumRestoreWalletFromPrivateKey extends WalletCredentials {
EthereumRestoreWalletFromPrivateKey(
{required String name,
required String password,
required this.privateKey,
WalletInfo? walletInfo})
: super(name: name, password: password, walletInfo: walletInfo);
final String wif;
final String privateKey;
}

View file

@ -13,7 +13,7 @@ import 'package:bip39/bip39.dart' as bip39;
import 'package:collection/collection.dart';
class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromWIFCredentials> {
EthereumRestoreWalletFromSeedCredentials, EthereumRestoreWalletFromPrivateKey> {
EthereumWalletService(this.walletInfoSource);
final Box<WalletInfo> walletInfoSource;
@ -66,8 +66,18 @@ class EthereumWalletService extends WalletService<EthereumNewWalletCredentials,
}
@override
Future<EthereumWallet> restoreFromKeys(credentials) {
throw UnimplementedError();
Future<EthereumWallet> restoreFromKeys(EthereumRestoreWalletFromPrivateKey credentials) async {
final wallet = EthereumWallet(
password: credentials.password!,
privateKey: credentials.privateKey,
walletInfo: credentials.walletInfo!,
);
await wallet.init();
wallet.addInitialTokens();
await wallet.save();
return wallet;
}
@override

View file

@ -12,13 +12,14 @@ environment:
dependencies:
flutter:
sdk: flutter
web3dart: 2.3.5
web3dart: ^2.7.1
erc20: ^1.0.1
mobx: ^2.0.7+4
bip39: ^1.0.6
bip32: ^2.0.0
ed25519_hd_key: ^2.2.0
hex: ^0.2.0
http: ^0.13.4
http: ^1.1.0
shared_preferences: ^2.0.15
cw_core:
path: ../cw_core

View file

@ -13,11 +13,11 @@ dependencies:
flutter:
sdk: flutter
ffi: ^2.0.1
http: ^0.13.4
http: ^1.1.0
path_provider: ^2.0.11
mobx: ^2.0.7+4
flutter_mobx: ^2.0.6+1
intl: ^0.17.0
intl: ^0.18.0
cw_core:
path: ../cw_core

View file

@ -399,5 +399,5 @@ packages:
source: hosted
version: "0.2.0+3"
sdks:
dart: ">=2.18.1 <4.0.0"
dart: ">=2.18.1 <3.0.0"
flutter: ">=3.0.0"

View file

@ -6,6 +6,7 @@
#include <fstream>
#include <unistd.h>
#include <mutex>
#include <list>
#include "thread"
#include "CwWalletListener.h"
#if __APPLE__
@ -182,6 +183,62 @@ extern "C"
}
};
struct CoinsInfoRow
{
uint64_t blockHeight;
char *hash;
uint64_t internalOutputIndex;
uint64_t globalOutputIndex;
bool spent;
bool frozen;
uint64_t spentHeight;
uint64_t amount;
bool rct;
bool keyImageKnown;
uint64_t pkIndex;
uint32_t subaddrIndex;
uint32_t subaddrAccount;
char *address;
char *addressLabel;
char *keyImage;
uint64_t unlockTime;
bool unlocked;
char *pubKey;
bool coinbase;
char *description;
CoinsInfoRow(Monero::CoinsInfo *coinsInfo)
{
blockHeight = coinsInfo->blockHeight();
std::string *hash_str = new std::string(coinsInfo->hash());
hash = strdup(hash_str->c_str());
internalOutputIndex = coinsInfo->internalOutputIndex();
globalOutputIndex = coinsInfo->globalOutputIndex();
spent = coinsInfo->spent();
frozen = coinsInfo->frozen();
spentHeight = coinsInfo->spentHeight();
amount = coinsInfo->amount();
rct = coinsInfo->rct();
keyImageKnown = coinsInfo->keyImageKnown();
pkIndex = coinsInfo->pkIndex();
subaddrIndex = coinsInfo->subaddrIndex();
subaddrAccount = coinsInfo->subaddrAccount();
address = strdup(coinsInfo->address().c_str()) ;
addressLabel = strdup(coinsInfo->addressLabel().c_str());
keyImage = strdup(coinsInfo->keyImage().c_str());
unlockTime = coinsInfo->unlockTime();
unlocked = coinsInfo->unlocked();
pubKey = strdup(coinsInfo->pubKey().c_str());
coinbase = coinsInfo->coinbase();
description = strdup(coinsInfo->description().c_str());
}
void setUnlocked(bool unlocked);
};
Monero::Coins *m_coins;
Monero::Wallet *m_wallet;
Monero::TransactionHistory *m_transaction_history;
MoneroWalletListener *m_listener;
@ -189,6 +246,7 @@ extern "C"
Monero::SubaddressAccount *m_account;
uint64_t m_last_known_wallet_height;
uint64_t m_cached_syncing_blockchain_height = 0;
std::list<Monero::CoinsInfo*> m_coins_info;
std::mutex store_lock;
bool is_storing = false;
@ -224,6 +282,17 @@ extern "C"
{
m_subaddress = nullptr;
}
m_coins_info = std::list<Monero::CoinsInfo*>();
if (wallet != nullptr)
{
m_coins = wallet->coins();
}
else
{
m_coins = nullptr;
}
}
Monero::Wallet *get_current_wallet()
@ -487,9 +556,18 @@ extern "C"
}
bool transaction_create(char *address, char *payment_id, char *amount,
uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction)
uint8_t priority_raw, uint32_t subaddr_account,
char **preferred_inputs, uint32_t preferred_inputs_size,
Utf8Box &error, PendingTransactionRaw &pendingTransaction)
{
nice(19);
std::set<std::string> _preferred_inputs;
for (int i = 0; i < preferred_inputs_size; i++) {
_preferred_inputs.insert(std::string(*preferred_inputs));
preferred_inputs++;
}
auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
std::string _payment_id;
@ -503,11 +581,11 @@ extern "C"
if (amount != nullptr)
{
uint64_t _amount = Monero::Wallet::amountFromString(std::string(amount));
transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account);
transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs);
}
else
{
transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account);
transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional<uint64_t>(), m_wallet->defaultMixin(), priority, subaddr_account, {}, _preferred_inputs);
}
int status = transaction->status();
@ -527,7 +605,9 @@ extern "C"
}
bool transaction_create_mult_dest(char **addresses, char *payment_id, char **amounts, uint32_t size,
uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction)
uint8_t priority_raw, uint32_t subaddr_account,
char **preferred_inputs, uint32_t preferred_inputs_size,
Utf8Box &error, PendingTransactionRaw &pendingTransaction)
{
nice(19);
@ -541,6 +621,13 @@ extern "C"
amounts++;
}
std::set<std::string> _preferred_inputs;
for (int i = 0; i < preferred_inputs_size; i++) {
_preferred_inputs.insert(std::string(*preferred_inputs));
preferred_inputs++;
}
auto priority = static_cast<Monero::PendingTransaction::Priority>(priority_raw);
std::string _payment_id;
Monero::PendingTransaction *transaction;
@ -800,6 +887,91 @@ extern "C"
return m_wallet->trustedDaemon();
}
CoinsInfoRow* coin(int index)
{
if (index >= 0 && index < m_coins_info.size()) {
std::list<Monero::CoinsInfo*>::iterator it = m_coins_info.begin();
std::advance(it, index);
Monero::CoinsInfo* element = *it;
std::cout << "Element at index " << index << ": " << element << std::endl;
return new CoinsInfoRow(element);
} else {
std::cout << "Invalid index." << std::endl;
return nullptr; // Return a default value (nullptr) for invalid index
}
}
void refresh_coins(uint32_t accountIndex)
{
m_coins_info.clear();
m_coins->refresh();
for (const auto i : m_coins->getAll()) {
if (i->subaddrAccount() == accountIndex && !(i->spent())) {
m_coins_info.push_back(i);
}
}
}
uint64_t coins_count()
{
return m_coins_info.size();
}
CoinsInfoRow** coins_from_account(uint32_t accountIndex)
{
std::vector<CoinsInfoRow*> matchingCoins;
for (int i = 0; i < coins_count(); i++) {
CoinsInfoRow* coinInfo = coin(i);
if (coinInfo->subaddrAccount == accountIndex) {
matchingCoins.push_back(coinInfo);
}
}
CoinsInfoRow** result = new CoinsInfoRow*[matchingCoins.size()];
std::copy(matchingCoins.begin(), matchingCoins.end(), result);
return result;
}
CoinsInfoRow** coins_from_txid(const char* txid, size_t* count)
{
std::vector<CoinsInfoRow*> matchingCoins;
for (int i = 0; i < coins_count(); i++) {
CoinsInfoRow* coinInfo = coin(i);
if (std::string(coinInfo->hash) == txid) {
matchingCoins.push_back(coinInfo);
}
}
*count = matchingCoins.size();
CoinsInfoRow** result = new CoinsInfoRow*[*count];
std::copy(matchingCoins.begin(), matchingCoins.end(), result);
return result;
}
CoinsInfoRow** coins_from_key_image(const char** keyimages, size_t keyimageCount, size_t* count)
{
std::vector<CoinsInfoRow*> matchingCoins;
for (int i = 0; i < coins_count(); i++) {
CoinsInfoRow* coinsInfoRow = coin(i);
for (size_t j = 0; j < keyimageCount; j++) {
if (coinsInfoRow->keyImageKnown && std::string(coinsInfoRow->keyImage) == keyimages[j]) {
matchingCoins.push_back(coinsInfoRow);
break;
}
}
}
*count = matchingCoins.size();
CoinsInfoRow** result = new CoinsInfoRow*[*count];
std::copy(matchingCoins.begin(), matchingCoins.end(), result);
return result;
}
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,23 @@
import 'dart:ffi';
import 'package:cw_monero/api/signatures.dart';
import 'package:cw_monero/api/structs/coins_info_row.dart';
import 'package:cw_monero/api/types.dart';
import 'package:cw_monero/api/monero_api.dart';
final refreshCoinsNative = moneroApi
.lookup<NativeFunction<refresh_coins>>('refresh_coins')
.asFunction<RefreshCoins>();
final coinsCountNative = moneroApi
.lookup<NativeFunction<coins_count>>('coins_count')
.asFunction<CoinsCount>();
final coinNative = moneroApi
.lookup<NativeFunction<coin>>('coin')
.asFunction<GetCoin>();
void refreshCoins(int accountIndex) => refreshCoinsNative(accountIndex);
int countOfCoins() => coinsCountNative();
CoinsInfoRow getCoin(int index) => coinNative(index).ref;

View file

@ -1,4 +1,5 @@
import 'dart:ffi';
import 'package:cw_monero/api/structs/coins_info_row.dart';
import 'package:cw_monero/api/structs/pending_transaction.dart';
import 'package:cw_monero/api/structs/ut8_box.dart';
import 'package:ffi/ffi.dart';
@ -9,8 +10,8 @@ typedef create_wallet = Int8 Function(
typedef restore_wallet_from_seed = Int8 Function(
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
typedef restore_wallet_from_keys = Int8 Function(Pointer<Utf8>, Pointer<Utf8>,
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
typedef restore_wallet_from_keys = Int8 Function(Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>,
Pointer<Utf8>, Pointer<Utf8>, Pointer<Utf8>, Int32, Int64, Pointer<Utf8>);
typedef is_wallet_exist = Int8 Function(Pointer<Utf8>);
@ -63,8 +64,7 @@ typedef subaddrress_refresh = Void Function(Int32);
typedef subaddress_get_all = Pointer<Int64> Function();
typedef subaddress_add_new = Void Function(
Int32 accountIndex, Pointer<Utf8> label);
typedef subaddress_add_new = Void Function(Int32 accountIndex, Pointer<Utf8> label);
typedef subaddress_set_label = Void Function(
Int32 accountIndex, Int32 addressIndex, Pointer<Utf8> label);
@ -77,8 +77,7 @@ typedef account_get_all = Pointer<Int64> Function();
typedef account_add_new = Void Function(Pointer<Utf8> label);
typedef account_set_label = Void Function(
Int32 accountIndex, Pointer<Utf8> label);
typedef account_set_label = Void Function(Int32 accountIndex, Pointer<Utf8> label);
typedef transactions_refresh = Void Function();
@ -94,6 +93,8 @@ typedef transaction_create = Int8 Function(
Pointer<Utf8> amount,
Int8 priorityRaw,
Int32 subaddrAccount,
Pointer<Pointer<Utf8>> preferredInputs,
Int32 preferredInputsSize,
Pointer<Utf8Box> error,
Pointer<PendingTransactionRaw> pendingTransaction);
@ -104,6 +105,8 @@ typedef transaction_create_mult_dest = Int8 Function(
Int32 size,
Int8 priorityRaw,
Int32 subaddrAccount,
Pointer<Pointer<Utf8>> preferredInputs,
Int32 preferredInputsSize,
Pointer<Utf8Box> error,
Pointer<PendingTransactionRaw> pendingTransaction);
@ -123,10 +126,16 @@ typedef on_startup = Void Function();
typedef rescan_blockchain = Void Function();
typedef get_subaddress_label = Pointer<Utf8> Function(
Int32 accountIndex,
Int32 addressIndex);
typedef get_subaddress_label = Pointer<Utf8> Function(Int32 accountIndex, Int32 addressIndex);
typedef set_trusted_daemon = Void Function(Int8 trusted);
typedef trusted_daemon = Int8 Function();
typedef trusted_daemon = Int8 Function();
typedef refresh_coins = Void Function(Int32 accountIndex);
typedef coins_count = Int64 Function();
// typedef coins_from_txid = Pointer<CoinsInfoRow> Function(Pointer<Utf8> txid);
typedef coin = Pointer<CoinsInfoRow> Function(Int32 index);

View file

@ -0,0 +1,73 @@
import 'dart:ffi';
import 'package:ffi/ffi.dart';
class CoinsInfoRow extends Struct {
@Int64()
external int blockHeight;
external Pointer<Utf8> hash;
@Uint64()
external int internalOutputIndex;
@Uint64()
external int globalOutputIndex;
@Int8()
external int spent;
@Int8()
external int frozen;
@Uint64()
external int spentHeight;
@Uint64()
external int amount;
@Int8()
external int rct;
@Int8()
external int keyImageKnown;
@Uint64()
external int pkIndex;
@Uint32()
external int subaddrIndex;
@Uint32()
external int subaddrAccount;
external Pointer<Utf8> address;
external Pointer<Utf8> addressLabel;
external Pointer<Utf8> keyImage;
@Uint64()
external int unlockTime;
@Int8()
external int unlocked;
external Pointer<Utf8> pubKey;
@Int8()
external int coinbase;
external Pointer<Utf8> description;
String getHash() => hash.toDartString();
String getAddress() => address.toDartString();
String getAddressLabel() => addressLabel.toDartString();
String getKeyImage() => keyImage.toDartString();
String getPubKey() => pubKey.toDartString();
String getDescription() => description.toDartString();
}

View file

@ -35,9 +35,8 @@ final transactionCommitNative = moneroApi
.lookup<NativeFunction<transaction_commit>>('transaction_commit')
.asFunction<TransactionCommit>();
final getTxKeyNative = moneroApi
.lookup<NativeFunction<get_tx_key>>('get_tx_key')
.asFunction<GetTxKey>();
final getTxKeyNative =
moneroApi.lookup<NativeFunction<get_tx_key>>('get_tx_key').asFunction<GetTxKey>();
String getTxKey(String txId) {
final txIdPointer = txId.toNativeUtf8();
@ -71,10 +70,21 @@ PendingTransactionDescription createTransactionSync(
required String paymentId,
required int priorityRaw,
String? amount,
int accountIndex = 0}) {
int accountIndex = 0,
List<String> preferredInputs = const []}) {
final addressPointer = address.toNativeUtf8();
final paymentIdPointer = paymentId.toNativeUtf8();
final amountPointer = amount != null ? amount.toNativeUtf8() : nullptr;
final int preferredInputsSize = preferredInputs.length;
final List<Pointer<Utf8>> preferredInputsPointers =
preferredInputs.map((output) => output.toNativeUtf8()).toList();
final Pointer<Pointer<Utf8>> preferredInputsPointerPointer = calloc(preferredInputsSize);
for (int i = 0; i < preferredInputsSize; i++) {
preferredInputsPointerPointer[i] = preferredInputsPointers[i];
}
final errorMessagePointer = calloc<Utf8Box>();
final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
final created = transactionCreateNative(
@ -83,10 +93,16 @@ PendingTransactionDescription createTransactionSync(
amountPointer,
priorityRaw,
accountIndex,
preferredInputsPointerPointer,
preferredInputsSize,
errorMessagePointer,
pendingTransactionRawPointer) !=
0;
calloc.free(preferredInputsPointerPointer);
preferredInputsPointers.forEach((element) => calloc.free(element));
calloc.free(addressPointer);
calloc.free(paymentIdPointer);
@ -111,15 +127,16 @@ PendingTransactionDescription createTransactionSync(
PendingTransactionDescription createTransactionMultDestSync(
{required List<MoneroOutput> outputs,
required String paymentId,
required int priorityRaw,
int accountIndex = 0}) {
required String paymentId,
required int priorityRaw,
int accountIndex = 0,
List<String> preferredInputs = const []}) {
final int size = outputs.length;
final List<Pointer<Utf8>> addressesPointers = outputs.map((output) =>
output.address.toNativeUtf8()).toList();
final List<Pointer<Utf8>> addressesPointers =
outputs.map((output) => output.address.toNativeUtf8()).toList();
final Pointer<Pointer<Utf8>> addressesPointerPointer = calloc(size);
final List<Pointer<Utf8>> amountsPointers = outputs.map((output) =>
output.amount.toNativeUtf8()).toList();
final List<Pointer<Utf8>> amountsPointers =
outputs.map((output) => output.amount.toNativeUtf8()).toList();
final Pointer<Pointer<Utf8>> amountsPointerPointer = calloc(size);
for (int i = 0; i < size; i++) {
@ -127,25 +144,38 @@ PendingTransactionDescription createTransactionMultDestSync(
amountsPointerPointer[i] = amountsPointers[i];
}
final int preferredInputsSize = preferredInputs.length;
final List<Pointer<Utf8>> preferredInputsPointers =
preferredInputs.map((output) => output.toNativeUtf8()).toList();
final Pointer<Pointer<Utf8>> preferredInputsPointerPointer = calloc(preferredInputsSize);
for (int i = 0; i < preferredInputsSize; i++) {
preferredInputsPointerPointer[i] = preferredInputsPointers[i];
}
final paymentIdPointer = paymentId.toNativeUtf8();
final errorMessagePointer = calloc<Utf8Box>();
final pendingTransactionRawPointer = calloc<PendingTransactionRaw>();
final created = transactionCreateMultDestNative(
addressesPointerPointer,
paymentIdPointer,
amountsPointerPointer,
size,
priorityRaw,
accountIndex,
errorMessagePointer,
pendingTransactionRawPointer) !=
addressesPointerPointer,
paymentIdPointer,
amountsPointerPointer,
size,
priorityRaw,
accountIndex,
preferredInputsPointerPointer,
preferredInputsSize,
errorMessagePointer,
pendingTransactionRawPointer) !=
0;
calloc.free(addressesPointerPointer);
calloc.free(amountsPointerPointer);
calloc.free(preferredInputsPointerPointer);
addressesPointers.forEach((element) => calloc.free(element));
amountsPointers.forEach((element) => calloc.free(element));
preferredInputsPointers.forEach((element) => calloc.free(element));
calloc.free(paymentIdPointer);
@ -164,13 +194,12 @@ PendingTransactionDescription createTransactionMultDestSync(
pointerAddress: pendingTransactionRawPointer.address);
}
void commitTransactionFromPointerAddress({required int address}) => commitTransaction(
transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address));
void commitTransactionFromPointerAddress({required int address}) =>
commitTransaction(transactionPointer: Pointer<PendingTransactionRaw>.fromAddress(address));
void commitTransaction({required Pointer<PendingTransactionRaw> transactionPointer}) {
final errorMessagePointer = calloc<Utf8Box>();
final isCommited =
transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
final isCommited = transactionCommitNative(transactionPointer, errorMessagePointer) != 0;
if (!isCommited) {
final message = errorMessagePointer.ref.getValue();
@ -185,13 +214,15 @@ PendingTransactionDescription _createTransactionSync(Map args) {
final amount = args['amount'] as String?;
final priorityRaw = args['priorityRaw'] as int;
final accountIndex = args['accountIndex'] as int;
final preferredInputs = args['preferredInputs'] as List<String>;
return createTransactionSync(
address: address,
paymentId: paymentId,
amount: amount,
priorityRaw: priorityRaw,
accountIndex: accountIndex);
accountIndex: accountIndex,
preferredInputs: preferredInputs);
}
PendingTransactionDescription _createTransactionMultDestSync(Map args) {
@ -199,12 +230,14 @@ PendingTransactionDescription _createTransactionMultDestSync(Map args) {
final paymentId = args['paymentId'] as String;
final priorityRaw = args['priorityRaw'] as int;
final accountIndex = args['accountIndex'] as int;
final preferredInputs = args['preferredInputs'] as List<String>;
return createTransactionMultDestSync(
outputs: outputs,
paymentId: paymentId,
priorityRaw: priorityRaw,
accountIndex: accountIndex);
accountIndex: accountIndex,
preferredInputs: preferredInputs);
}
Future<PendingTransactionDescription> createTransaction(
@ -212,23 +245,27 @@ Future<PendingTransactionDescription> createTransaction(
required int priorityRaw,
String? amount,
String paymentId = '',
int accountIndex = 0}) =>
int accountIndex = 0,
List<String> preferredInputs = const []}) =>
compute(_createTransactionSync, {
'address': address,
'paymentId': paymentId,
'amount': amount,
'priorityRaw': priorityRaw,
'accountIndex': accountIndex
'accountIndex': accountIndex,
'preferredInputs': preferredInputs
});
Future<PendingTransactionDescription> createTransactionMultDest(
{required List<MoneroOutput> outputs,
required int priorityRaw,
String paymentId = '',
int accountIndex = 0}) =>
{required List<MoneroOutput> outputs,
required int priorityRaw,
String paymentId = '',
int accountIndex = 0,
List<String> preferredInputs = const []}) =>
compute(_createTransactionMultDestSync, {
'outputs': outputs,
'paymentId': paymentId,
'priorityRaw': priorityRaw,
'accountIndex': accountIndex
'accountIndex': accountIndex,
'preferredInputs': preferredInputs
});

View file

@ -1,4 +1,5 @@
import 'dart:ffi';
import 'package:cw_monero/api/structs/coins_info_row.dart';
import 'package:cw_monero/api/structs/pending_transaction.dart';
import 'package:cw_monero/api/structs/ut8_box.dart';
import 'package:ffi/ffi.dart';
@ -92,6 +93,8 @@ typedef TransactionCreate = int Function(
Pointer<Utf8> amount,
int priorityRaw,
int subaddrAccount,
Pointer<Pointer<Utf8>> preferredInputs,
int preferredInputsSize,
Pointer<Utf8Box> error,
Pointer<PendingTransactionRaw> pendingTransaction);
@ -102,6 +105,8 @@ typedef TransactionCreateMultDest = int Function(
int size,
int priorityRaw,
int subaddrAccount,
Pointer<Pointer<Utf8>> preferredInputs,
int preferredInputsSize,
Pointer<Utf8Box> error,
Pointer<PendingTransactionRaw> pendingTransaction);
@ -127,4 +132,10 @@ typedef GetSubaddressLabel = Pointer<Utf8> Function(
typedef SetTrustedDaemon = void Function(int);
typedef TrustedDaemon = int Function();
typedef TrustedDaemon = int Function();
typedef RefreshCoins = void Function(int);
typedef CoinsCount = int Function();
typedef GetCoin = Pointer<CoinsInfoRow> Function(int);

View file

@ -0,0 +1,4 @@
class MoneroTransactionNoInputsException implements Exception {
@override
String toString() => 'Not enough inputs available. Please select more under Coin Control';
}

View file

@ -1,6 +1,6 @@
import 'package:cw_monero/api/structs/subaddress_row.dart';
import 'package:flutter/services.dart';
import 'package:mobx/mobx.dart';
import 'package:cw_monero/api/coins_info.dart';
import 'package:cw_monero/api/subaddress_list.dart' as subaddress_list;
import 'package:cw_core/subaddress.dart';
@ -22,6 +22,8 @@ abstract class MoneroSubaddressListBase with Store {
bool _isUpdating;
void update({required int accountIndex}) {
refreshCoins(accountIndex);
if (_isUpdating) {
return;
}

View file

@ -0,0 +1,28 @@
import 'package:cw_monero/api/structs/coins_info_row.dart';
class MoneroUnspent {
MoneroUnspent(this.address, this.hash, this.keyImage, this.value, this.isFrozen, this.isUnlocked)
: isSending = true,
note = '';
MoneroUnspent.fromCoinsInfoRow(CoinsInfoRow coinsInfoRow)
: address = coinsInfoRow.getAddress(),
hash = coinsInfoRow.getHash(),
keyImage = coinsInfoRow.getKeyImage(),
value = coinsInfoRow.amount,
isFrozen = coinsInfoRow.frozen == 1,
isUnlocked = coinsInfoRow.unlocked == 1,
isSending = true,
note = '';
final String address;
final String hash;
final String keyImage;
final int value;
final bool isUnlocked;
bool isFrozen;
bool isSending;
String note;
}

View file

@ -1,33 +1,35 @@
import 'dart:async';
import 'dart:io';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_monero/monero_transaction_creation_exception.dart';
import 'package:cw_monero/monero_transaction_info.dart';
import 'package:cw_monero/monero_wallet_addresses.dart';
import 'package:cw_core/monero_wallet_utils.dart';
import 'package:cw_monero/api/structs/pending_transaction.dart';
import 'package:mobx/mobx.dart';
import 'package:cw_monero/api/transaction_history.dart'
as monero_transaction_history;
import 'package:cw_monero/api/wallet.dart';
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
import 'package:cw_monero/api/transaction_history.dart' as transaction_history;
import 'package:cw_monero/api/monero_output.dart';
import 'package:cw_monero/monero_transaction_creation_credentials.dart';
import 'package:cw_monero/pending_monero_transaction.dart';
import 'package:cw_core/monero_wallet_keys.dart';
import 'package:cw_core/monero_balance.dart';
import 'package:cw_monero/monero_transaction_history.dart';
import 'package:cw_core/account.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/monero_transaction_priority.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/monero_amount_format.dart';
import 'package:cw_core/monero_balance.dart';
import 'package:cw_core/monero_transaction_priority.dart';
import 'package:cw_core/monero_wallet_keys.dart';
import 'package:cw_core/monero_wallet_utils.dart';
import 'package:cw_core/node.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/sync_status.dart';
import 'package:cw_core/transaction_priority.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_monero/api/coins_info.dart';
import 'package:cw_monero/api/monero_output.dart';
import 'package:cw_monero/api/structs/pending_transaction.dart';
import 'package:cw_monero/api/transaction_history.dart' as transaction_history;
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
import 'package:cw_monero/exceptions/monero_transaction_creation_exception.dart';
import 'package:cw_monero/exceptions/monero_transaction_no_inputs_exception.dart';
import 'package:cw_monero/pending_monero_transaction.dart';
import 'package:cw_monero/monero_transaction_creation_credentials.dart';
import 'package:cw_monero/monero_transaction_history.dart';
import 'package:cw_monero/monero_transaction_info.dart';
import 'package:cw_monero/monero_unspent.dart';
import 'package:cw_monero/monero_wallet_addresses.dart';
import 'package:mobx/mobx.dart';
import 'package:hive/hive.dart';
part 'monero_wallet.g.dart';
@ -37,37 +39,39 @@ class MoneroWallet = MoneroWalletBase with _$MoneroWallet;
abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
MoneroTransactionHistory, MoneroTransactionInfo> with Store {
MoneroWalletBase({required WalletInfo walletInfo})
MoneroWalletBase({required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo})
: balance = ObservableMap<CryptoCurrency, MoneroBalance>.of({
CryptoCurrency.xmr: MoneroBalance(
CryptoCurrency.xmr: MoneroBalance(
fullBalance: monero_wallet.getFullBalance(accountIndex: 0),
unlockedBalance: monero_wallet.getFullBalance(accountIndex: 0))
}),
}),
_isTransactionUpdating = false,
_hasSyncAfterStartup = false,
walletAddresses = MoneroWalletAddresses(walletInfo),
syncStatus = NotConnectedSyncStatus(),
unspentCoins = [],
this.unspentCoinsInfo = unspentCoinsInfo,
super(walletInfo) {
transactionHistory = MoneroTransactionHistory();
_onAccountChangeReaction = reaction((_) => walletAddresses.account,
(Account? account) {
_onAccountChangeReaction = reaction((_) => walletAddresses.account, (Account? account) {
if (account == null) {
return;
}
balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(
<CryptoCurrency, MoneroBalance>{
currency: MoneroBalance(
balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(<CryptoCurrency, MoneroBalance>{
currency: MoneroBalance(
fullBalance: monero_wallet.getFullBalance(accountIndex: account.id),
unlockedBalance:
monero_wallet.getUnlockedBalance(accountIndex: account.id))
});
unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: account.id))
});
walletAddresses.updateSubaddressList(accountIndex: account.id);
});
}
static const int _autoSaveInterval = 30;
Box<UnspentCoinsInfo> unspentCoinsInfo;
@override
MoneroWalletAddresses walletAddresses;
@ -89,11 +93,12 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
publicSpendKey: monero_wallet.getPublicSpendKey(),
publicViewKey: monero_wallet.getPublicViewKey());
SyncListener? _listener;
monero_wallet.SyncListener? _listener;
ReactionDisposer? _onAccountChangeReaction;
bool _isTransactionUpdating;
bool _hasSyncAfterStartup;
Timer? _autoSaveTimer;
List<MoneroUnspent> unspentCoins;
Future<void> init() async {
await walletAddresses.init();
@ -170,10 +175,12 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
@override
Future<PendingTransaction> createTransaction(Object credentials) async {
final _credentials = credentials as MoneroTransactionCreationCredentials;
final inputs = <String>[];
final outputs = _credentials.outputs;
final hasMultiDestination = outputs.length > 1;
final unlockedBalance =
monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id);
var allInputsAmount = 0;
PendingTransactionDescription pendingTransactionDescription;
@ -181,6 +188,21 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
throw MoneroTransactionCreationException('The wallet is not synced.');
}
if (unspentCoins.isEmpty) {
await updateUnspent();
}
for (final utx in unspentCoins) {
if (utx.isSending) {
allInputsAmount += utx.value;
inputs.add(utx.keyImage);
}
}
if (inputs.isEmpty) {
throw MoneroTransactionNoInputsException();
}
if (hasMultiDestination) {
if (outputs.any((item) => item.sendAll
|| (item.formattedCryptoAmount ?? 0) <= 0)) {
@ -208,7 +230,8 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
await transaction_history.createTransactionMultDest(
outputs: moneroOutputs,
priorityRaw: _credentials.priority.serialize(),
accountIndex: walletAddresses.account!.id);
accountIndex: walletAddresses.account!.id,
preferredInputs: inputs);
} else {
final output = outputs.first;
final address = output.isParsedAddress
@ -229,12 +252,12 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
'You do not have enough unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${output.cryptoAmount}.');
}
pendingTransactionDescription =
await transaction_history.createTransaction(
pendingTransactionDescription = await transaction_history.createTransaction(
address: address!,
amount: amount,
priorityRaw: _credentials.priority.serialize(),
accountIndex: walletAddresses.account!.id);
accountIndex: walletAddresses.account!.id,
preferredInputs: inputs);
}
return PendingMoneroTransaction(pendingTransactionDescription);
@ -354,6 +377,85 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
await walletInfo.save();
}
Future<void> updateUnspent() async {
refreshCoins(walletAddresses.account!.id);
unspentCoins.clear();
final coinCount = countOfCoins();
for (var i = 0; i < coinCount; i++) {
final coin = getCoin(i);
if (coin.spent == 0) {
unspentCoins.add(MoneroUnspent.fromCoinsInfoRow(coin));
}
}
if (unspentCoinsInfo.isEmpty) {
unspentCoins.forEach((coin) => _addCoinInfo(coin));
return;
}
if (unspentCoins.isNotEmpty) {
unspentCoins.forEach((coin) {
final coinInfoList = unspentCoinsInfo.values.where((element) =>
element.walletId.contains(id) && element.hash.contains(coin.hash));
if (coinInfoList.isNotEmpty) {
final coinInfo = coinInfoList.first;
coin.isFrozen = coinInfo.isFrozen;
coin.isSending = coinInfo.isSending;
coin.note = coinInfo.note;
} else {
_addCoinInfo(coin);
}
});
}
await _refreshUnspentCoinsInfo();
_askForUpdateBalance();
}
Future<void> _addCoinInfo(MoneroUnspent coin) async {
final newInfo = UnspentCoinsInfo(
walletId: id,
hash: coin.hash,
isFrozen: coin.isFrozen,
isSending: coin.isSending,
noteRaw: coin.note,
address: coin.address,
value: coin.value,
vout: 0,
keyImage: coin.keyImage
);
await unspentCoinsInfo.add(newInfo);
}
Future<void> _refreshUnspentCoinsInfo() async {
try {
final List<dynamic> keys = <dynamic>[];
final currentWalletUnspentCoins = unspentCoinsInfo.values
.where((element) => element.walletId.contains(id));
if (currentWalletUnspentCoins.isNotEmpty) {
currentWalletUnspentCoins.forEach((element) {
final existUnspentCoins = unspentCoins.where((coin) => element.hash.contains(coin.hash));
if (existUnspentCoins.isEmpty) {
keys.add(element.key);
}
});
}
if (keys.isNotEmpty) {
await unspentCoinsInfo.deleteAll(keys);
}
} catch (e) {
print(e.toString());
}
}
String getTransactionAddress(int accountIndex, int addressIndex) =>
monero_wallet.getAddress(
accountIndex: accountIndex,
@ -361,7 +463,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
@override
Future<Map<String, MoneroTransactionInfo>> fetchTransactions() async {
monero_transaction_history.refreshTransactions();
transaction_history.refreshTransactions();
return _getAllTransactions(null).fold<Map<String, MoneroTransactionInfo>>(
<String, MoneroTransactionInfo>{},
(Map<String, MoneroTransactionInfo> acc, MoneroTransactionInfo tx) {
@ -392,7 +494,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
}
List<MoneroTransactionInfo> _getAllTransactions(dynamic _) =>
monero_transaction_history
transaction_history
.getAllTransations()
.map((row) => MoneroTransactionInfo.fromRow(row))
.toList();
@ -407,7 +509,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
return;
}
final currentHeight = getCurrentHeight();
final currentHeight = monero_wallet.getCurrentHeight();
if (currentHeight <= 1) {
final height = _getHeightByDate(walletInfo.date);
@ -439,11 +541,13 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
void _askForUpdateBalance() {
final unlockedBalance = _getUnlockedBalance();
final fullBalance = _getFullBalance();
final frozenBalance = _getFrozenBalance();
if (balance[currency]!.fullBalance != fullBalance ||
balance[currency]!.unlockedBalance != unlockedBalance) {
balance[currency]!.unlockedBalance != unlockedBalance ||
balance[currency]!.frozenBalance != frozenBalance) {
balance[currency] = MoneroBalance(
fullBalance: fullBalance, unlockedBalance: unlockedBalance);
fullBalance: fullBalance, unlockedBalance: unlockedBalance, frozenBalance: frozenBalance);
}
}
@ -456,6 +560,17 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
int _getUnlockedBalance() =>
monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id);
int _getFrozenBalance() {
var frozenBalance = 0;
for (var coin in unspentCoinsInfo.values) {
if (coin.isFrozen)
frozenBalance += coin.value;
}
return frozenBalance;
}
void _onNewBlock(int height, int blocksLeft, double ptc) async {
try {
if (walletInfo.isRecovery) {

View file

@ -1,16 +1,16 @@
import 'dart:io';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/monero_wallet_utils.dart';
import 'package:hive/hive.dart';
import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager;
import 'package:cw_monero/api/wallet.dart' as monero_wallet;
import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
import 'package:cw_monero/monero_wallet.dart';
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/pathForWallet.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_credentials.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_service.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cw_monero/api/exceptions/wallet_opening_exception.dart';
import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager;
import 'package:cw_monero/monero_wallet.dart';
import 'package:hive/hive.dart';
class MoneroNewWalletCredentials extends WalletCredentials {
MoneroNewWalletCredentials({required String name, required this.language, String? password})
@ -53,9 +53,10 @@ class MoneroWalletService extends WalletService<
MoneroNewWalletCredentials,
MoneroRestoreWalletFromSeedCredentials,
MoneroRestoreWalletFromKeysCredentials> {
MoneroWalletService(this.walletInfoSource);
MoneroWalletService(this.walletInfoSource, this.unspentCoinsInfoSource);
final Box<WalletInfo> walletInfoSource;
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
static bool walletFilesExist(String path) =>
!File(path).existsSync() && !File('$path.keys').existsSync();
@ -71,7 +72,8 @@ class MoneroWalletService extends WalletService<
path: path,
password: credentials.password!,
language: credentials.language);
final wallet = MoneroWallet(walletInfo: credentials.walletInfo!);
final wallet = MoneroWallet(
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.init();
return wallet;
@ -107,7 +109,7 @@ class MoneroWalletService extends WalletService<
.openWalletAsync({'path': path, 'password': password});
final walletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(name, getType()));
final wallet = MoneroWallet(walletInfo: walletInfo);
final wallet = MoneroWallet(walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
final isValid = wallet.walletAddresses.validate();
if (!isValid) {
@ -157,7 +159,8 @@ class MoneroWalletService extends WalletService<
String currentName, String password, String newName) async {
final currentWalletInfo = walletInfoSource.values.firstWhere(
(info) => info.id == WalletBase.idFor(currentName, getType()));
final currentWallet = MoneroWallet(walletInfo: currentWalletInfo);
final currentWallet =
MoneroWallet(walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource);
await currentWallet.renameWalletFiles(newName);
@ -181,7 +184,8 @@ class MoneroWalletService extends WalletService<
address: credentials.address,
viewKey: credentials.viewKey,
spendKey: credentials.spendKey);
final wallet = MoneroWallet(walletInfo: credentials.walletInfo!);
final wallet = MoneroWallet(
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.init();
return wallet;
@ -202,7 +206,8 @@ class MoneroWalletService extends WalletService<
password: credentials.password!,
seed: credentials.mnemonic,
restoreHeight: credentials.height!);
final wallet = MoneroWallet(walletInfo: credentials.walletInfo!);
final wallet = MoneroWallet(
walletInfo: credentials.walletInfo!, unspentCoinsInfo: unspentCoinsInfoSource);
await wallet.init();
return wallet;

View file

@ -672,5 +672,5 @@ packages:
source: hosted
version: "3.1.1"
sdks:
dart: ">=2.19.0 <4.0.0"
dart: ">=2.19.0 <3.0.0"
flutter: ">=3.0.0"

View file

@ -13,11 +13,11 @@ dependencies:
flutter:
sdk: flutter
ffi: ^2.0.1
http: ^0.13.4
http: ^1.1.0
path_provider: ^2.0.11
mobx: ^2.0.7+4
flutter_mobx: ^2.0.6+1
intl: ^0.17.0
intl: ^0.18.0
encrypt: ^5.0.1
cw_core:
path: ../cw_core

View file

@ -5,7 +5,7 @@ author: Cake Walelt
homepage: https://cakewallet.com
environment:
sdk: ">=2.7.0 <3.0.0"
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.20.0"
dependencies:

View file

@ -5,10 +5,10 @@
The following are the system requirements to build CakeWallet for your Android device.
```
Ubuntu >= 16.04
Ubuntu >= 20.04
Android SDK 29 or higher (better to have the latest one 33)
Android NDK 17c
Flutter 3.7.x
Flutter 3.10.x or earlier
```
## Building CakeWallet on Android
@ -66,7 +66,7 @@ Verify that the Android toolchain, Flutter, and Android Studio have been correct
The output of this command will appear like this, indicating successful installations. If there are problems with your installation, they **must** be corrected before proceeding.
```
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.7.x, on Linux, locale en_US.UTF-8)
[✓] Flutter (Channel stable, 3.10.x, on Linux, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 29 or higher)
[✓] Android Studio (version 4.0 or higher)
```

View file

@ -174,12 +174,12 @@ DEPENDENCIES:
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
- local_auth_ios (from `.symlinks/plugins/local_auth_ios/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- platform_device_id (from `.symlinks/plugins/platform_device_id/ios`)
- sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- uni_links (from `.symlinks/plugins/uni_links/ios`)
- UnstoppableDomainsResolution (~> 4.0.0)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
@ -236,7 +236,7 @@ EXTERNAL SOURCES:
package_info:
:path: ".symlinks/plugins/package_info/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
platform_device_id:
@ -246,7 +246,7 @@ EXTERNAL SOURCES:
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
uni_links:
:path: ".symlinks/plugins/uni_links/ios"
url_launcher_ios:

View file

@ -182,6 +182,8 @@ class AnonPayApi {
switch (currency) {
case CryptoCurrency.usdt:
return CryptoCurrency.btc.title.toLowerCase();
case CryptoCurrency.eth:
return 'ERC20';
default:
return currency.tag != null ? _normalizeTag(currency.tag!) : 'Mainnet';
}

View file

@ -137,7 +137,8 @@ class CWBitcoin extends Bitcoin {
bitcoinUnspent.address,
bitcoinUnspent.hash,
bitcoinUnspent.value,
bitcoinUnspent.vout))
bitcoinUnspent.vout,
null))
.toList();
}
@ -169,4 +170,4 @@ class CWBitcoin extends Bitcoin {
@override
TransactionPriority getLitecoinTransactionPrioritySlow()
=> LitecoinTransactionPriority.slow;
}
}

View file

@ -1,8 +1,10 @@
import 'package:cake_wallet/.secrets.g.dart' as secrets;
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:flutter/material.dart';
class OnRamperBuyProvider {
OnRamperBuyProvider({required SettingsStore settingsStore, required WalletBase wallet})
@ -27,7 +29,11 @@ class OnRamperBuyProvider {
}
}
Uri requestUrl() {
String getColorStr(Color color) {
return color.value.toRadixString(16).replaceAll(RegExp(r'^ff'), "");
}
Uri requestUrl(BuildContext context) {
String primaryColor,
secondaryColor,
primaryTextColor,
@ -35,31 +41,16 @@ class OnRamperBuyProvider {
containerColor,
cardColor;
switch (_settingsStore.currentTheme.type) {
case ThemeType.bright:
primaryColor = '815dfbff';
secondaryColor = 'ffffff';
primaryTextColor = '141519';
secondaryTextColor = '6b6f80';
containerColor = 'ffffff';
cardColor = 'f2f0faff';
break;
case ThemeType.light:
primaryColor = '2194ffff';
secondaryColor = 'ffffff';
primaryTextColor = '141519';
secondaryTextColor = '6b6f80';
containerColor = 'ffffff';
cardColor = 'e5f7ff';
break;
case ThemeType.dark:
primaryColor = '456effff';
secondaryColor = '1b2747ff';
primaryTextColor = 'ffffff';
secondaryTextColor = 'ffffff';
containerColor = '19233C';
cardColor = '232f4fff';
break;
primaryColor = getColorStr(Theme.of(context).primaryColor);
secondaryColor = getColorStr(Theme.of(context).colorScheme.background);
primaryTextColor = getColorStr(Theme.of(context).extension<CakeTextTheme>()!.titleColor);
secondaryTextColor =
getColorStr(Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor);
containerColor = getColorStr(Theme.of(context).colorScheme.background);
cardColor = getColorStr(Theme.of(context).cardColor);
if (_settingsStore.currentTheme.title == S.current.high_contrast_theme) {
cardColor = getColorStr(Colors.white);
}
final networkName = _wallet.currency.fullName?.toUpperCase().replaceAll(" ", "");

View file

@ -1,4 +1,3 @@
import 'package:uuid/uuid.dart';
import 'package:cw_core/key.dart';
String generateWalletPassword() {

View file

@ -178,8 +178,6 @@ import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart';
import 'package:cake_wallet/view_model/wallet_restoration_from_keys_vm.dart';
import 'package:cake_wallet/core/wallet_creation_service.dart';
import 'package:cake_wallet/store/app_store.dart';
import 'package:cw_core/wallet_type.dart';
@ -219,10 +217,10 @@ late Box<Template> _templates;
late Box<ExchangeTemplate> _exchangeTemplates;
late Box<TransactionDescription> _transactionDescriptionBox;
late Box<Order> _ordersSource;
late Box<UnspentCoinsInfo>? _unspentCoinsInfoSource;
late Box<UnspentCoinsInfo> _unspentCoinsInfoSource;
late Box<AnonpayInvoiceInfo> _anonpayInvoiceInfoSource;
Future setup({
Future<void> setup({
required Box<WalletInfo> walletInfoSource,
required Box<Node> nodeSource,
required Box<Contact> contactSource,
@ -231,7 +229,7 @@ Future setup({
required Box<ExchangeTemplate> exchangeTemplates,
required Box<TransactionDescription> transactionDescriptionBox,
required Box<Order> ordersSource,
Box<UnspentCoinsInfo>? unspentCoinsInfoSource,
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfoSource,
}) async {
_walletInfoSource = walletInfoSource;
@ -321,25 +319,6 @@ Future setup({
getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
type: type));
getIt.registerFactoryParam<WalletRestorationFromSeedVM, List, void>((args, _) {
final type = args.first as WalletType;
final language = args[1] as String;
final mnemonic = args[2] as String;
return WalletRestorationFromSeedVM(
getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
type: type, language: language, seed: mnemonic);
});
getIt.registerFactoryParam<WalletRestorationFromKeysVM, List, void>((args, _) {
final type = args.first as WalletType;
final language = args[1] as String;
return WalletRestorationFromKeysVM(
getIt.get<AppStore>(), getIt.get<WalletCreationService>(param1: type), _walletInfoSource,
type: type, language: language);
});
getIt.registerFactoryParam<WalletRestorationFromQRVM, WalletType, void>((WalletType type, _) {
return WalletRestorationFromQRVM(getIt.get<AppStore>(),
getIt.get<WalletCreationService>(param1: type), _walletInfoSource, type);
@ -753,11 +732,11 @@ Future setup({
case WalletType.haven:
return haven!.createHavenWalletService(_walletInfoSource);
case WalletType.monero:
return monero!.createMoneroWalletService(_walletInfoSource);
return monero!.createMoneroWalletService(_walletInfoSource, _unspentCoinsInfoSource);
case WalletType.bitcoin:
return bitcoin!.createBitcoinWalletService(_walletInfoSource, _unspentCoinsInfoSource!);
return bitcoin!.createBitcoinWalletService(_walletInfoSource, _unspentCoinsInfoSource);
case WalletType.litecoin:
return bitcoin!.createLitecoinWalletService(_walletInfoSource, _unspentCoinsInfoSource!);
return bitcoin!.createLitecoinWalletService(_walletInfoSource, _unspentCoinsInfoSource);
case WalletType.ethereum:
return ethereum!.createEthereumWalletService(_walletInfoSource);
case WalletType.bitcoinCash:

View file

@ -50,7 +50,7 @@ class MainActions {
case WalletType.monero:
case WalletType.bitcoinCash:
if (viewModel.isEnabledBuyAction) {
final uri = getIt.get<OnRamperBuyProvider>().requestUrl();
final uri = getIt.get<OnRamperBuyProvider>().requestUrl(context);
if (DeviceInfo.instance.isMobile) {
Navigator.of(context)
.pushNamed(Routes.webViewPage, arguments: [S.of(context).buy, uri]);

View file

@ -0,0 +1,18 @@
class Unspent {
Unspent(this.address, this.hash, this.value, this.vout, this.keyImage)
: isSending = true,
isFrozen = false,
note = '';
final String address;
final String hash;
final int value;
final int vout;
final String? keyImage;
bool isSending;
bool isFrozen;
String note;
bool get isP2wpkh => address.startsWith('bc') || address.startsWith('ltc');
}

View file

@ -22,6 +22,14 @@ class CWEthereum extends Ethereum {
}) =>
EthereumRestoreWalletFromSeedCredentials(name: name, password: password, mnemonic: mnemonic);
@override
WalletCredentials createEthereumRestoreWalletFromPrivateKey({
required String name,
required String privateKey,
required String password,
}) =>
EthereumRestoreWalletFromPrivateKey(name: name, password: password, privateKey: privateKey);
@override
String getAddress(WalletBase wallet) => (wallet as EthereumWallet).walletAddresses.address;

View file

@ -68,14 +68,12 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
required CryptoCurrency to,
required bool isFixedRateMode}) async {
final headers = {apiHeaderKey: apiKey};
final normalizedFrom = normalizeCryptoCurrency(from);
final normalizedTo = normalizeCryptoCurrency(to);
final flow = getFlow(isFixedRateMode);
final params = <String, String>{
'fromCurrency': normalizedFrom,
'toCurrency': normalizedTo,
'fromNetwork': networkFor(from),
'toNetwork': networkFor(to),
'fromCurrency': _normalizeCurrency(from),
'toCurrency': _normalizeCurrency(to),
'fromNetwork': _networkFor(from),
'toNetwork': _networkFor(to),
'flow': flow
};
final uri = Uri.https(apiAuthority, rangePath, params);
@ -112,10 +110,10 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
final flow = getFlow(isFixedRateMode);
final type = isFixedRateMode ? 'reverse' : 'direct';
final body = <String, dynamic>{
'fromCurrency': normalizeCryptoCurrency(_request.from),
'toCurrency': normalizeCryptoCurrency(_request.to),
'fromNetwork': networkFor(_request.from),
'toNetwork': networkFor(_request.to),
'fromCurrency': _normalizeCurrency(_request.from),
'toCurrency': _normalizeCurrency(_request.to),
'fromNetwork': _networkFor(_request.from),
'toNetwork': _networkFor(_request.to),
if (!isFixedRateMode) 'fromAmount': _request.fromAmount,
if (isFixedRateMode) 'toAmount': _request.toAmount,
'address': _request.address,
@ -241,10 +239,10 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
final type = isReverse ? 'reverse' : 'direct';
final flow = getFlow(isFixedRateMode);
final params = <String, String>{
'fromCurrency': normalizeCryptoCurrency(from),
'toCurrency': normalizeCryptoCurrency(to),
'fromNetwork': networkFor(from),
'toNetwork': networkFor(to),
'fromCurrency': _normalizeCurrency(from),
'toCurrency': _normalizeCurrency(to),
'fromNetwork': _networkFor(from),
'toNetwork': _networkFor(to),
'type': type,
'flow': flow
};
@ -273,25 +271,34 @@ class ChangeNowExchangeProvider extends ExchangeProvider {
}
}
String networkFor(CryptoCurrency currency) {
String _networkFor(CryptoCurrency currency) {
switch (currency) {
case CryptoCurrency.usdt:
return CryptoCurrency.btc.title.toLowerCase();
return 'btc';
default:
return currency.tag != null ? currency.tag!.toLowerCase() : currency.title.toLowerCase();
return currency.tag != null ? _normalizeTag(currency.tag!) : currency.title.toLowerCase();
}
}
}
String normalizeCryptoCurrency(CryptoCurrency currency) {
switch (currency) {
case CryptoCurrency.zec:
return 'zec';
case CryptoCurrency.usdcpoly:
return 'usdcmatic';
case CryptoCurrency.maticpoly:
return 'maticmainnet';
default:
return currency.title.toLowerCase();
String _normalizeCurrency(CryptoCurrency currency) {
switch (currency) {
case CryptoCurrency.zec:
return 'zec';
default:
return currency.title.toLowerCase();
}
}
}
String _normalizeTag(String tag) {
switch (tag) {
case 'POLY':
return 'matic';
case 'LN':
return 'lightning';
case 'AVAXC':
return 'cchain';
default:
return tag.toLowerCase();
}
}
}

View file

@ -28,7 +28,6 @@ class SideShiftExchangeProvider extends ExchangeProvider {
CryptoCurrency.xhv,
CryptoCurrency.dcr,
CryptoCurrency.kmd,
CryptoCurrency.mkr,
CryptoCurrency.oxt,
CryptoCurrency.pivx,
CryptoCurrency.rune,

View file

@ -20,7 +20,6 @@ class TrocadorExchangeProvider extends ExchangeProvider {
bool useTorOnly;
static const List<CryptoCurrency> _notSupported = [
CryptoCurrency.scrt,
CryptoCurrency.stx,
CryptoCurrency.zaddr,
];
@ -60,8 +59,8 @@ class TrocadorExchangeProvider extends ExchangeProvider {
}) async {
final params = <String, String>{
'api_key': apiKey,
'ticker_from': request.from.title.toLowerCase(),
'ticker_to': request.to.title.toLowerCase(),
'ticker_from': _normalizeCurrency(request.from),
'ticker_to': _normalizeCurrency(request.to),
'network_from': _networkFor(request.from),
'network_to': _networkFor(request.to),
'payment': isFixedRateMode ? 'True' : 'False',
@ -137,7 +136,7 @@ class TrocadorExchangeProvider extends ExchangeProvider {
required bool isFixedRateMode}) async {
final params = <String, String>{
'api_key': apiKey,
'ticker': from.title.toLowerCase(),
'ticker': _normalizeCurrency(from),
'name': from.name,
};
@ -177,8 +176,8 @@ class TrocadorExchangeProvider extends ExchangeProvider {
final params = <String, String>{
'api_key': apiKey,
'ticker_from': from.title.toLowerCase(),
'ticker_to': to.title.toLowerCase(),
'ticker_from': _normalizeCurrency(from),
'ticker_to': _normalizeCurrency(to),
'network_from': _networkFor(from),
'network_to': _networkFor(to),
if (!isFixedRateMode) 'amount_from': amount.toString(),
@ -279,6 +278,15 @@ class TrocadorExchangeProvider extends ExchangeProvider {
}
}
String _normalizeCurrency(CryptoCurrency currency) {
switch (currency) {
case CryptoCurrency.zec:
return 'zec';
default:
return currency.title.toLowerCase();
}
}
String _normalizeTag(String tag) {
switch (tag) {
case 'ETH':

View file

@ -736,6 +736,21 @@ class HaMaterialLocalizations extends GlobalMaterialLocalizations {
@override
String get keyboardKeySpace => 'Space';
@override
String get bottomSheetLabel => "Bottom Sheet";
@override
String get currentDateLabel => "Current Date";
@override
String get keyboardKeyShift => "Shift";
@override
String get scrimLabel => "Scrim";
@override
String get scrimOnTapHintRaw => "Scrip on Tap";
}
/// Cupertino Support
@ -937,4 +952,7 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations {
static const LocalizationsDelegate<CupertinoLocalizations> delegate =
_HaCupertinoLocalizationsDelegate();
@override
String get noSpellCheckReplacementsLabel => "";
}

View file

@ -736,6 +736,21 @@ String get keyboardKeyMetaWindows => 'Windows';
@override
String get keyboardKeySpace => 'Space';
@override
String get bottomSheetLabel => "Bottom Sheet";
@override
String get currentDateLabel => "Current Date";
@override
String get keyboardKeyShift => "Shift";
@override
String get scrimLabel => "Scrim";
@override
String get scrimOnTapHintRaw => "Scrip on Tap";
}
/// Cupertino Support
@ -937,4 +952,7 @@ String get todayLabel => 'Oyọ';
static const LocalizationsDelegate<CupertinoLocalizations> delegate =
_YoCupertinoLocalizationsDelegate();
@override
String get noSpellCheckReplacementsLabel => "";
}

View file

@ -133,11 +133,7 @@ Future<void> initializeAppConfigs() async {
final templates = await CakeHive.openBox<Template>(Template.boxName);
final exchangeTemplates = await CakeHive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
final anonpayInvoiceInfo = await CakeHive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName);
Box<UnspentCoinsInfo>? unspentCoinsInfoSource;
if (!isMoneroOnly) {
unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName);
}
final unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName);
await initialSetup(
sharedPreferences: await SharedPreferences.getInstance(),
@ -169,7 +165,7 @@ Future<void> initialSetup(
required Box<TransactionDescription> transactionDescriptions,
required FlutterSecureStorage secureStorage,
required Box<AnonpayInvoiceInfo> anonpayInvoiceInfo,
Box<UnspentCoinsInfo>? unspentCoinsInfoSource,
required Box<UnspentCoinsInfo> unspentCoinsInfoSource,
int initialMigrationVersion = 15}) async {
LanguageService.loadLocaleList();
await defaultSettingsMigration(

View file

@ -1,361 +1,363 @@
part of 'monero.dart';
class CWMoneroAccountList extends MoneroAccountList {
CWMoneroAccountList(this._wallet);
final Object _wallet;
CWMoneroAccountList(this._wallet);
@override
@computed
final Object _wallet;
@override
@computed
ObservableList<Account> get accounts {
final moneroWallet = _wallet as MoneroWallet;
final accounts = moneroWallet.walletAddresses.accountList
.accounts
.map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
.toList();
return ObservableList<Account>.of(accounts);
final moneroWallet = _wallet as MoneroWallet;
final accounts = moneroWallet.walletAddresses.accountList.accounts
.map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
.toList();
return ObservableList<Account>.of(accounts);
}
@override
void update(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.accountList.update();
final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.accountList.update();
}
@override
void refresh(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.accountList.refresh();
}
void refresh(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.accountList.refresh();
}
@override
@override
List<Account> getAll(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.walletAddresses.accountList
.getAll()
.map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
.toList();
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.walletAddresses.accountList
.getAll()
.map((acc) => Account(id: acc.id, label: acc.label, balance: acc.balance))
.toList();
}
@override
Future<void> addAccount(Object wallet, {required String label}) async {
final moneroWallet = wallet as MoneroWallet;
await moneroWallet.walletAddresses.accountList.addAccount(label: label);
final moneroWallet = wallet as MoneroWallet;
await moneroWallet.walletAddresses.accountList.addAccount(label: label);
}
@override
Future<void> setLabelAccount(Object wallet, {required int accountIndex, required String label}) async {
final moneroWallet = wallet as MoneroWallet;
await moneroWallet.walletAddresses.accountList
.setLabelAccount(
accountIndex: accountIndex,
label: label);
Future<void> setLabelAccount(Object wallet,
{required int accountIndex, required String label}) async {
final moneroWallet = wallet as MoneroWallet;
await moneroWallet.walletAddresses.accountList
.setLabelAccount(accountIndex: accountIndex, label: label);
}
}
class CWMoneroSubaddressList extends MoneroSubaddressList {
CWMoneroSubaddressList(this._wallet);
final Object _wallet;
CWMoneroSubaddressList(this._wallet);
@override
@computed
final Object _wallet;
@override
@computed
ObservableList<Subaddress> get subaddresses {
final moneroWallet = _wallet as MoneroWallet;
final subAddresses = moneroWallet.walletAddresses.subaddressList
.subaddresses
.map((sub) => Subaddress(
id: sub.id,
address: sub.address,
label: sub.label))
.toList();
return ObservableList<Subaddress>.of(subAddresses);
final moneroWallet = _wallet as MoneroWallet;
final subAddresses = moneroWallet.walletAddresses.subaddressList.subaddresses
.map((sub) => Subaddress(id: sub.id, address: sub.address, label: sub.label))
.toList();
return ObservableList<Subaddress>.of(subAddresses);
}
@override
void update(Object wallet, {required int accountIndex}) {
final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex);
final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.subaddressList.update(accountIndex: accountIndex);
}
@override
void refresh(Object wallet, {required int accountIndex}) {
final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex);
final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.subaddressList.refresh(accountIndex: accountIndex);
}
@override
List<Subaddress> getAll(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.walletAddresses
.subaddressList
.getAll()
.map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address))
.toList();
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.walletAddresses.subaddressList
.getAll()
.map((sub) => Subaddress(id: sub.id, label: sub.label, address: sub.address))
.toList();
}
@override
Future<void> addSubaddress(Object wallet, {required int accountIndex, required String label}) async {
final moneroWallet = wallet as MoneroWallet;
await moneroWallet.walletAddresses.subaddressList
.addSubaddress(
accountIndex: accountIndex,
label: label);
Future<void> addSubaddress(Object wallet,
{required int accountIndex, required String label}) async {
final moneroWallet = wallet as MoneroWallet;
await moneroWallet.walletAddresses.subaddressList
.addSubaddress(accountIndex: accountIndex, label: label);
}
@override
Future<void> setLabelSubaddress(Object wallet,
{required int accountIndex, required int addressIndex, required String label}) async {
final moneroWallet = wallet as MoneroWallet;
await moneroWallet.walletAddresses.subaddressList
.setLabelSubaddress(
accountIndex: accountIndex,
addressIndex: addressIndex,
label: label);
final moneroWallet = wallet as MoneroWallet;
await moneroWallet.walletAddresses.subaddressList
.setLabelSubaddress(accountIndex: accountIndex, addressIndex: addressIndex, label: label);
}
}
class CWMoneroWalletDetails extends MoneroWalletDetails {
CWMoneroWalletDetails(this._wallet);
final Object _wallet;
CWMoneroWalletDetails(this._wallet);
@computed
final Object _wallet;
@computed
@override
Account get account {
final moneroWallet = _wallet as MoneroWallet;
final acc = moneroWallet.walletAddresses.account;
return Account(id: acc!.id, label: acc.label, balance: acc.balance);
final moneroWallet = _wallet as MoneroWallet;
final acc = moneroWallet.walletAddresses.account;
return Account(id: acc!.id, label: acc.label, balance: acc.balance);
}
@computed
@override
MoneroBalance get balance {
final moneroWallet = _wallet as MoneroWallet;
final balance = moneroWallet.balance;
MoneroBalance get balance {
final moneroWallet = _wallet as MoneroWallet;
final balance = moneroWallet.balance;
throw Exception('Unimplemented');
// return MoneroBalance();
//return MoneroBalance(
// fullBalance: balance.fullBalance,
// unlockedBalance: balance.unlockedBalance);
}
// return MoneroBalance();
//return MoneroBalance(
// fullBalance: balance.fullBalance,
// unlockedBalance: balance.unlockedBalance);
}
}
class CWMonero extends Monero {
@override
MoneroAccountList getAccountList(Object wallet) {
return CWMoneroAccountList(wallet);
}
@override
MoneroSubaddressList getSubaddressList(Object wallet) {
return CWMoneroSubaddressList(wallet);
}
@override
TransactionHistoryBase getTransactionHistory(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.transactionHistory;
}
@override
MoneroWalletDetails getMoneroWalletDetails(Object wallet) {
return CWMoneroWalletDetails(wallet);
}
@override
int getHeigthByDate({required DateTime date}) {
return getMoneroHeigthByDate(date: date);
}
@override
TransactionPriority getDefaultTransactionPriority() {
return MoneroTransactionPriority.automatic;
}
MoneroAccountList getAccountList(Object wallet) {
return CWMoneroAccountList(wallet);
}
@override
TransactionPriority getMoneroTransactionPrioritySlow()
=> MoneroTransactionPriority.slow;
MoneroSubaddressList getSubaddressList(Object wallet) {
return CWMoneroSubaddressList(wallet);
}
@override
TransactionPriority getMoneroTransactionPriorityAutomatic()
=> MoneroTransactionPriority.automatic;
TransactionHistoryBase getTransactionHistory(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.transactionHistory;
}
@override
TransactionPriority deserializeMoneroTransactionPriority({required int raw}) {
return MoneroTransactionPriority.deserialize(raw: raw);
}
@override
MoneroWalletDetails getMoneroWalletDetails(Object wallet) {
return CWMoneroWalletDetails(wallet);
}
@override
List<TransactionPriority> getTransactionPriorities() {
return MoneroTransactionPriority.all;
}
@override
int getHeigthByDate({required DateTime date}) {
return getMoneroHeigthByDate(date: date);
}
@override
List<String> getMoneroWordList(String language) {
switch (language.toLowerCase()) {
case 'english':
return EnglishMnemonics.words;
case 'chinese (simplified)':
return ChineseSimplifiedMnemonics.words;
case 'dutch':
return DutchMnemonics.words;
case 'german':
return GermanMnemonics.words;
case 'japanese':
return JapaneseMnemonics.words;
case 'portuguese':
return PortugueseMnemonics.words;
case 'russian':
return RussianMnemonics.words;
case 'spanish':
return SpanishMnemonics.words;
case 'french':
return FrenchMnemonics.words;
case 'italian':
return ItalianMnemonics.words;
default:
return EnglishMnemonics.words;
}
}
@override
TransactionPriority getDefaultTransactionPriority() {
return MoneroTransactionPriority.automatic;
}
@override
WalletCredentials createMoneroRestoreWalletFromKeysCredentials({
required String name,
required String spendKey,
required String viewKey,
required String address,
required String password,
required String language,
required int height}) {
return MoneroRestoreWalletFromKeysCredentials(
name: name,
spendKey: spendKey,
viewKey: viewKey,
address: address,
password: password,
language: language,
height: height);
}
@override
WalletCredentials createMoneroRestoreWalletFromSeedCredentials({
required String name,
required String password,
required int height,
required String mnemonic}) {
return MoneroRestoreWalletFromSeedCredentials(
name: name,
password: password,
height: height,
mnemonic: mnemonic);
}
@override
TransactionPriority getMoneroTransactionPrioritySlow() => MoneroTransactionPriority.slow;
@override
WalletCredentials createMoneroNewWalletCredentials({
@override
TransactionPriority getMoneroTransactionPriorityAutomatic() =>
MoneroTransactionPriority.automatic;
@override
TransactionPriority deserializeMoneroTransactionPriority({required int raw}) {
return MoneroTransactionPriority.deserialize(raw: raw);
}
@override
List<TransactionPriority> getTransactionPriorities() {
return MoneroTransactionPriority.all;
}
@override
List<String> getMoneroWordList(String language) {
switch (language.toLowerCase()) {
case 'english':
return EnglishMnemonics.words;
case 'chinese (simplified)':
return ChineseSimplifiedMnemonics.words;
case 'dutch':
return DutchMnemonics.words;
case 'german':
return GermanMnemonics.words;
case 'japanese':
return JapaneseMnemonics.words;
case 'portuguese':
return PortugueseMnemonics.words;
case 'russian':
return RussianMnemonics.words;
case 'spanish':
return SpanishMnemonics.words;
case 'french':
return FrenchMnemonics.words;
case 'italian':
return ItalianMnemonics.words;
default:
return EnglishMnemonics.words;
}
}
@override
WalletCredentials createMoneroRestoreWalletFromKeysCredentials(
{required String name,
required String spendKey,
required String viewKey,
required String address,
required String password,
required String language,
required int height}) {
return MoneroRestoreWalletFromKeysCredentials(
name: name,
spendKey: spendKey,
viewKey: viewKey,
address: address,
password: password,
language: language,
height: height);
}
@override
WalletCredentials createMoneroRestoreWalletFromSeedCredentials(
{required String name,
required String password,
required int height,
required String mnemonic}) {
return MoneroRestoreWalletFromSeedCredentials(
name: name, password: password, height: height, mnemonic: mnemonic);
}
@override
WalletCredentials createMoneroNewWalletCredentials({
required String name,
required String language,
String? password,}) {
return MoneroNewWalletCredentials(
name: name,
password: password,
language: language);
}
String? password,
}) {
return MoneroNewWalletCredentials(name: name, password: password, language: language);
}
@override
Map<String, String> getKeys(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
final keys = moneroWallet.keys;
return <String, String>{
'privateSpendKey': keys.privateSpendKey,
@override
Map<String, String> getKeys(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
final keys = moneroWallet.keys;
return <String, String>{
'privateSpendKey': keys.privateSpendKey,
'privateViewKey': keys.privateViewKey,
'publicSpendKey': keys.publicSpendKey,
'publicViewKey': keys.publicViewKey};
}
'publicViewKey': keys.publicViewKey
};
}
@override
Object createMoneroTransactionCreationCredentials({
required List<Output> outputs,
required TransactionPriority priority}) {
return MoneroTransactionCreationCredentials(
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);
}
@override
Object createMoneroTransactionCreationCredentials(
{required List<Output> outputs, required TransactionPriority priority}) {
return MoneroTransactionCreationCredentials(
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);
}
@override
Object createMoneroTransactionCreationCredentialsRaw({
required List<OutputInfo> outputs,
required TransactionPriority priority}) {
return MoneroTransactionCreationCredentials(
outputs: outputs,
priority: priority as MoneroTransactionPriority);
}
@override
Object createMoneroTransactionCreationCredentialsRaw(
{required List<OutputInfo> outputs, required TransactionPriority priority}) {
return MoneroTransactionCreationCredentials(
outputs: outputs, priority: priority as MoneroTransactionPriority);
}
@override
String formatterMoneroAmountToString({required int amount}) {
return moneroAmountToString(amount: amount);
}
@override
String formatterMoneroAmountToString({required int amount}) {
return moneroAmountToString(amount: amount);
}
@override
double formatterMoneroAmountToDouble({required int amount}) {
return moneroAmountToDouble(amount: amount);
}
@override
double formatterMoneroAmountToDouble({required int amount}) {
return moneroAmountToDouble(amount: amount);
}
@override
int formatterMoneroParseAmount({required String amount}) {
return moneroParseAmount(amount: amount);
}
@override
int formatterMoneroParseAmount({required String amount}) {
return moneroParseAmount(amount: amount);
}
@override
Account getCurrentAccount(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
final acc = moneroWallet.walletAddresses.account;
return Account(id: acc!.id, label: acc.label, balance: acc.balance);
}
@override
Account getCurrentAccount(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
final acc = moneroWallet.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 moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.account = monero_account.Account(id: id, label: label, balance: balance);
}
@override
void setCurrentAccount(Object wallet, int id, String label, String? balance) {
final moneroWallet = wallet as MoneroWallet;
moneroWallet.walletAddresses.account =
monero_account.Account(id: id, label: label, balance: balance);
}
@override
void onStartup() {
monero_wallet_api.onStartup();
}
@override
void onStartup() {
monero_wallet_api.onStartup();
}
@override
int getTransactionInfoAccountId(TransactionInfo tx) {
final moneroTransactionInfo = tx as MoneroTransactionInfo;
return moneroTransactionInfo.accountIndex;
}
@override
int getTransactionInfoAccountId(TransactionInfo tx) {
final moneroTransactionInfo = tx as MoneroTransactionInfo;
return moneroTransactionInfo.accountIndex;
}
@override
WalletService createMoneroWalletService(Box<WalletInfo> walletInfoSource) {
return MoneroWalletService(walletInfoSource);
}
@override
WalletService createMoneroWalletService(
Box<WalletInfo> walletInfoSource, Box<UnspentCoinsInfo> unspentCoinSource) {
return MoneroWalletService(walletInfoSource, unspentCoinSource);
}
@override
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.getTransactionAddress(accountIndex, addressIndex);
}
@override
String getTransactionAddress(Object wallet, int accountIndex, int addressIndex) {
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.getTransactionAddress(accountIndex, addressIndex);
}
@override
String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex) {
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.getSubaddressLabel(accountIndex, addressIndex);
}
@override
String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex) {
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.getSubaddressLabel(accountIndex, addressIndex);
}
@override
Map<String, String> pendingTransactionInfo(Object transaction) {
final ptx = transaction as PendingMoneroTransaction;
return {'id': ptx.id, 'hex': ptx.hex, 'key': ptx.txKey};
}
@override
Map<String, String> pendingTransactionInfo(Object transaction) {
final ptx = transaction as PendingMoneroTransaction;
return {'id': ptx.id, 'hex': ptx.hex, 'key': ptx.txKey};
}
@override
List<Unspent> getUnspents(Object wallet) {
final moneroWallet = wallet as MoneroWallet;
return moneroWallet.unspentCoins
.map((MoneroUnspent moneroUnspent) => Unspent(moneroUnspent.address, moneroUnspent.hash,
moneroUnspent.value, 0, moneroUnspent.keyImage))
.toList();
}
@override
void updateUnspents(Object wallet) async {
final moneroWallet = wallet as MoneroWallet;
await moneroWallet.updateUnspent();
}
}

View file

@ -15,6 +15,9 @@ class Palette {
static const Color nightBlue = Color.fromRGBO(46, 57, 96, 1.0);
static const Color moderateOrangeYellow = Color.fromRGBO(245, 134, 82, 1.0);
static const Color moderateOrange = Color.fromRGBO(235, 117, 63, 1.0);
static const Color moneroOrange = Color.fromRGBO(255, 102, 0, 1.0);
static const Color moneroLightOrange = Color.fromRGBO(250, 240, 246, 1.0);
static const Color bitcoinOrange = Color.fromRGBO(242, 169, 0, 1.0);
static const Color shineGreen = Color.fromRGBO(76, 189, 87, 1.0);
static const Color moderateGreen = Color.fromRGBO(45, 158, 56, 1.0);
static const Color cornflower = Color.fromRGBO(85, 147, 240, 1.0);
@ -48,6 +51,7 @@ class Palette {
static const Color paleCornflowerBlue = Color.fromRGBO(185, 196, 237, 1.0);
static const Color manatee = Color.fromRGBO(153, 161, 176, 1.0);
static const Color stateGray = Color.fromRGBO(68, 74, 89, 1.0);
static const Color highContrastGray = Color.fromRGBO(76, 76, 76, 1.0);
static const Color frostySky = Color.fromRGBO(0, 184, 250, 1.0);
}
@ -90,4 +94,7 @@ class PaletteDark {
static const Color lightPurpleBlue = Color.fromRGBO(120, 133, 170, 1.0);
static const Color indicatorVioletBlue = Color.fromRGBO(59, 72, 119, 1.0);
static const Color granite = Color.fromRGBO(48, 51, 60, 1.0);
}
static const Color matrixGreen = Color.fromRGBO(18, 229, 90, 1.0);
static const Color moneroOrange = Color.fromRGBO(255, 102, 0, 1.0);
static const Color moneroCard = Color.fromRGBO(20, 21, 24, 1.0);
}

View file

@ -57,7 +57,6 @@ import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/view_model/wallet_new_vm.dart';
import 'package:cake_wallet/view_model/wallet_restoration_from_seed_vm.dart';
import 'package:cake_wallet/exchange/trade.dart';
import 'package:cw_core/transaction_info.dart';
import 'package:cw_core/wallet_type.dart';
@ -80,7 +79,6 @@ import 'package:cake_wallet/src/screens/monero_accounts/monero_account_edit_or_c
import 'package:cake_wallet/src/screens/contact/contact_list_page.dart';
import 'package:cake_wallet/src/screens/contact/contact_page.dart';
import 'package:cake_wallet/src/screens/wallet_keys/wallet_keys_page.dart';
import 'package:cake_wallet/src/screens/restore/restore_wallet_from_seed_details.dart';
import 'package:cake_wallet/src/screens/exchange/exchange_page.dart';
import 'package:cake_wallet/src/screens/rescan/rescan_page.dart';
import 'package:cake_wallet/src/screens/faq/faq_page.dart';
@ -398,16 +396,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
builder: (_) =>
getIt.get<BuyWebViewPage>(param1: args));
case Routes.restoreWalletFromSeedDetails:
final args = settings.arguments as List;
final walletRestorationFromSeedVM =
getIt.get<WalletRestorationFromSeedVM>(param1: args);
return CupertinoPageRoute<void>(
fullscreenDialog: true,
builder: (_) => RestoreWalletFromSeedDetailsPage(
walletRestorationFromSeedVM: walletRestorationFromSeedVM));
case Routes.exchange:
return CupertinoPageRoute<void>(
fullscreenDialog: true,

View file

@ -30,7 +30,6 @@ class Routes {
static const tradeDetails = '/trade_details';
static const exchangeFunds = '/exchange_funds';
static const exchangeTrade = '/exchange_trade';
static const restoreWalletFromSeedDetails = '/restore_from_seed_details';
static const exchange = '/exchange';
static const settings = '/settings';
static const desktop_settings_page = '/desktop_settings_page';

View file

@ -42,10 +42,9 @@ class _AnonpayDetailsPageBodyState extends State<AnonpayDetailsPageBody> {
@override
Widget build(BuildContext context) {
return SectionStandardList(
context: context,
sectionCount: 1,
itemCounter: (int _) => widget.anonpayDetailsViewModel.items.length,
itemBuilder: (_, __, index) {
itemBuilder: (__, index) {
final item = widget.anonpayDetailsViewModel.items[index];
if (item is DetailsListStatusItem) {

View file

@ -80,7 +80,7 @@ class BackupPage extends BasePage {
isLoading: backupViewModelBase.state is IsExecutingState,
onPressed: () => onExportBackup(context),
text: S.of(context).export_backup,
color: Theme.of(context).accentTextTheme.bodyLarge!.color!,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
),
),
@ -127,9 +127,9 @@ class BackupPage extends BasePage {
builder: (dialogContext) {
return AlertWithTwoActions(
alertTitle: S.of(context).export_backup,
alertContent: 'Please select destination for the backup file.',
rightButtonText: 'Save to Downloads',
leftButtonText: 'Share',
alertContent: S.of(context).select_destination,
rightButtonText: S.of(context).save_to_downloads,
leftButtonText:S.of(context).share,
actionRightButton: () async {
final permission = await Permission.storage.request();

View file

@ -7,6 +7,7 @@ import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/view_model/edit_backup_password_view_model.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
class EditBackupPasswordPage extends BasePage {
EditBackupPasswordPage(this.editBackupPasswordViewModel)
@ -39,19 +40,13 @@ class EditBackupPasswordPage extends BasePage {
controller: textEditingController,
style: TextStyle(
fontSize: 26,
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!)))),
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)))),
Positioned(
child: Observer(
builder: (_) => PrimaryButton(
onPressed: () => onSave(context),
text: S.of(context).save,
color: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.color!,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
isDisabled: !editBackupPasswordViewModel.canSave)),
bottom: 24,

View file

@ -1,7 +1,6 @@
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/src/widgets/nav_bar.dart';
@ -10,22 +9,22 @@ import 'package:cake_wallet/generated/i18n.dart';
enum AppBarStyle { regular, withShadow, transparent }
abstract class BasePage extends StatelessWidget {
BasePage()
: _scaffoldKey = GlobalKey<ScaffoldState>();
BasePage() : _scaffoldKey = GlobalKey<ScaffoldState>();
final GlobalKey<ScaffoldState> _scaffoldKey;
final Image closeButtonImage =
Image.asset('assets/images/close_button.png');
final Image closeButtonImage = Image.asset('assets/images/close_button.png');
final Image closeButtonImageDarkTheme =
Image.asset('assets/images/close_button_dark_theme.png');
Image.asset('assets/images/close_button_dark_theme.png');
String? get title => null;
Color get backgroundLightColor => Colors.white;
Color? get backgroundLightColor => null;
Color get backgroundDarkColor => PaletteDark.backgroundColor;
Color? get backgroundDarkColor => null;
Color? get titleColor => null;
bool get gradientBackground => false;
bool get gradientAll => false;
bool get resizeToAvoidBottomInset => true;
@ -43,15 +42,41 @@ abstract class BasePage extends StatelessWidget {
void onClose(BuildContext context) => Navigator.of(context).pop();
Color pageBackgroundColor(BuildContext context) =>
(currentTheme.type == ThemeType.dark
? backgroundDarkColor
: backgroundLightColor) ??
(gradientBackground && currentTheme.type == ThemeType.bright
? Colors.transparent
: Theme.of(context).colorScheme.background);
Color titleColor(BuildContext context) =>
(gradientBackground && currentTheme.type == ThemeType.bright) ||
(gradientAll && currentTheme.brightness == Brightness.light)
? Colors.white
: Theme.of(context).appBarTheme.titleTextStyle!.color!;
Color? pageIconColor(BuildContext context) => titleColor(context);
Widget closeButton(BuildContext context) => Image.asset(
currentTheme.type == ThemeType.dark
? 'assets/images/close_button_dark_theme.png'
: 'assets/images/close_button.png',
color: pageIconColor(context),
height: 16,
);
Widget backButton(BuildContext context) => Icon(
Icons.arrow_back_ios,
color: pageIconColor(context),
size: 16,
);
Widget? leading(BuildContext context) {
if (ModalRoute.of(context)?.isFirst ?? true) {
return null;
}
final _backButton = Icon(Icons.arrow_back_ios,
color: titleColor ?? Theme.of(context).primaryTextTheme!.titleLarge!.color!,
size: 16,);
return MergeSemantics(
child: SizedBox(
height: 37,
@ -66,7 +91,7 @@ abstract class BasePage extends StatelessWidget {
(states) => Colors.transparent),
),
onPressed: () => onClose(context),
child: _backButton,
child: backButton(context),
),
),
),
@ -83,8 +108,7 @@ abstract class BasePage extends StatelessWidget {
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'Lato',
color: titleColor ??
Theme.of(context).primaryTextTheme!.titleLarge!.color!),
color: titleColor(context)),
);
}
@ -93,9 +117,8 @@ abstract class BasePage extends StatelessWidget {
Widget? floatingActionButton(BuildContext context) => null;
ObstructingPreferredSizeWidget appBar(BuildContext context) {
final appBarColor = currentTheme.type == ThemeType.dark
? backgroundDarkColor : backgroundLightColor;
final appBarColor = pageBackgroundColor(context);
switch (appBarStyle) {
case AppBarStyle.regular:
// FIX-ME: NavBar no context
@ -139,12 +162,9 @@ abstract class BasePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _backgroundColor = currentTheme.type == ThemeType.dark
? backgroundDarkColor : backgroundLightColor;
final root = Scaffold(
key: _scaffoldKey,
backgroundColor: _backgroundColor,
backgroundColor: pageBackgroundColor(context),
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
extendBodyBehindAppBar: extendBodyBehindAppBar,
endDrawer: endDrawer,

View file

@ -24,9 +24,6 @@ class BuyWebViewPage extends BasePage {
@override
Color get backgroundDarkColor => Colors.white;
@override
Color get titleColor => Palette.darkBlueCraiola;
@override
Widget body(BuildContext context) =>
BuyWebViewPageBody(buyViewModel, ordersStore: ordersStore, url: url);

View file

@ -3,6 +3,10 @@ import 'package:cake_wallet/buy/buy_provider.dart';
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cake_wallet/src/widgets/picker.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:cake_wallet/src/screens/buy/widgets/buy_list_item.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
@ -58,9 +62,6 @@ class PreOrderPage extends BasePage {
@override
String get title => S.current.buy + ' ' + walletTypeToString(buyViewModel.wallet.type);
@override
Color get titleColor => Colors.white;
@override
bool get resizeToAvoidBottomInset => false;
@ -80,10 +81,7 @@ class PreOrderPage extends BasePage {
return KeyboardActions(
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
keyboardBarColor: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.backgroundColor!,
keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
nextFocus: false,
actions: [
KeyboardActionsItem(
@ -104,10 +102,8 @@ class PreOrderPage extends BasePage {
bottomLeft: Radius.circular(24),
bottomRight: Radius.circular(24)),
gradient: LinearGradient(colors: [
Theme.of(context).primaryTextTheme!.titleMedium!.color!,
Theme.of(context)
.primaryTextTheme!.titleMedium!
.decorationColor!,
Theme.of(context).extension<SendPageTheme>()!.firstGradientColor,
Theme.of(context).extension<SendPageTheme>()!.secondGradientColor,
], begin: Alignment.topLeft, end: Alignment.bottomRight),
),
child: Padding(
@ -162,11 +158,11 @@ class PreOrderPage extends BasePage {
),
),
hintText: '0.00',
borderColor: Theme.of(context).primaryTextTheme!.bodyLarge!.decorationColor!,
borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
borderWidth: 0.5,
textStyle: TextStyle(fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white),
placeholderTextStyle: TextStyle(
color: Theme.of(context).primaryTextTheme!.headlineSmall!.decorationColor!,
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor,
fontWeight: FontWeight.w500,
fontSize: 36,
),
@ -181,7 +177,7 @@ class PreOrderPage extends BasePage {
S.of(context).buy_with + ':',
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).primaryTextTheme.titleLarge!.color!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
fontSize: 18,
fontWeight: FontWeight.bold
),
@ -248,7 +244,7 @@ class PreOrderPage extends BasePage {
? S.of(context).buy
: S.of(context).buy_with +
' ${buyViewModel.selectedProvider!.description.title}',
color: Theme.of(context).accentTextTheme!.bodyLarge!.color!,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
isLoading: buyViewModel.isRunning,
isDisabled: (buyViewModel.selectedProvider == null) ||

View file

@ -1,6 +1,8 @@
import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/entities/contact_base.dart';
import 'package:cake_wallet/entities/contact_record.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.dart';
@ -32,13 +34,13 @@ class ContactListPage extends BasePage {
height: 32.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).accentTextTheme!.bodySmall!.color!),
color: Theme.of(context).extension<ExchangePageTheme>()!.buttonBackgroundColor),
child: Stack(
alignment: Alignment.center,
children: <Widget>[
Icon(
Icons.add,
color: Theme.of(context).primaryTextTheme.titleLarge!.color!,
color: Theme.of(context).appBarTheme.titleTextStyle!.color,
size: 22.0,
),
ButtonTheme(
@ -48,17 +50,15 @@ class ContactListPage extends BasePage {
// FIX-ME: Style
//shape: CircleBorder(),
onPressed: () async {
if (contactListViewModel
.shouldRequireTOTP2FAForAddingContacts) {
if (contactListViewModel.shouldRequireTOTP2FAForAddingContacts) {
authService.authenticateAction(
context,
route: Routes.addressBookAddContact,
conditionToDetermineIfToUse2FA: contactListViewModel
.shouldRequireTOTP2FAForAddingContacts,
conditionToDetermineIfToUse2FA:
contactListViewModel.shouldRequireTOTP2FAForAddingContacts,
);
} else {
await Navigator.of(context)
.pushNamed(Routes.addressBookAddContact);
await Navigator.of(context).pushNamed(Routes.addressBookAddContact);
}
},
child: Offstage()),
@ -72,17 +72,13 @@ class ContactListPage extends BasePage {
@override
Widget body(BuildContext context) {
return Container(
padding: EdgeInsets.only(top: 20.0, bottom: 20.0),
padding: EdgeInsets.all(20.0),
child: Observer(builder: (_) {
final contacts = contactListViewModel.contactsToShow;
final walletContacts = contactListViewModel.walletContactsToShow;
return CollapsibleSectionList(
context: context,
sectionCount: 2,
themeColor: Theme.of(context).primaryTextTheme.titleLarge!.color!,
dividerThemeColor:
Theme.of(context).primaryTextTheme.bodySmall!.decorationColor!,
sectionTitleBuilder: (_, int sectionIndex) {
sectionTitleBuilder: (int sectionIndex) {
var title = S.current.contact_list_contacts;
if (sectionIndex == 0) {
@ -95,7 +91,7 @@ class ContactListPage extends BasePage {
},
itemCounter: (int sectionIndex) =>
sectionIndex == 0 ? walletContacts.length : contacts.length,
itemBuilder: (_, sectionIndex, index) {
itemBuilder: (int sectionIndex, index) {
if (sectionIndex == 0) {
final walletInfo = walletContacts[index];
return generateRaw(context, walletInfo);
@ -128,8 +124,7 @@ class ContactListPage extends BasePage {
return;
}
final isCopied = await showNameAndAddressDialog(
context, contact.name, contact.address);
final isCopied = await showNameAndAddressDialog(context, contact.name, contact.address);
if (isCopied) {
await Clipboard.setData(ClipboardData(text: contact.address));
@ -137,7 +132,6 @@ class ContactListPage extends BasePage {
}
},
child: Container(
color: Colors.transparent,
padding: const EdgeInsets.only(top: 16, bottom: 16, right: 24),
child: Row(
mainAxisSize: MainAxisSize.min,
@ -152,7 +146,7 @@ class ContactListPage extends BasePage {
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
color: Theme.of(context).primaryTextTheme.titleLarge!.color!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
),
))
@ -177,8 +171,7 @@ class ContactListPage extends BasePage {
false;
}
Future<bool> showNameAndAddressDialog(
BuildContext context, String name, String address) async {
Future<bool> showNameAndAddressDialog(BuildContext context, String name, String address) async {
return await showPopUp<bool>(
context: context,
builder: (BuildContext context) {
@ -193,8 +186,7 @@ class ContactListPage extends BasePage {
false;
}
ActionPane _actionPane(BuildContext context, ContactRecord contact) =>
ActionPane(
ActionPane _actionPane(BuildContext context, ContactRecord contact) => ActionPane(
motion: const ScrollMotion(),
extentRatio: 0.4,
children: [

View file

@ -1,5 +1,6 @@
import 'package:cake_wallet/core/address_validator.dart';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cw_core/currency.dart';
import 'package:flutter/material.dart';
@ -17,6 +18,8 @@ import 'package:cake_wallet/src/widgets/address_text_field.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
import 'package:cake_wallet/themes/extensions/address_theme.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
class ContactPage extends BasePage {
ContactPage(this.contactViewModel)
@ -47,7 +50,7 @@ class ContactPage extends BasePage {
@override
Widget body(BuildContext context) {
final downArrow = Image.asset('assets/images/arrow_bottom_purple_icon.png',
color: Theme.of(context).primaryTextTheme!.labelSmall!.color!,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
height: 8);
reaction((_) => contactViewModel.state, (ExecutionState state) {
@ -99,15 +102,9 @@ class ContactPage extends BasePage {
AddressTextFieldOption.paste,
AddressTextFieldOption.qrCode,
],
buttonColor: Theme.of(context)
.accentTextTheme!
.displaySmall!
.color!,
buttonColor: Theme.of(context).extension<AddressTheme>()!.actionButtonColor,
iconColor: PaletteDark.gray,
borderColor: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.backgroundColor!,
borderColor: Theme.of(context).extension<CakeTextTheme>()!.textfieldUnderlineColor,
validator:
AddressValidator(type: contactViewModel.currency!),
),
@ -143,10 +140,7 @@ class ContactPage extends BasePage {
await contactViewModel.save();
},
text: S.of(context).save,
color: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.color!,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
isDisabled: !contactViewModel.isReady)))
],

View file

@ -4,6 +4,8 @@ import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/entities/main_actions.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart';
import 'package:cake_wallet/src/widgets/gradient_background.dart';
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
import 'package:cake_wallet/utils/device_info.dart';
import 'package:cake_wallet/utils/version_comparator.dart';
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
@ -11,7 +13,6 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/yat_emoji_id.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.dart';
@ -29,6 +30,8 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart';
import 'package:cake_wallet/main.dart';
import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
class DashboardPage extends StatelessWidget {
DashboardPage({
@ -81,28 +84,11 @@ class _DashboardPageView extends BasePage {
final BalancePage balancePage;
@override
Color get backgroundLightColor =>
currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white;
@override
Color get backgroundDarkColor => Colors.transparent;
bool get gradientBackground => true;
@override
Widget Function(BuildContext, Widget) get rootWrapper =>
(BuildContext context, Widget scaffold) => Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Theme.of(context).colorScheme.secondary,
Theme.of(context).scaffoldBackgroundColor,
Theme.of(context).primaryColor,
],
begin: Alignment.topRight,
end: Alignment.bottomLeft,
),
),
child: scaffold,
);
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
@override
bool get resizeToAvoidBottomInset => false;
@ -122,7 +108,7 @@ class _DashboardPageView extends BasePage {
Widget trailing(BuildContext context) {
final menuButton = Image.asset(
'assets/images/menu.png',
color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor,
color: Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
);
return Container(
@ -141,6 +127,7 @@ class _DashboardPageView extends BasePage {
final DashboardViewModel dashboardViewModel;
final WalletAddressListViewModel addressListViewModel;
int get initialPage => dashboardViewModel.shouldShowMarketPlaceInDashboard ? 1 : 0;
ObservableList<Widget> pages = ObservableList<Widget>();
bool _isEffectsInstalled = false;
@ -199,8 +186,10 @@ class _DashboardPageView extends BasePage {
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context).indicatorColor,
activeDotColor:
Theme.of(context).accentTextTheme.headlineMedium!.backgroundColor!,
activeDotColor: Theme.of(context)
.extension<DashboardPageTheme>()!
.indicatorDotTheme
.activeIndicatorColor,
),
),
);
@ -216,12 +205,11 @@ class _DashboardPageView extends BasePage {
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50.0),
border: Border.all(
color: currentTheme.type == ThemeType.bright
? Color.fromRGBO(255, 255, 255, 0.2)
: Colors.transparent,
color: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
width: 1,
),
color: Theme.of(context).textTheme.titleLarge!.backgroundColor!,
color:
Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
),
child: Container(
padding: EdgeInsets.only(left: 32, right: 32),
@ -240,13 +228,11 @@ class _DashboardPageView extends BasePage {
width: 24,
color: action.isEnabled?.call(dashboardViewModel) ?? true
? Theme.of(context)
.accentTextTheme
.displayMedium!
.backgroundColor!
.extension<DashboardPageTheme>()!
.mainActionsIconColor
: Theme.of(context)
.accentTextTheme
.displaySmall!
.backgroundColor!,
.extension<BalancePageTheme>()!
.labelTextColor,
),
title: action.name(context),
onClick: () async =>
@ -254,9 +240,8 @@ class _DashboardPageView extends BasePage {
textColor: action.isEnabled?.call(dashboardViewModel) ?? true
? null
: Theme.of(context)
.accentTextTheme
.displaySmall!
.backgroundColor!,
.extension<BalancePageTheme>()!
.labelTextColor,
),
),
)

View file

@ -1,4 +1,7 @@
import 'package:auto_size_text/auto_size_text.dart';
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
import 'package:flutter/material.dart';
class DesktopActionButton extends StatelessWidget {
@ -30,7 +33,7 @@ class DesktopActionButton extends StatelessWidget {
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Theme.of(context).textTheme!.titleLarge!.backgroundColor!,
color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
),
child: Center(
child: Row(
@ -41,14 +44,8 @@ class DesktopActionButton extends StatelessWidget {
height: 30,
width: 30,
color: isEnabled
? Theme.of(context)
.accentTextTheme!
.displayMedium!
.backgroundColor!
: Theme.of(context)
.accentTextTheme!
.displaySmall!
.backgroundColor!,
? Theme.of(context).extension<DashboardPageTheme>()!.textColor
: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
),
const SizedBox(width: 10),
AutoSizeText(
@ -58,10 +55,7 @@ class DesktopActionButton extends StatelessWidget {
fontFamily: 'Lato',
fontWeight: FontWeight.bold,
color: isEnabled
? Theme.of(context)
.accentTextTheme!
.displayMedium!
.backgroundColor!
? Theme.of(context).extension<DashboardPageTheme>()!.textColor
: null,
height: 1,
),

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
class SideMenuItem extends StatelessWidget {
const SideMenuItem({
@ -16,7 +17,7 @@ class SideMenuItem extends StatelessWidget {
Color _setColor(BuildContext context) {
if (isSelected) {
return Theme.of(context).primaryTextTheme!.titleLarge!.color!;
return Theme.of(context).extension<CakeTextTheme>()!.titleColor;
} else {
return Theme.of(context).highlightColor;
}

View file

@ -1,10 +1,12 @@
import 'package:another_flushbar/flushbar.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/entities/desktop_dropdown_item.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/dropdown_item_widget.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
@ -38,14 +40,14 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
'assets/images/new_wallet.png',
height: 12,
width: 12,
color: Theme.of(context).primaryTextTheme!.titleLarge!.color!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
);
Image _restoreWalletImage(BuildContext context) => Image.asset(
'assets/images/restore_wallet.png',
height: 12,
width: 12,
color: Theme.of(context).primaryTextTheme!.titleLarge!.color!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
);
Flushbar<void>? _progressBar;
@ -95,8 +97,8 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
onChanged: (item) {
item?.onSelected();
},
dropdownColor: themeData.textTheme!.bodyLarge?.decorationColor,
style: TextStyle(color: themeData.primaryTextTheme!.titleLarge?.color),
dropdownColor: themeData.extension<CakeMenuTheme>()!.backgroundColor,
style: TextStyle(color: themeData.extension<CakeTextTheme>()!.titleColor),
selectedItemBuilder: (context) => dropDownItems.map((item) => item.child).toList(),
value: dropDownItems.firstWhere((element) => element.isSelected),
underline: const SizedBox(),

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:flutter/material.dart';
class DropDownItemWidget extends StatelessWidget {
@ -23,7 +24,7 @@ class DropDownItemWidget extends StatelessWidget {
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryTextTheme!.titleLarge!.color!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,

View file

@ -6,6 +6,7 @@ import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/src/widgets/checkbox_widget.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart';
import 'package:cw_core/erc20_token.dart';
import 'package:flutter/material.dart';
@ -111,7 +112,7 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> {
Container(
padding: EdgeInsets.symmetric(vertical: 16, horizontal: 28),
decoration: BoxDecoration(
color: Theme.of(context).accentTextTheme.bodySmall!.color!,
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(12),
),
child: Row(
@ -128,7 +129,7 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> {
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).primaryTextTheme.titleLarge!.color!,
color: Theme.of(context).dialogTheme.backgroundColor,
),
),
Padding(
@ -138,7 +139,7 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> {
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.normal,
color: Theme.of(context).primaryTextTheme.labelSmall!.color!,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
),
),
),
@ -197,7 +198,7 @@ class _EditTokenPageBodyState extends State<EditTokenPageBody> {
}
},
text: S.of(context).save,
color: Theme.of(context).accentTextTheme.bodyLarge!.color!,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
),
),

View file

@ -7,6 +7,8 @@ import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
import 'package:cake_wallet/themes/extensions/address_theme.dart';
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
import 'package:cake_wallet/view_model/dashboard/home_settings_view_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
@ -34,7 +36,7 @@ class HomeSettingsPage extends BasePage {
onItemSelected: _homeSettingsViewModel.setSortBalanceBy,
),
),
Divider(color: Theme.of(context).primaryTextTheme.bodySmall!.decorationColor!),
Divider(color: Theme.of(context).extension<CakeMenuTheme>()!.dividerColor),
Observer(
builder: (_) => SettingsSwitcherCell(
title: S.of(context).pin_at_top(_homeSettingsViewModel.nativeToken.title),
@ -44,7 +46,7 @@ class HomeSettingsPage extends BasePage {
},
),
),
Divider(color: Theme.of(context).primaryTextTheme.bodySmall!.decorationColor!),
Divider(color: Theme.of(context).extension<CakeMenuTheme>()!.dividerColor),
const SizedBox(height: 20),
Row(
children: [
@ -53,12 +55,12 @@ class HomeSettingsPage extends BasePage {
padding: const EdgeInsetsDirectional.only(start: 16),
child: TextFormField(
controller: _searchController,
style: TextStyle(color: Theme.of(context).primaryTextTheme.titleLarge!.color!),
style: TextStyle(color: Theme.of(context).dialogTheme.backgroundColor),
decoration: InputDecoration(
hintText: S.of(context).search_add_token,
prefixIcon: Image.asset("assets/images/search_icon.png"),
filled: true,
fillColor: Theme.of(context).accentTextTheme.displaySmall!.color!,
fillColor: Theme.of(context).extension<AddressTheme>()!.actionButtonColor,
alignLabelWithHint: false,
contentPadding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16),
enabledBorder: OutlineInputBorder(
@ -84,15 +86,15 @@ class HomeSettingsPage extends BasePage {
});
},
elevation: 0,
fillColor: Theme.of(context).accentTextTheme.bodySmall!.color!,
fillColor: Theme.of(context).cardColor,
child: Icon(
Icons.add,
color: Theme.of(context).primaryTextTheme.titleLarge!.color!,
color: Theme.of(context).dialogTheme.backgroundColor,
size: 22.0,
),
padding: EdgeInsets.all(12),
shape: CircleBorder(),
splashColor: Theme.of(context).accentTextTheme.bodySmall!.color!,
splashColor: Theme.of(context).cardColor,
),
],
),
@ -146,7 +148,7 @@ class HomeSettingsPage extends BasePage {
),
),
decoration: BoxDecoration(
color: Theme.of(context).accentTextTheme.bodySmall!.color!,
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(30),
),
);

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
class ActionButton extends StatelessWidget {
ActionButton(
@ -46,14 +47,11 @@ class ActionButton extends StatelessWidget {
style: TextStyle(
fontSize: 10,
color: textColor ??
Theme.of(context)
.accentTextTheme!
.displayMedium!
.backgroundColor!),
Theme.of(context).extension<DashboardPageTheme>()!.cardTextColor),
)
],
),
),
);
}
}
}

View file

@ -1,10 +1,14 @@
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/receive_page_option.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/src/widgets/gradient_background.dart';
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
import 'package:cake_wallet/themes/extensions/receive_page_theme.dart';
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/utils/share_util.dart';
@ -21,6 +25,8 @@ import 'package:keyboard_actions/keyboard_actions.dart';
import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
class AddressPage extends BasePage {
AddressPage({
@ -48,11 +54,7 @@ class AddressPage extends BasePage {
final FocusNode _cryptoAmountFocus;
@override
Color get backgroundLightColor =>
currentTheme.type == ThemeType.bright ? Colors.transparent : Colors.white;
@override
Color get backgroundDarkColor => Colors.transparent;
bool get gradientBackground => true;
@override
bool get resizeToAvoidBottomInset => false;
@ -61,14 +63,6 @@ class AddressPage extends BasePage {
@override
Widget? leading(BuildContext context) {
final _backButton = Icon(
Icons.arrow_back_ios,
color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
size: 16,
);
final _closeButton =
currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage;
bool isMobileView = ResponsiveLayoutUtil.instance.isMobile;
return MergeSemantics(
@ -84,7 +78,7 @@ class AddressPage extends BasePage {
overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent),
),
onPressed: () => onClose(context),
child: !isMobileView ? _closeButton : _backButton,
child: !isMobileView ? closeButton(context) : backButton(context),
),
),
),
@ -94,20 +88,11 @@ class AddressPage extends BasePage {
@override
Widget middle(BuildContext context) => PresentReceiveOptionPicker(
receiveOptionViewModel: receiveOptionViewModel,
hasWhiteBackground: currentTheme.type == ThemeType.light,
);
color: titleColor(context), receiveOptionViewModel: receiveOptionViewModel);
@override
Widget Function(BuildContext, Widget) get rootWrapper =>
(BuildContext context, Widget scaffold) => Container(
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Theme.of(context).colorScheme.secondary,
Theme.of(context).scaffoldBackgroundColor,
Theme.of(context).primaryColor,
], begin: Alignment.topRight, end: Alignment.bottomLeft)),
child: scaffold);
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
@override
Widget? trailing(BuildContext context) {
@ -125,11 +110,7 @@ class AddressPage extends BasePage {
context: context,
);
},
icon: Icon(
Icons.share,
size: 20,
color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
),
icon: Icon(Icons.share, size: 20, color: pageIconColor(context)),
),
);
}
@ -166,10 +147,10 @@ class AddressPage extends BasePage {
return KeyboardActions(
autoScroll: false,
disableScroll: true,
tapOutsideToDismiss: true,
tapOutsideBehavior: TapOutsideBehavior.translucentDismiss,
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
keyboardBarColor: Theme.of(context).accentTextTheme.bodyLarge!.backgroundColor!,
keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
nextFocus: false,
actions: [
KeyboardActionsItem(
@ -201,8 +182,12 @@ class AddressPage extends BasePage {
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(25)),
border: Border.all(
color: Theme.of(context).textTheme.titleMedium!.color!, width: 1),
color: Theme.of(context).textTheme.titleLarge!.backgroundColor!),
color:
Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
width: 1),
color: Theme.of(context)
.extension<SyncIndicatorTheme>()!
.syncedBackgroundColor),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -216,14 +201,13 @@ class AddressPage extends BasePage {
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.accentTextTheme.displayMedium!
.backgroundColor!),
.extension<SyncIndicatorTheme>()!
.textColor),
)),
Icon(
Icons.arrow_forward_ios,
size: 14,
color:
Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
color: Theme.of(context).extension<SyncIndicatorTheme>()!.textColor,
)
],
),
@ -234,8 +218,7 @@ class AddressPage extends BasePage {
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
color:
Theme.of(context).accentTextTheme.displaySmall!.backgroundColor!));
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor));
} else {
return const SizedBox();
}

View file

@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
class AnonpayTransactionRow extends StatelessWidget {
AnonpayTransactionRow({
@ -37,19 +39,19 @@ class AnonpayTransactionRow extends StatelessWidget {
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!)),
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)),
Text(amount + ' ' + currency,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!))
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor))
]),
SizedBox(height: 5),
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[
Text(createdAt,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).textTheme!.labelSmall!.backgroundColor!))
color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))
])
],
))

View file

@ -1,7 +1,7 @@
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/exchange_trade/information_page.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
import 'package:cake_wallet/utils/feature_flag.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.dart';
@ -10,6 +10,8 @@ import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:cake_wallet/src/widgets/introducing_card.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
class BalancePage extends StatelessWidget {
BalancePage({required this.dashboardViewModel, required this.settingsStore});
@ -41,7 +43,8 @@ class BalancePage extends StatelessWidget {
fontSize: 24,
fontFamily: 'Lato',
fontWeight: FontWeight.w600,
color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
color:
Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
height: 1,
),
maxLines: 1,
@ -55,8 +58,9 @@ class BalancePage extends StatelessWidget {
padding: const EdgeInsets.all(8.0),
child: Image.asset(
'assets/images/home_screen_settings_icon.png',
color:
Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
color: Theme.of(context)
.extension<DashboardPageTheme>()!
.pageTitleTextColor,
),
),
),
@ -72,9 +76,7 @@ class BalancePage extends StatelessWidget {
return IntroducingCard(
title: S.of(context).introducing_cake_pay,
subTitle: S.of(context).cake_pay_learn_more,
borderColor: settingsStore.currentTheme.type == ThemeType.bright
? Color.fromRGBO(255, 255, 255, 0.2)
: Colors.transparent,
borderColor: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
closeCard: dashboardViewModel.balanceViewModel.disableIntroCakePayCard);
}
return Container();
@ -134,12 +136,10 @@ class BalancePage extends StatelessWidget {
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30.0),
border: Border.all(
color: settingsStore.currentTheme.type == ThemeType.bright
? Color.fromRGBO(255, 255, 255, 0.2)
: Colors.transparent,
color: Theme.of(context).extension<BalancePageTheme>()!.cardBorderColor,
width: 1,
),
color: Theme.of(context).textTheme.titleLarge!.backgroundColor!,
color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
),
child: Container(
margin: const EdgeInsets.only(top: 16, left: 24, right: 24, bottom: 24),
@ -164,9 +164,8 @@ class BalancePage extends StatelessWidget {
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context)
.accentTextTheme!
.displaySmall!
.backgroundColor!,
.extension<BalancePageTheme>()!
.labelTextColor,
height: 1)),
if (hasAdditionalBalance)
Padding(
@ -174,9 +173,8 @@ class BalancePage extends StatelessWidget {
child: Icon(Icons.help_outline,
size: 16,
color: Theme.of(context)
.accentTextTheme!
.displaySmall!
.backgroundColor!),
.extension<BalancePageTheme>()!
.labelTextColor),
),
],
),
@ -187,9 +185,8 @@ class BalancePage extends StatelessWidget {
fontFamily: 'Lato',
fontWeight: FontWeight.w900,
color: Theme.of(context)
.accentTextTheme!
.displayMedium!
.backgroundColor!,
.extension<BalancePageTheme>()!
.balanceAmountColor,
height: 1),
maxLines: 1,
textAlign: TextAlign.start),
@ -200,10 +197,7 @@ class BalancePage extends StatelessWidget {
fontSize: 16,
fontFamily: 'Lato',
fontWeight: FontWeight.w500,
color: Theme.of(context)
.accentTextTheme!
.displayMedium!
.backgroundColor!,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1)),
],
),
@ -213,7 +207,7 @@ class BalancePage extends StatelessWidget {
fontSize: 28,
fontFamily: 'Lato',
fontWeight: FontWeight.w800,
color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!,
color: Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor,
height: 1)),
],
),
@ -229,7 +223,7 @@ class BalancePage extends StatelessWidget {
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).accentTextTheme.displaySmall!.backgroundColor!,
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
height: 1,
),
),
@ -240,7 +234,7 @@ class BalancePage extends StatelessWidget {
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
height: 1,
),
maxLines: 1,
@ -254,7 +248,7 @@ class BalancePage extends StatelessWidget {
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
height: 1,
),
),
@ -272,7 +266,7 @@ class BalancePage extends StatelessWidget {
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).accentTextTheme.displaySmall!.backgroundColor!,
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor,
height: 1,
),
),
@ -283,7 +277,7 @@ class BalancePage extends StatelessWidget {
fontSize: 20,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
color: Theme.of(context).extension<BalancePageTheme>()!.assetTitleColor,
height: 1,
),
maxLines: 1,
@ -297,7 +291,7 @@ class BalancePage extends StatelessWidget {
fontSize: 12,
fontFamily: 'Lato',
fontWeight: FontWeight.w400,
color: Theme.of(context).accentTextTheme.displayMedium!.backgroundColor!,
color: Theme.of(context).extension<BalancePageTheme>()!.textColor,
height: 1,
),
),

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:intl/intl.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/utils/date_formatter.dart';
@ -36,9 +37,6 @@ class DateSectionRaw extends StatelessWidget {
child: Text(title,
style: TextStyle(
fontSize: 12,
color: Theme.of(context)
.textTheme!
.labelSmall!
.backgroundColor!)));
color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)));
}
}

View file

@ -1,12 +1,15 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/filter_tile.dart';
import 'package:cake_wallet/src/widgets/section_divider.dart';
import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
//import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
class FilterWidget extends StatelessWidget {
FilterWidget({required this.dashboardViewModel});
@ -15,7 +18,7 @@ class FilterWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
const sectionDivider = const SectionDivider();
const sectionDivider = const HorizontalSectionDivider();
return PickerWrapperWidget(
children: [
Padding(
@ -23,7 +26,7 @@ class FilterWidget extends StatelessWidget {
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(24)),
child: Container(
color: Theme.of(context).textTheme!.bodyLarge!.decorationColor!,
color: Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -32,10 +35,7 @@ class FilterWidget extends StatelessWidget {
child: Text(
S.of(context).filter_by,
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme!
.labelSmall!
.color!,
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor,
fontSize: 16,
fontFamily: 'Lato',
decoration: TextDecoration.none,
@ -63,10 +63,7 @@ class FilterWidget extends StatelessWidget {
child: Text(
title,
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
fontSize: 16,
fontFamily: 'Lato',
fontWeight: FontWeight.bold,

View file

@ -1,8 +1,10 @@
import 'package:cake_wallet/src/screens/dashboard/widgets/filter_widget.dart';
import 'package:cake_wallet/themes/extensions/filter_theme.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
class HeaderRow extends StatelessWidget {
HeaderRow({required this.dashboardViewModel});
@ -12,7 +14,7 @@ class HeaderRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final filterIcon = Image.asset('assets/images/filter_icon.png',
color: Theme.of(context).textTheme!.bodySmall!.decorationColor!);
color: Theme.of(context).extension<FilterTheme>()!.iconColor);
return Container(
height: 52,
@ -27,10 +29,7 @@ class HeaderRow extends StatelessWidget {
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.accentTextTheme!
.displayMedium!
.backgroundColor!),
color: Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor),
),
GestureDetector(
onTap: () {
@ -45,7 +44,7 @@ class HeaderRow extends StatelessWidget {
width: 36,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).textTheme!.labelSmall!.color!),
color: Theme.of(context).extension<FilterTheme>()!.buttonColor),
child: filterIcon,
),
)

View file

@ -8,6 +8,7 @@ import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
class MarketPlacePage extends StatelessWidget {
MarketPlacePage({
@ -40,10 +41,7 @@ class MarketPlacePage extends StatelessWidget {
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.accentTextTheme!
.displayMedium!
.backgroundColor!,
color: Theme.of(context).extension<DashboardPageTheme>()!.pageTitleTextColor,
),
),
Expanded(

View file

@ -1,13 +1,12 @@
import 'package:cake_wallet/src/widgets/setting_action_button.dart';
import 'package:cake_wallet/src/widgets/setting_actions.dart';
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
// FIXME: terrible design.
class MenuWidget extends StatefulWidget {
MenuWidget(this.dashboardViewModel);
@ -19,19 +18,19 @@ class MenuWidget extends StatefulWidget {
class MenuWidgetState extends State<MenuWidget> {
MenuWidgetState()
: this.menuWidth = 0,
this.screenWidth = 0,
this.screenHeight = 0,
this.headerHeight = 120,
this.tileHeight = 60,
this.fromTopEdge = 50,
this.fromBottomEdge = 25,
this.moneroIcon = Image.asset('assets/images/monero_menu.png'),
this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'),
this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'),
this.havenIcon = Image.asset('assets/images/haven_menu.png'),
this.ethereumIcon = Image.asset('assets/images/eth_icon.png'),
this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png');
: this.menuWidth = 0,
this.screenWidth = 0,
this.screenHeight = 0,
this.headerHeight = 120,
this.tileHeight = 60,
this.fromTopEdge = 50,
this.fromBottomEdge = 25,
this.moneroIcon = Image.asset('assets/images/monero_menu.png'),
this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'),
this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'),
this.havenIcon = Image.asset('assets/images/haven_menu.png'),
this.ethereumIcon = Image.asset('assets/images/eth_icon.png'),
this.bitcoinCashIcon = Image.asset('assets/images/bch_icon.png');
final largeScreen = 731;
@ -88,121 +87,111 @@ class MenuWidgetState extends State<MenuWidget> {
final itemCount = SettingActions.all.length;
moneroIcon = Image.asset('assets/images/monero_menu.png',
color: Theme.of(context)
.accentTextTheme
.labelSmall!
.decorationColor!);
color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor);
bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png',
color: Theme.of(context)
.accentTextTheme
.labelSmall!
.decorationColor!);
color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor);
return Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 24),
child: Container(
height: 60,
width: 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(2)), color: PaletteDark.gray),
)),
padding: EdgeInsets.only(left: 24),
child: Container(
height: 60,
width: 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(2)), color: PaletteDark.gray),
),
),
SizedBox(width: 12),
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(24), bottomLeft: Radius.circular(24)),
child: Container(
color:
Theme.of(context).textTheme!.bodyLarge!.decorationColor!,
child: ListView.separated(
padding: EdgeInsets.only(top: 0),
itemBuilder: (_, index) {
if (index == 0) {
return Container(
height: headerHeight,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Theme.of(context)
.accentTextTheme!
.headlineMedium!
.color!,
Theme.of(context)
.accentTextTheme!
.headlineMedium!
.decorationColor!, ], begin: Alignment.topLeft, end: Alignment.bottomRight),
),
padding: EdgeInsets.only(
left: 24, top: fromTopEdge, right: 24, bottom: fromBottomEdge),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
_iconFor(type: widget.dashboardViewModel.type),
SizedBox(width: 12),
SingleChildScrollView(
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: widget.dashboardViewModel.subname.isNotEmpty
? MainAxisAlignment.spaceBetween
: MainAxisAlignment.center,
children: <Widget>[
Text(
widget.dashboardViewModel.name,
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
),
if (widget.dashboardViewModel.subname.isNotEmpty)
Observer(
builder: (_) => Text(
widget.dashboardViewModel.subname,
style: TextStyle(
color: Theme.of(context)
.accentTextTheme!
.labelSmall!
.decorationColor!,
fontWeight: FontWeight.w500,
fontSize: 12),
))
],
child: ClipRRect(
borderRadius:
BorderRadius.only(topLeft: Radius.circular(24), bottomLeft: Radius.circular(24)),
child: Container(
color: Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor,
child: ListView.separated(
padding: EdgeInsets.only(top: 0),
itemBuilder: (_, index) {
if (index == 0) {
return Container(
height: headerHeight,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Theme.of(context).extension<CakeMenuTheme>()!.headerFirstGradientColor,
Theme.of(context).extension<CakeMenuTheme>()!.headerSecondGradientColor,
], begin: Alignment.topLeft, end: Alignment.bottomRight),
),
padding: EdgeInsets.only(
left: 24, top: fromTopEdge, right: 24, bottom: fromBottomEdge),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
_iconFor(type: widget.dashboardViewModel.type),
SizedBox(width: 12),
SingleChildScrollView(
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: widget.dashboardViewModel.subname.isNotEmpty
? MainAxisAlignment.spaceBetween
: MainAxisAlignment.center,
children: <Widget>[
Text(
widget.dashboardViewModel.name,
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold),
),
))
],
if (widget.dashboardViewModel.subname.isNotEmpty)
Observer(
builder: (_) => Text(
widget.dashboardViewModel.subname,
style: TextStyle(
color: Theme.of(context)
.extension<CakeMenuTheme>()!
.subnameTextColor,
fontWeight: FontWeight.w500,
fontSize: 12),
),
),
],
),
),
);
}
index--;
final item = SettingActions.all[index];
final isLastTile = index == itemCount - 1;
return SettingActionButton(
isLastTile: isLastTile,
tileHeight: tileHeight,
selectionActive: false,
fromBottomEdge: fromBottomEdge,
fromTopEdge: fromTopEdge,
onTap: () => item.onTap.call(context),
image: item.image,
title: item.name.call(context),
);
},
separatorBuilder: (_, index) => Container(
height: 1,
color: Theme.of(context)
.primaryTextTheme!
.bodySmall!
.decorationColor!,
),
itemCount: itemCount + 1),
)))
],
),
);
}
index--;
final item = SettingActions.all[index];
final isLastTile = index == itemCount - 1;
return SettingActionButton(
isLastTile: isLastTile,
tileHeight: tileHeight,
selectionActive: false,
fromBottomEdge: fromBottomEdge,
fromTopEdge: fromTopEdge,
onTap: () => item.onTap.call(context),
image: item.image,
title: item.name.call(context),
);
},
separatorBuilder: (_, index) => Container(
height: 1,
color: Theme.of(context).extension<CakeMenuTheme>()!.dividerColor,
),
itemCount: itemCount + 1,
),
),
),
),
],
);
}

View file

@ -1,6 +1,9 @@
import 'package:cake_wallet/buy/buy_provider_description.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/buy/get_buy_provider_icon.dart';
import 'package:cake_wallet/themes/extensions/order_theme.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
class OrderRow extends StatelessWidget {
OrderRow({
@ -20,7 +23,7 @@ class OrderRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final iconColor =
Theme.of(context).primaryTextTheme!.displayLarge!.backgroundColor!;
Theme.of(context).extension<OrderTheme>()!.iconColor;
final providerIcon = getBuyProviderIcon(provider, iconColor: iconColor);
@ -48,14 +51,14 @@ class OrderRow extends StatelessWidget {
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor
)),
formattedAmount != null
? Text(formattedAmount! + ' ' + to,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor
))
: Container()
]),
@ -66,10 +69,7 @@ class OrderRow extends StatelessWidget {
Text(createdAtFormattedDate,
style: TextStyle(
fontSize: 14,
color: Theme.of(context)
.textTheme!
.labelSmall!
.backgroundColor!))
color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))
])
],
)

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/src/screens/ionia/widgets/rounded_checkbox.dart';
import 'package:cake_wallet/src/widgets/alert_background.dart';
@ -10,22 +11,16 @@ import 'package:cake_wallet/generated/i18n.dart';
class PresentReceiveOptionPicker extends StatelessWidget {
PresentReceiveOptionPicker(
{required this.receiveOptionViewModel, this.hasWhiteBackground = false});
{required this.receiveOptionViewModel, required this.color});
final ReceiveOptionViewModel receiveOptionViewModel;
final bool hasWhiteBackground;
final Color color;
@override
Widget build(BuildContext context) {
final textIconTheme = hasWhiteBackground
? Theme.of(context)
.accentTextTheme!
.displayMedium!
.backgroundColor!
: Colors.white;
final arrowBottom = Image.asset(
'assets/images/arrow_bottom_purple_icon.png',
color: textIconTheme,
color: color,
height: 6,
);
@ -51,14 +46,14 @@ class PresentReceiveOptionPicker extends StatelessWidget {
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'Lato',
color: textIconTheme),
color: color),
),
Observer(
builder: (_) => Text(receiveOptionViewModel.selectedReceiveOption.toString(),
style: TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.w500,
color: textIconTheme)))
color: color)))
],
),
SizedBox(width: 5),
@ -113,10 +108,7 @@ class PresentReceiveOptionPicker extends StatelessWidget {
Text(option.toString(),
textAlign: TextAlign.left,
style: textSmall(
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
).copyWith(
fontWeight:
value == option ? FontWeight.w800 : FontWeight.w500,

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/core/sync_status_title.dart';
@ -32,7 +33,7 @@ class SyncIndicator extends StatelessWidget {
child: Container(
height: 30,
width: syncIndicatorWidth,
color: Theme.of(context).textTheme!.titleLarge!.decorationColor!,
color: Theme.of(context).extension<SyncIndicatorTheme>()!.notSyncedBackgroundColor,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
@ -44,7 +45,7 @@ class SyncIndicator extends StatelessWidget {
child: Container(
width: indicatorWidth,
height: 30,
color: Theme.of(context).textTheme!.titleLarge!.backgroundColor!,
color: Theme.of(context).extension<SyncIndicatorTheme>()!.syncedBackgroundColor,
)
)
: Offstage(),
@ -66,7 +67,7 @@ class SyncIndicator extends StatelessWidget {
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: Theme.of(context).textTheme!.titleLarge!.color!
color: Theme.of(context).extension<SyncIndicatorTheme>()!.textColor
),
),
)

View file

@ -1,3 +1,5 @@
import 'package:cake_wallet/themes/extensions/sync_indicator_theme.dart';
import 'package:cake_wallet/themes/extensions/receive_page_theme.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
@ -26,7 +28,7 @@ class SyncIndicatorIcon extends StatelessWidget {
if (boolMode) {
indicatorColor = isSynced
? PaletteDark.brightGreen
: Theme.of(context).textTheme!.bodySmall!.color!;
: Theme.of(context).extension<SyncIndicatorTheme>()!.notSyncedIconColor;
} else {
switch (value.toLowerCase()) {
case waiting:
@ -34,7 +36,7 @@ class SyncIndicatorIcon extends StatelessWidget {
break;
case actionRequired:
indicatorColor =
Theme.of(context).textTheme!.displayMedium!.decorationColor!;
Theme.of(context).extension<ReceivePageTheme>()!.currentTileBackgroundColor;
break;
case created:
indicatorColor = PaletteDark.brightGreen;

View file

@ -1,6 +1,8 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:flutter/material.dart';
import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
class TradeRow extends StatelessWidget {
TradeRow({
@ -43,14 +45,14 @@ class TradeRow extends StatelessWidget {
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!)),
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)),
formattedAmount != null
? Text(formattedAmount! + ' ' + amountCrypto,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color:
Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!))
Theme.of(context).extension<DashboardPageTheme>()!.textColor))
: Container()
]),
SizedBox(height: 5),
@ -59,7 +61,7 @@ class TradeRow extends StatelessWidget {
Text(createdAtFormattedDate!,
style: TextStyle(
fontSize: 14,
color: Theme.of(context).textTheme!.labelSmall!.backgroundColor!))
color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))
])
],
))

View file

@ -1,5 +1,8 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:flutter/material.dart';
import 'package:cw_core/transaction_direction.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
class TransactionRow extends StatelessWidget {
TransactionRow(
@ -35,7 +38,7 @@ class TransactionRow extends StatelessWidget {
width: 36,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).textTheme!.labelSmall!.decorationColor!
color: Theme.of(context).extension<TransactionTradeTheme>()!.rowsColor
),
child: Image.asset(
direction == TransactionDirection.incoming
@ -54,14 +57,12 @@ class TransactionRow extends StatelessWidget {
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).accentTextTheme!
.displayMedium!.backgroundColor!)),
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor)),
Text(formattedAmount,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Theme.of(context).accentTextTheme!
.displayMedium!.backgroundColor!))
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor))
]),
SizedBox(height: 5),
Row(
@ -70,17 +71,11 @@ class TransactionRow extends StatelessWidget {
Text(formattedDate,
style: TextStyle(
fontSize: 14,
color: Theme.of(context)
.textTheme!
.labelSmall!
.backgroundColor!)),
color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor)),
Text(formattedFiatAmount,
style: TextStyle(
fontSize: 14,
color: Theme.of(context)
.textTheme!
.labelSmall!
.backgroundColor!))
color: Theme.of(context).extension<CakeTextTheme>()!.dateSectionRowColor))
])
],
)

View file

@ -1,5 +1,6 @@
import 'package:cake_wallet/src/screens/dashboard/widgets/anonpay_transaction_row.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/order_row.dart';
import 'package:cake_wallet/themes/extensions/placeholder_theme.dart';
import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart';
@ -155,10 +156,7 @@ class TransactionsPage extends StatelessWidget {
S.of(context).placeholder_transactions,
style: TextStyle(
fontSize: 14,
color: Theme.of(context)
.primaryTextTheme
.labelSmall!
.decorationColor!),
color: Theme.of(context).extension<PlaceholderTheme>()!.color),
),
);
}))

View file

@ -1,6 +1,8 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'dart:ui';
import 'package:cake_wallet/palette.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
@ -87,10 +89,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!),
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
)
],
@ -107,10 +106,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.bold,
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!),
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
)
],
@ -126,10 +122,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.normal,
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!),
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
))
],
),
@ -146,10 +139,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.bold,
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!),
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
)
],
@ -167,7 +157,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
changenowUrl,
textAlign: TextAlign.left,
style: TextStyle(
color: Palette.blueCraiola,
color: Theme.of(context).primaryColor,
fontSize: 14.0,
fontWeight: FontWeight.normal,
decoration: TextDecoration.underline),
@ -193,7 +183,8 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
gradient: LinearGradient(
colors: [
Theme.of(context)
.backgroundColor
.colorScheme
.background
.withOpacity(0.0),
Theme.of(context).colorScheme.background,
],
@ -232,10 +223,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
),
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context)
.primaryTextTheme!
.bodySmall!
.color!,
color: Theme.of(context).extension<CakeTextTheme>()!.secondaryTextColor,
width: 1.0),
borderRadius: BorderRadius.all(
Radius.circular(8.0)),
@ -253,10 +241,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.0,
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!),
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
)
],
),
@ -273,14 +258,8 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
.popAndPushNamed(Routes.welcome)
: null,
text: 'Accept',
color: Theme.of(context)
.accentTextTheme!
.titleSmall!
.decorationColor!,
textColor: Theme.of(context)
.accentTextTheme!
.headlineSmall!
.decorationColor!),
color: Theme.of(context).extension<WalletListTheme>()!.createNewWalletButtonBackgroundColor,
textColor: Theme.of(context).extension<WalletListTheme>()!.restoreWalletButtonTextColor),
),
],
],

View file

@ -1,8 +1,11 @@
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/desktop_exchange_cards_section.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/mobile_exchange_cards_section.dart';
import 'package:cake_wallet/src/widgets/add_template_button.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/utils/debounce.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
@ -78,7 +81,10 @@ class ExchangePage extends BasePage {
String get title => S.current.exchange;
@override
Color get titleColor => Colors.white;
bool get gradientBackground => true;
@override
bool get gradientAll => true;
@override
bool get resizeToAvoidBottomInset => false;
@ -115,7 +121,7 @@ class ExchangePage extends BasePage {
Widget? leading(BuildContext context) {
final _backButton = Icon(
Icons.arrow_back_ios,
color: titleColor,
color: titleColor(context),
size: 16,
);
final _closeButton =
@ -152,7 +158,7 @@ class ExchangePage extends BasePage {
disableScroll: true,
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
keyboardBarColor: Theme.of(context).accentTextTheme.bodyLarge!.backgroundColor!,
keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
nextFocus: false,
actions: [
KeyboardActionsItem(
@ -205,8 +211,8 @@ class ExchangePage extends BasePage {
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme.displayLarge!
.decorationColor!,
.extension<ExchangePageTheme>()!
.receiveAmountColor,
fontWeight: FontWeight.w500,
fontSize: 12),
),
@ -244,7 +250,7 @@ class ExchangePage extends BasePage {
}
}
},
color: Theme.of(context).accentTextTheme.bodyLarge!.color!,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
isDisabled: exchangeViewModel.selectedProviders.isEmpty,
isLoading: exchangeViewModel.tradeState is TradeIsCreating)),
@ -624,8 +630,8 @@ class ExchangePage extends BasePage {
},
imageArrow: arrowBottomPurple,
currencyButtonColor: Colors.transparent,
addressButtonsColor: Theme.of(context).focusColor,
borderColor: Theme.of(context).primaryTextTheme.bodyLarge!.color!,
addressButtonsColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderTopPanelColor,
currencyValueValidator: (value) {
return !exchangeViewModel.isFixedRateMode
? AmountValidator(
@ -672,8 +678,8 @@ class ExchangePage extends BasePage {
exchangeViewModel.changeReceiveCurrency(currency: currency),
imageArrow: arrowBottomCakeGreen,
currencyButtonColor: Colors.transparent,
addressButtonsColor: Theme.of(context).focusColor,
borderColor: Theme.of(context).primaryTextTheme.bodyLarge!.decorationColor!,
addressButtonsColor: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
currencyValueValidator: (value) {
return exchangeViewModel.isFixedRateMode
? AmountValidator(

View file

@ -1,3 +1,5 @@
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/exchange/exchange_provider.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
@ -29,10 +31,10 @@ class ExchangeTemplatePage extends BasePage {
var _isReactionsSet = false;
@override
String get title => S.current.exchange_new_template;
bool get gradientAll => true;
@override
Color get titleColor => Colors.white;
String get title => S.current.exchange_new_template;
@override
bool get extendBodyBehindAppBar => true;
@ -73,10 +75,7 @@ class ExchangeTemplatePage extends BasePage {
disableScroll: true,
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
keyboardBarColor: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.backgroundColor!,
keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
nextFocus: false,
actions: [
KeyboardActionsItem(
@ -101,8 +100,8 @@ class ExchangeTemplatePage extends BasePage {
),
gradient: LinearGradient(
colors: [
Theme.of(context).primaryTextTheme!.bodyMedium!.color!,
Theme.of(context).primaryTextTheme!.bodyMedium!.decorationColor!,
Theme.of(context).extension<ExchangePageTheme>()!.firstGradientBottomPanelColor,
Theme.of(context).extension<ExchangePageTheme>()!.secondGradientBottomPanelColor,
],
stops: [0.35, 1.0],
begin: Alignment.topLeft,
@ -120,12 +119,8 @@ class ExchangeTemplatePage extends BasePage {
),
gradient: LinearGradient(
colors: [
Theme.of(context)
.primaryTextTheme!.titleSmall!
.color!,
Theme.of(context)
.primaryTextTheme!.titleSmall!
.decorationColor!,
Theme.of(context).extension<ExchangePageTheme>()!.firstGradientTopPanelColor,
Theme.of(context).extension<ExchangePageTheme>()!.secondGradientTopPanelColor,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight),
@ -157,10 +152,8 @@ class ExchangeTemplatePage extends BasePage {
imageArrow: arrowBottomPurple,
currencyButtonColor: Colors.transparent,
addressButtonsColor:
Theme.of(context).focusColor,
borderColor: Theme.of(context)
.primaryTextTheme!.bodyLarge!
.color!,
Theme.of(context).extension<ExchangePageTheme>()!.textFieldButtonColor,
borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
currencyValueValidator: AmountValidator(
currency: exchangeViewModel.depositCurrency),
//addressTextFieldValidator: AddressValidator(
@ -197,10 +190,8 @@ class ExchangeTemplatePage extends BasePage {
imageArrow: arrowBottomCakeGreen,
currencyButtonColor: Colors.transparent,
addressButtonsColor:
Theme.of(context).focusColor,
borderColor: Theme.of(context)
.primaryTextTheme!.bodyLarge!
.decorationColor!,
Theme.of(context).extension<ExchangePageTheme>()!.textFieldButtonColor,
borderColor: Theme.of(context).extension<ExchangePageTheme>()!.textFieldBorderBottomPanelColor,
currencyValueValidator: AmountValidator(
currency: exchangeViewModel.receiveCurrency),
//addressTextFieldValidator: AddressValidator(
@ -226,9 +217,7 @@ class ExchangeTemplatePage extends BasePage {
description,
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme!.displayLarge!
.decorationColor!,
color: Theme.of(context).extension<ExchangePageTheme>()!.receiveAmountColor,
fontWeight: FontWeight.w500,
fontSize: 12),
),
@ -256,7 +245,7 @@ class ExchangeTemplatePage extends BasePage {
}
},
text: S.of(context).save,
color: Colors.green,
color: Theme.of(context).primaryColor,
textColor: Colors.white),
]),
))
@ -444,4 +433,4 @@ class ExchangeTemplatePage extends BasePage {
key.currentState!.addressController.text = '';
}
}
}
}

View file

@ -1,3 +1,5 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/cake_scrollbar_theme.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
@ -20,10 +22,7 @@ class PickerItemWidget extends StatelessWidget {
return GestureDetector(
onTap: onTap,
child: Container(
color: Theme.of(context)
.accentTextTheme!
.titleLarge!
.color!,
color: Theme.of(context).dialogTheme.backgroundColor,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 24),
child: Row(
@ -44,10 +43,7 @@ class PickerItemWidget extends StatelessWidget {
style: TextStyle(
color: isSelected
? Palette.blueCraiola
: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!,
: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
fontSize: isSelected ? 16 : 14.0,
fontFamily: 'Lato',
fontWeight: FontWeight.w600,
@ -65,19 +61,13 @@ class PickerItemWidget extends StatelessWidget {
style: TextStyle(
fontSize: 7.0,
fontFamily: 'Lato',
color: Theme.of(context)
.textTheme!
.bodyMedium!
.color!),
color: Theme.of(context).extension<CakeScrollbarTheme>()!.thumbColor),
),
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6.0),
//border: Border.all(color: ),
color: Theme.of(context)
.textTheme!
.bodyMedium!
.decorationColor!,
color: Theme.of(context).extension<CakeScrollbarTheme>()!.trackColor,
),
),
),
@ -86,10 +76,7 @@ class PickerItemWidget extends StatelessWidget {
),
if (isSelected)
Icon(Icons.check_circle,
color: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.color!)
color: Theme.of(context).primaryColor)
],
),
),

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/themes/extensions/picker_theme.dart';
import 'package:cw_core/currency.dart';
import 'package:flutter/material.dart';
import 'currency_picker_item_widget.dart';
@ -20,10 +21,7 @@ class CurrencyPickerWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context)
.accentTextTheme!
.titleLarge!
.backgroundColor!,
color: Theme.of(context).extension<PickerTheme>()!.dividerColor,
child: Scrollbar(
controller: _scrollController,
child: GridView.builder(

View file

@ -1,6 +1,8 @@
import 'package:cake_wallet/entities/contact_base.dart';
import 'package:cake_wallet/themes/extensions/qr_code_theme.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/utils/payment_request.dart';
@ -12,6 +14,7 @@ import 'package:cw_core/crypto_currency.dart';
import 'package:cake_wallet/src/widgets/address_text_field.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
class ExchangeCard extends StatefulWidget {
ExchangeCard(
@ -160,7 +163,7 @@ class ExchangeCardState extends State<ExchangeCard> {
final copyImage = Image.asset('assets/images/copy_content.png',
height: 16,
width: 16,
color: Theme.of(context).primaryTextTheme!.displaySmall!.color!);
color: Theme.of(context).extension<SendPageTheme>()!.estimatedFeeColor);
return Container(
width: double.infinity,
@ -175,7 +178,7 @@ class ExchangeCardState extends State<ExchangeCard> {
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
color: Theme.of(context).textTheme!.headlineSmall!.color!),
color: Theme.of(context).extension<QRCodeTheme>()!.qrCodeColor),
)
],
),
@ -211,10 +214,7 @@ class ExchangeCardState extends State<ExchangeCard> {
height: 32,
decoration: BoxDecoration(
color: widget.addressButtonsColor ??
Theme.of(context)
.primaryTextTheme!
.headlineMedium!
.color!,
Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
borderRadius:
BorderRadius.all(Radius.circular(6))),
child: Center(
@ -224,10 +224,7 @@ class ExchangeCardState extends State<ExchangeCard> {
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Theme.of(context)
.primaryTextTheme!
.headlineMedium!
.decorationColor!)),
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor)),
),
),
),
@ -268,10 +265,7 @@ class ExchangeCardState extends State<ExchangeCard> {
placeholderTextStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context)
.accentTextTheme!
.displayLarge!
.decorationColor!),
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor),
validator: _isAmountEditable
? widget.currencyValueValidator
: null),
@ -282,10 +276,7 @@ class ExchangeCardState extends State<ExchangeCard> {
height: 32,
width: 32,
decoration: BoxDecoration(
color: Theme.of(context)
.primaryTextTheme!
.headlineMedium!
.color!,
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonColor,
borderRadius:
BorderRadius.all(Radius.circular(6))),
child: InkWell(
@ -296,10 +287,7 @@ class ExchangeCardState extends State<ExchangeCard> {
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Theme.of(context)
.primaryTextTheme!
.headlineMedium!
.decorationColor!)),
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor)),
),
),
)
@ -310,10 +298,7 @@ class ExchangeCardState extends State<ExchangeCard> {
)),
Divider(
height: 1,
color: Theme.of(context)
.primaryTextTheme!
.headlineSmall!
.decorationColor!),
color: Theme.of(context).extension<SendPageTheme>()!.textFieldHintColor),
Padding(
padding: EdgeInsets.only(top: 5),
child: Container(
@ -329,10 +314,7 @@ class ExchangeCardState extends State<ExchangeCard> {
style: TextStyle(
fontSize: 10,
height: 1.2,
color: Theme.of(context)
.accentTextTheme!
.displayLarge!
.decorationColor!),
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor),
)
: Offstage(),
_min != null ? SizedBox(width: 10) : Offstage(),
@ -344,10 +326,7 @@ class ExchangeCardState extends State<ExchangeCard> {
style: TextStyle(
fontSize: 10,
height: 1.2,
color: Theme.of(context)
.accentTextTheme!
.displayLarge!
.decorationColor!))
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor))
: Offstage(),
])),
),
@ -359,10 +338,7 @@ class ExchangeCardState extends State<ExchangeCard> {
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.accentTextTheme!
.displayLarge!
.decorationColor!),
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor),
))
: Offstage(),
_isAddressEditable
@ -400,10 +376,7 @@ class ExchangeCardState extends State<ExchangeCard> {
hintStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context)
.accentTextTheme!
.displayLarge!
.decorationColor!),
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor),
buttonColor: widget.addressButtonsColor,
validator: widget.addressTextFieldValidator,
onPushPasteButton: widget.onPushPasteButton,
@ -472,10 +445,7 @@ class ExchangeCardState extends State<ExchangeCard> {
6))),
child: Image.asset(
'assets/images/open_book.png',
color: Theme.of(context)
.primaryTextTheme!
.headlineMedium!
.decorationColor!,
color: Theme.of(context).extension<SendPageTheme>()!.textFieldButtonIconColor,
)),
)),
),

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:flutter/material.dart';
class MobileExchangeCardsSection extends StatelessWidget {
@ -21,8 +22,8 @@ class MobileExchangeCardsSection extends StatelessWidget {
),
gradient: LinearGradient(
colors: [
Theme.of(context).primaryTextTheme!.bodyMedium!.color!,
Theme.of(context).primaryTextTheme!.bodyMedium!.decorationColor!,
Theme.of(context).extension<ExchangePageTheme>()!.firstGradientBottomPanelColor,
Theme.of(context).extension<ExchangePageTheme>()!.secondGradientBottomPanelColor,
],
stops: [0.35, 1.0],
begin: Alignment.topLeft,
@ -37,11 +38,8 @@ class MobileExchangeCardsSection extends StatelessWidget {
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
gradient: LinearGradient(
colors: [
Theme.of(context).primaryTextTheme!.titleSmall!.color!,
Theme.of(context)
.primaryTextTheme!
.titleSmall!
.decorationColor!,
Theme.of(context).extension<ExchangePageTheme>()!.firstGradientTopPanelColor,
Theme.of(context).extension<ExchangePageTheme>()!.secondGradientTopPanelColor,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,

View file

@ -1,4 +1,5 @@
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/themes/extensions/qr_code_theme.dart';
import 'package:cake_wallet/src/widgets/check_box_picker.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:flutter/material.dart';
@ -49,10 +50,7 @@ class PresentProviderPicker extends StatelessWidget {
style: TextStyle(
fontSize: 10.0,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.textTheme!
.headlineSmall!
.color!)))
color: Theme.of(context).extension<QRCodeTheme>()!.qrCodeColor)))
],
),
SizedBox(width: 5),

View file

@ -1,5 +1,7 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
import 'package:cake_wallet/store/dashboard/trades_store.dart';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
@ -9,6 +11,7 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/exchange/trade.dart';
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
class ExchangeConfirmPage extends BasePage {
ExchangeConfirmPage({required this.tradesStore}) : trade = tradesStore.trade!;
@ -36,10 +39,7 @@ class ExchangeConfirmPage extends BasePage {
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!),
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
)),
Container(
@ -48,14 +48,8 @@ class ExchangeConfirmPage extends BasePage {
borderRadius: BorderRadius.all(Radius.circular(30)),
border: Border.all(
width: 1,
color: Theme.of(context)
.accentTextTheme!
.bodySmall!
.color!),
color: Theme.of(context)
.accentTextTheme!
.titleLarge!
.color!),
color: Theme.of(context).cardColor),
color: Theme.of(context).dialogTheme.backgroundColor),
child: Column(
children: <Widget>[
Expanded(
@ -70,10 +64,7 @@ class ExchangeConfirmPage extends BasePage {
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.primaryTextTheme!
.labelSmall!
.color!),
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
),
Text(
trade.id,
@ -82,10 +73,7 @@ class ExchangeConfirmPage extends BasePage {
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!),
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
],
),
@ -100,14 +88,8 @@ class ExchangeConfirmPage extends BasePage {
context, S.of(context).copied_to_clipboard);
},
text: S.of(context).copy_id,
color: Theme.of(context)
.accentTextTheme!
.bodySmall!
.backgroundColor!,
textColor: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!),
color: Theme.of(context).extension<ExchangePageTheme>()!.buttonBackgroundColor,
textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
)
],
@ -136,10 +118,7 @@ class ExchangeConfirmPage extends BasePage {
onPressed: () => Navigator.of(context)
.pushReplacementNamed(Routes.exchangeTrade),
text: S.of(context).saved_the_trade_id,
color: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.color!,
color: Theme.of(context).primaryColor,
textColor: Colors.white)
],
),

View file

@ -1,4 +1,6 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'dart:ui';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/utils/request_review_handler.dart';
import 'package:mobx/mobx.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
@ -20,6 +22,7 @@ import 'package:cake_wallet/src/screens/exchange_trade/widgets/timer_widget.dart
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/themes/extensions/transaction_trade_theme.dart';
void showInformation(
ExchangeTradeViewModel exchangeTradeViewModel, BuildContext context) {
@ -51,7 +54,7 @@ class ExchangeTradePage extends BasePage {
@override
Widget trailing(BuildContext context) {
final questionImage = Image.asset('assets/images/question_mark.png',
color: Theme.of(context).primaryTextTheme!.titleLarge!.color!);
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor);
return SizedBox(
height: 20.0,
@ -111,7 +114,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
final copyImage = Image.asset('assets/images/copy_content.png',
height: 16,
width: 16,
color: Theme.of(context).primaryTextTheme!.labelSmall!.color!);
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor);
_setEffects();
@ -133,17 +136,11 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
style: TextStyle(
fontSize: 14.0,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.primaryTextTheme!
.labelSmall!
.color!),
color: Theme.of(context).extension<TransactionTradeTheme>()!.detailsTitlesColor),
),
if (trade.expiredAt != null)
TimerWidget(trade.expiredAt!,
color: Theme.of(context)
.primaryTextTheme!
.titleLarge!
.color!)
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor)
])
: Offstage(),
Padding(
@ -160,10 +157,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: Theme.of(context)
.accentTextTheme!
.titleSmall!
.color!
color: Theme.of(context).extension<ExchangePageTheme>()!.qrCodeColor
)
),
child: QrImage(data: trade.inputAddress ?? fetchingLabel),
@ -179,10 +173,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
itemCount: widget.exchangeTradeViewModel.items.length,
separatorBuilder: (context, index) => Container(
height: 1,
color: Theme.of(context)
.accentTextTheme!
.titleSmall!
.backgroundColor!,
color: Theme.of(context).extension<ExchangePageTheme>()!.dividerCodeColor,
),
itemBuilder: (context, index) {
final item = widget.exchangeTradeViewModel.items[index];
@ -228,10 +219,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
onPressed: () =>
widget.exchangeTradeViewModel.confirmSending(),
text: S.of(context).confirm,
color: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.color!,
color: Theme.of(context).primaryColor,
textColor: Colors.white)
: Offstage();
})),
@ -321,7 +309,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
return Stack(
children: <Widget>[
Container(
color: Theme.of(popupContext).backgroundColor,
color: Theme.of(popupContext).colorScheme.background,
child: Center(
child: Image.asset(
'assets/images/birthday_cake.png'),
@ -341,10 +329,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Theme.of(popupContext)
.primaryTextTheme!
.titleLarge!
.color,
color: Theme.of(popupContext).extension<CakeTextTheme>()!.titleColor,
decoration: TextDecoration.none,
),
),
@ -360,10 +345,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
RequestReviewHandler.requestReview();
},
text: S.of(popupContext).got_it,
color: Theme.of(popupContext)
.accentTextTheme!
.bodyLarge!
.color!,
color: Theme.of(popupContext).primaryColor,
textColor: Colors.white))
],
);
@ -372,7 +354,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
return Stack(
children: <Widget>[
Container(
color: Theme.of(popupContext).backgroundColor,
color: Theme.of(popupContext).colorScheme.background,
child: Center(
child: Image.asset(
'assets/images/birthday_cake.png'),
@ -384,7 +366,8 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
child: Container(
decoration: BoxDecoration(
color: Theme.of(popupContext)
.backgroundColor
.colorScheme
.background
.withOpacity(0.25)),
child: Center(
child: Padding(
@ -395,10 +378,7 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: Theme.of(popupContext)
.primaryTextTheme!
.titleLarge!
.color!,
color: Theme.of(popupContext).extension<CakeTextTheme>()!.titleColor,
decoration: TextDecoration.none,
),
),

View file

@ -1,9 +1,13 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'dart:ui';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/themes/extensions/info_theme.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/src/widgets/alert_background.dart';
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
class InformationPage extends StatelessWidget {
InformationPage({required this.information});
@ -21,7 +25,7 @@ class InformationPage extends StatelessWidget {
),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(30)),
color: Theme.of(context).textTheme!.bodyLarge!.decorationColor!
color: Theme.of(context).extension<CakeMenuTheme>()!.backgroundColor
),
child: Column(
mainAxisSize: MainAxisSize.min,
@ -36,7 +40,7 @@ class InformationPage extends StatelessWidget {
fontWeight: FontWeight.normal,
fontFamily: 'Lato',
decoration: TextDecoration.none,
color: Theme.of(context).accentTextTheme!.bodySmall!.decorationColor!
color: Theme.of(context).extension<InfoTheme>()!.textColor
),
),
),
@ -45,8 +49,8 @@ class InformationPage extends StatelessWidget {
child: PrimaryButton(
onPressed: () => Navigator.of(context).pop(),
text: S.of(context).got_it,
color: Theme.of(context).accentTextTheme!.bodySmall!.backgroundColor!,
textColor: Theme.of(context).primaryTextTheme!.titleLarge!.color!
color: Theme.of(context).extension<ExchangePageTheme>()!.buttonBackgroundColor,
textColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor
),
)
],

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/palette.dart';
@ -26,12 +27,12 @@ class FAQItemState extends State<FAQItem> {
@override
Widget build(BuildContext context) {
final addIcon = Icon(Icons.add,
color: Theme.of(context).primaryTextTheme!.titleLarge!.color!);
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor);
final removeIcon = Icon(Icons.remove, color: Palette.blueCraiola);
final icon = isActive ? removeIcon : addIcon;
final color = isActive
? Palette.blueCraiola
: Theme.of(context).primaryTextTheme!.titleLarge!.color!;
: Theme.of(context).extension<CakeTextTheme>()!.titleColor;
return ListTileTheme(
contentPadding: EdgeInsets.fromLTRB(0, 6, 24, 6),
@ -54,7 +55,7 @@ class FAQItemState extends State<FAQItem> {
fontSize: 14,
fontWeight: FontWeight.normal,
color:
Theme.of(context).primaryTextTheme!.titleLarge!.color!),
Theme.of(context).extension<CakeTextTheme>()!.titleColor),
),
))
])

View file

@ -1,3 +1,4 @@
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/core/email_validator.dart';
import 'package:cake_wallet/ionia/ionia_create_state.dart';
import 'package:cake_wallet/routes.dart';
@ -40,10 +41,7 @@ class IoniaCreateAccountPage extends BasePage {
return Text(
S.current.sign_up,
style: textMediumSemiBold(
color: Theme.of(context)
.accentTextTheme!
.displayLarge!
.backgroundColor!,
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
),
);
}
@ -84,10 +82,7 @@ class IoniaCreateAccountPage extends BasePage {
onPressed: _createAccount,
isLoading:
_authViewModel.createUserState is IoniaCreateStateLoading,
color: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.color!,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
),
),
@ -107,10 +102,7 @@ class IoniaCreateAccountPage extends BasePage {
TextSpan(
text: S.of(context).settings_terms_and_conditions,
style: TextStyle(
color: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.color!,
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.w700,
),
recognizer: TapGestureRecognizer()
@ -122,10 +114,7 @@ class IoniaCreateAccountPage extends BasePage {
TextSpan(
text: S.of(context).privacy_policy,
style: TextStyle(
color: Theme.of(context)
.accentTextTheme!
.bodyLarge!
.color!,
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.w700,
),
recognizer: TapGestureRecognizer()

Some files were not shown because too many files have changed in this diff Show more