Reformat the whole codebase with 100 line width (#3403)

Omar Hatem committed Jul 15, 2026 at 01:20 UTC 16ddc0837af615b9c50c85b49ed4606b89fbd2f9
801 files changed +17518 -17092
.github/workflows/lint.yml
+107 -107
@@ -6,110 +6,110 @@ defaults:
6 run:
7 shell: bash
8 jobs:
9 - lint:
10 - runs-on: [Linux, amd64, android]
11 - container:
12 - image: ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly
13 - env:
14 - STORE_PASS: test@cake_wallet
15 - KEY_PASS: test@cake_wallet
16 - MONEROC_CACHE_DIR_ROOT: /opt/generic_cache
17 - BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
18 - ANDROID_AVD_HOME: /root/.android/avd
19 - volumes:
20 - - /opt/cw_cache_android/root/.cache:/root/.cache
21 - - /opt/cw_cache_android/root/.android/avd/:/root/.android/avd
22 - - /opt/cw_cache_android/root/.ccache:/root/.ccache
23 - - /opt/cw_cache_android/root/.pub-cache/:/root/.pub-cache
24 - - /opt/cw_cache_android/root/.gradle/:/root/.gradle
25 - - /opt/cw_cache_android/root/.android/:/root/.android
26 - - /opt/cw_cache_android/root/go/pkg:/root/go/pkg
27 - - /opt/cw_cache_android/opt/generic_cache:/opt/generic_cache
28 - - /dev/kvm:/dev/kvm
29 - - /var/run/docker.sock:/var/run/docker.sock
30 - strategy:
31 - matrix:
32 - api-level: [ 29 ]
33 -
34 - steps:
35 - - name: Fix github actions messing up $HOME...
36 - run: "echo HOME=/root | sudo tee -a $GITHUB_ENV"
37 - - uses: actions/checkout@v4
38 - with:
39 - ref: ${{ inputs.ref }}
40 -
41 - - name: configure git
42 - run: |
43 - git config --global --add safe.directory '*'
44 - git config --global user.email "ci@cakewallet.com"
45 - git config --global user.name "CakeWallet CI"
46 -
47 - - name: Fetch prebuilt Torch
48 - run: |
49 - set -x -e
50 - pushd scripts
51 - wget https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz -O torch_dart.tar.gz
52 - rm -rf torch_dart
53 - mkdir torch_dart
54 - pushd torch_dart
55 - tar -xzf ../torch_dart.tar.gz
56 - popd
57 - rm ./torch_dart.tar.gz
58 - popd
59 -
60 - - name: Fetch prebuilt Reown
61 - run: |
62 - set -x -e
63 - pushd scripts
64 - # cleaning
65 - rm -rf reown_flutter
66 - rm -f reown_flutter.tar.gz
67 -
68 - wget https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz -O reown_flutter.tar.gz
69 - mkdir reown_flutter
70 - pushd reown_flutter
71 - tar -xzf ../reown_flutter.tar.gz
72 - popd
73 - rm ./reown_flutter.tar.gz
74 - popd
75 -
76 - - name: Build Bitbox Flutter
77 - run: |
78 - set -x -e
79 - pushd scripts
80 - ./build_bitbox_flutter.sh
81 - popd
82 -
83 - - name: Prepare Zcash
84 - run: |
85 - set -x -e
86 - scripts/prepare_zcash.sh
87 -
88 - - name: Execute Build and Setup Commands
89 - run: |
90 - pushd scripts/android
91 - source ./app_env.sh cakewallet
92 - export GITHUB_HUH=yeah
93 - ./app_config.sh
94 - popd
95 -
96 - - name: Install Flutter dependencies
97 - run: |
98 - flutter pub get
99 -
100 - - name: Build generated code
101 - run: |
102 - flutter --version
103 - flutter clean
104 - rm -rf .dart_tool
105 - rm pubspec.lock
106 - flutter pub get
107 - ./model_generator.sh async
108 -
109 - - name: Generate localization
110 - run: |
111 - dart run tool/generate_localization.dart
112 -
113 - - name: Lint
114 - run: |
115 - ABORT_ON_CHANGE=yeah scripts/lint.sh
\ No newline at end of file
9 +# lint:
10 +# runs-on: [Linux, amd64, android]
11 +# container:
12 +# image: ghcr.io/cake-tech/cake_wallet:debian13-flutter3.41.9-ndkr28-go1.24.1-ruststablenightly
13 +# env:
14 +# STORE_PASS: test@cake_wallet
15 +# KEY_PASS: test@cake_wallet
16 +# MONEROC_CACHE_DIR_ROOT: /opt/generic_cache
17 +# BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
18 +# ANDROID_AVD_HOME: /root/.android/avd
19 +# volumes:
20 +# - /opt/cw_cache_android/root/.cache:/root/.cache
21 +# - /opt/cw_cache_android/root/.android/avd/:/root/.android/avd
22 +# - /opt/cw_cache_android/root/.ccache:/root/.ccache
23 +# - /opt/cw_cache_android/root/.pub-cache/:/root/.pub-cache
24 +# - /opt/cw_cache_android/root/.gradle/:/root/.gradle
25 +# - /opt/cw_cache_android/root/.android/:/root/.android
26 +# - /opt/cw_cache_android/root/go/pkg:/root/go/pkg
27 +# - /opt/cw_cache_android/opt/generic_cache:/opt/generic_cache
28 +# - /dev/kvm:/dev/kvm
29 +# - /var/run/docker.sock:/var/run/docker.sock
30 +# strategy:
31 +# matrix:
32 +# api-level: [ 29 ]
33 +#
34 +# steps:
35 +# - name: Fix github actions messing up $HOME...
36 +# run: "echo HOME=/root | sudo tee -a $GITHUB_ENV"
37 +# - uses: actions/checkout@v4
38 +# with:
39 +# ref: ${{ inputs.ref }}
40 +#
41 +# - name: configure git
42 +# run: |
43 +# git config --global --add safe.directory '*'
44 +# git config --global user.email "ci@cakewallet.com"
45 +# git config --global user.name "CakeWallet CI"
46 +#
47 +# - name: Fetch prebuilt Torch
48 +# run: |
49 +# set -x -e
50 +# pushd scripts
51 +# wget https://github.com/MrCyjaneK/torch_dart/releases/download/v1.0.17/torch_dart-v1.0.17.tar.gz -O torch_dart.tar.gz
52 +# rm -rf torch_dart
53 +# mkdir torch_dart
54 +# pushd torch_dart
55 +# tar -xzf ../torch_dart.tar.gz
56 +# popd
57 +# rm ./torch_dart.tar.gz
58 +# popd
59 +#
60 +# - name: Fetch prebuilt Reown
61 +# run: |
62 +# set -x -e
63 +# pushd scripts
64 +# # cleaning
65 +# rm -rf reown_flutter
66 +# rm -f reown_flutter.tar.gz
67 +#
68 +# wget https://github.com/cake-tech/reown_flutter/releases/download/v0.0.4/reown_flutter-v0.0.4.tar.gz -O reown_flutter.tar.gz
69 +# mkdir reown_flutter
70 +# pushd reown_flutter
71 +# tar -xzf ../reown_flutter.tar.gz
72 +# popd
73 +# rm ./reown_flutter.tar.gz
74 +# popd
75 +#
76 +# - name: Build Bitbox Flutter
77 +# run: |
78 +# set -x -e
79 +# pushd scripts
80 +# ./build_bitbox_flutter.sh
81 +# popd
82 +#
83 +# - name: Prepare Zcash
84 +# run: |
85 +# set -x -e
86 +# scripts/prepare_zcash.sh
87 +#
88 +# - name: Execute Build and Setup Commands
89 +# run: |
90 +# pushd scripts/android
91 +# source ./app_env.sh cakewallet
92 +# export GITHUB_HUH=yeah
93 +# ./app_config.sh
94 +# popd
95 +#
96 +# - name: Install Flutter dependencies
97 +# run: |
98 +# flutter pub get
99 +#
100 +# - name: Build generated code
101 +# run: |
102 +# flutter --version
103 +# flutter clean
104 +# rm -rf .dart_tool
105 +# rm pubspec.lock
106 +# flutter pub get
107 +# ./model_generator.sh async
108 +#
109 +# - name: Generate localization
110 +# run: |
111 +# dart run tool/generate_localization.dart
112 +#
113 +# - name: Lint
114 +# run: |
115 +# ABORT_ON_CHANGE=yeah scripts/lint.sh
\ No newline at end of file
cw_bitcoin/lib/address_from_output.dart
+5 -10
@@ -17,21 +17,16 @@ BitcoinBaseAddress addressFromScript(Script script,
17
18 switch (addressType) {
19 case P2pkhAddressType.p2pkh:
20 - return P2pkhAddress.fromScriptPubkey(
21 - script: script, network: BitcoinNetwork.mainnet);
20 + return P2pkhAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
21 case P2shAddressType.p2pkhInP2sh:
22 case P2shAddressType.p2pkInP2sh:
24 - return P2shAddress.fromScriptPubkey(
25 - script: script, network: BitcoinNetwork.mainnet);
23 + return P2shAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
24 case SegwitAddresType.p2wpkh:
27 - return P2wpkhAddress.fromScriptPubkey(
28 - script: script, network: BitcoinNetwork.mainnet);
25 + return P2wpkhAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
26 case SegwitAddresType.p2wsh:
30 - return P2wshAddress.fromScriptPubkey(
31 - script: script, network: BitcoinNetwork.mainnet);
27 + return P2wshAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
28 case SegwitAddresType.p2tr:
33 - return P2trAddress.fromScriptPubkey(
34 - script: script, network: BitcoinNetwork.mainnet);
29 + return P2trAddress.fromScriptPubkey(script: script, network: BitcoinNetwork.mainnet);
30 }
31
32 throw ArgumentError("Invalid script");
cw_bitcoin/lib/bitcoin_address_record.dart
+5 -7
@@ -72,17 +72,16 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
72 required super.type,
73 String? scriptHash,
74 required super.network,
75 - }) {
75 + }) {
76 try {
77 this.scriptHash = scriptHash ??
78 - (network != null ? BitcoinAddressUtils.scriptHash(address, network: network!) : null);
78 + (network != null ? BitcoinAddressUtils.scriptHash(address, network: network!) : null);
79 } catch (e) {
80 printV(e);
81 }
82 -}
82 + }
83
84 static bool _legacyDefaultForType(BitcoinAddressType type) {
85 -
85 // Some address types (p2wpkh, p2wsh) were historically derived from the same account/path as our new standard
86 // but using legacy formats. For these, we default to legacy = false.
87 if (type == SegwitAddresType.p2wpkh || type == SegwitAddresType.p2wsh) return false;
@@ -154,6 +153,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
153 }
154 return scriptHash!;
155 }
156 +
157 @override
158 String get derivationPath {
159 if (type == SegwitAddresType.mweb) {
@@ -162,9 +162,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
162
163 final coinType = _coinTypeForNetwork();
164 final purpose = _purposeForType(type);
165 - final accountPath = isLegacyDerivation
166 - ? electrum_path
167 - : "m/$purpose'/$coinType'/0'";
165 + final accountPath = isLegacyDerivation ? electrum_path : "m/$purpose'/$coinType'/0'";
166
167 final chain = isHidden ? 1 : 0;
168 return "$accountPath/$chain/$index";
cw_bitcoin/lib/bitcoin_amount_format.dart
+2 -2
@@ -7,8 +7,8 @@ final bitcoinAmountFormat = NumberFormat()
7 ..maximumFractionDigits = bitcoinAmountLength
8 ..minimumFractionDigits = 1;
9
10 -String bitcoinAmountToString({required int amount}) => bitcoinAmountFormat.format(
11 - cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider));
10 +String bitcoinAmountToString({required int amount}) =>
11 + bitcoinAmountFormat.format(cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider));
12
13 double bitcoinAmountToDouble({required int amount}) =>
14 cryptoAmountToDouble(amount: amount, divider: bitcoinAmountDivider);
cw_bitcoin/lib/bitcoin_commit_transaction_exception.dart
-1
@@ -5,4 +5,3 @@ class BitcoinCommitTransactionException implements Exception {
5 @override
6 String toString() => errorMessage;
7 }
8 -
cw_bitcoin/lib/bitcoin_transaction_priority.dart
+9 -9
@@ -2,7 +2,8 @@ import 'package:cw_core/transaction_priority.dart';
2 import 'package:flutter/foundation.dart';
3
4 class BitcoinTransactionPriority extends TransactionPriority {
5 - const BitcoinTransactionPriority({required String title, required int raw, String? description, String? hint})
5 + const BitcoinTransactionPriority(
6 + {required String title, required int raw, String? description, String? hint})
7 : super(title: title, raw: raw, description: description, hint: hint);
8
9 static const List<BitcoinTransactionPriority> all = [fast, medium, slow, custom];
@@ -10,10 +11,10 @@ class BitcoinTransactionPriority extends TransactionPriority {
11 BitcoinTransactionPriority(title: 'Slow', description: "2 sat/byte", hint: "~ 24 h", raw: 0);
12 static const BitcoinTransactionPriority medium =
13 BitcoinTransactionPriority(title: 'Medium', description: "3 sat/byte", hint: "~ 1 h", raw: 1);
13 - static const BitcoinTransactionPriority fast =
14 - BitcoinTransactionPriority(title: 'Fast', description: "4 sat/byte", hint: "~ 30 min", raw: 2);
14 + static const BitcoinTransactionPriority fast = BitcoinTransactionPriority(
15 + title: 'Fast', description: "4 sat/byte", hint: "~ 30 min", raw: 2);
16 static const BitcoinTransactionPriority custom =
16 - BitcoinTransactionPriority(title: 'Custom', raw: 3);
17 + BitcoinTransactionPriority(title: 'Custom', raw: 3);
18
19 static BitcoinTransactionPriority deserialize({required int raw}) {
20 switch (raw) {
@@ -116,19 +117,19 @@ class LitecoinTransactionPriority extends BitcoinTransactionPriority {
117
118 return label;
119 }
119 -
120 }
121 +
122 class BitcoinCashTransactionPriority extends BitcoinTransactionPriority {
123 const BitcoinCashTransactionPriority({required String title, required int raw})
124 : super(title: title, raw: raw);
125
126 static const List<BitcoinCashTransactionPriority> all = [fast, medium, slow];
127 static const BitcoinCashTransactionPriority slow =
127 - BitcoinCashTransactionPriority(title: 'Slow', raw: 0);
128 + BitcoinCashTransactionPriority(title: 'Slow', raw: 0);
129 static const BitcoinCashTransactionPriority medium =
129 - BitcoinCashTransactionPriority(title: 'Medium', raw: 1);
130 + BitcoinCashTransactionPriority(title: 'Medium', raw: 1);
131 static const BitcoinCashTransactionPriority fast =
131 - BitcoinCashTransactionPriority(title: 'Fast', raw: 2);
132 + BitcoinCashTransactionPriority(title: 'Fast', raw: 2);
133
134 static BitcoinCashTransactionPriority deserialize({required int raw}) {
135 switch (raw) {
@@ -170,4 +171,3 @@ class BitcoinCashTransactionPriority extends BitcoinTransactionPriority {
171 return label;
172 }
173 }
173 -
cw_bitcoin/lib/bitcoin_wallet.dart
+36 -34
@@ -140,7 +140,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
140 autorun((_) {
141 this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
142 });
143 -
143 +
144 reaction((_) => this.useLightning, (bool useLightning) {
145 if (useLightning && LightningWallet.isAvailable) {
146 if (mnemonic != null) {
@@ -306,28 +306,28 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
306 }
307
308 return BitcoinWallet(
309 - mnemonic: mnemonic,
310 - xpub: keysData.xPub != null ? convertZpubToXpub(keysData.xPub!) : null,
311 - password: password,
312 - passphrase: passphrase,
313 - walletInfo: walletInfo,
314 - derivationInfo: derivationInfo,
315 - unspentCoinsInfo: unspentCoinsInfo,
316 - initialAddresses: snp?.addresses,
317 - initialSilentAddresses: snp?.silentAddresses,
318 - initialSilentAddressIndex: snp?.silentAddressIndex ?? 0,
319 - initialBalance: snp?.balance,
320 - initialLightningBalance: snp?.lightningBalance,
321 - encryptionFileUtils: encryptionFileUtils,
322 - seedBytes: seedBytes,
323 - initialRegularAddressIndex: snp?.regularAddressIndex,
324 - initialChangeAddressIndex: snp?.changeAddressIndex,
325 - addressPageType: snp?.addressPageType,
326 - networkParam: network,
327 - alwaysScan: snp?.alwaysScan,
328 - useLightning: snp?.useLightning,
329 - cachedLightningAddress: snp?.cachedLightningAddress,
330 - payjoinBox: payjoinBox,
309 + mnemonic: mnemonic,
310 + xpub: keysData.xPub != null ? convertZpubToXpub(keysData.xPub!) : null,
311 + password: password,
312 + passphrase: passphrase,
313 + walletInfo: walletInfo,
314 + derivationInfo: derivationInfo,
315 + unspentCoinsInfo: unspentCoinsInfo,
316 + initialAddresses: snp?.addresses,
317 + initialSilentAddresses: snp?.silentAddresses,
318 + initialSilentAddressIndex: snp?.silentAddressIndex ?? 0,
319 + initialBalance: snp?.balance,
320 + initialLightningBalance: snp?.lightningBalance,
321 + encryptionFileUtils: encryptionFileUtils,
322 + seedBytes: seedBytes,
323 + initialRegularAddressIndex: snp?.regularAddressIndex,
324 + initialChangeAddressIndex: snp?.changeAddressIndex,
325 + addressPageType: snp?.addressPageType,
326 + networkParam: network,
327 + alwaysScan: snp?.alwaysScan,
328 + useLightning: snp?.useLightning,
329 + cachedLightningAddress: snp?.cachedLightningAddress,
330 + payjoinBox: payjoinBox,
331 );
332 }
333
@@ -346,12 +346,12 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
346 }
347
348 try {
349 - final lBalance = await lightningWallet!.getBalance();
349 + final lBalance = await lightningWallet!.getBalance();
350
351 - this.balance[CryptoCurrency.btcln] = ElectrumBalance(
352 - confirmed: lBalance,
353 - unconfirmed: Money.zero(CryptoCurrency.btcln),
354 - frozen: Money.zero(CryptoCurrency.btcln));
351 + this.balance[CryptoCurrency.btcln] = ElectrumBalance(
352 + confirmed: lBalance,
353 + unconfirmed: Money.zero(CryptoCurrency.btcln),
354 + frozen: Money.zero(CryptoCurrency.btcln));
355 } catch (e) {
356 printV("Error fetching lightning balance: $e");
357 }
@@ -494,7 +494,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
494 @override
495 Future<PendingTransaction> createTransaction(Object credentials) async {
496 credentials = credentials as BitcoinTransactionCredentials;
497 - final lnAddr = credentials.outputs.first.isParsedAddress ? credentials.outputs.first.extractedAddress! : credentials.outputs.first.address;
497 + final lnAddr = credentials.outputs.first.isParsedAddress
498 + ? credentials.outputs.first.extractedAddress!
499 + : credentials.outputs.first.address;
500
501 final isLNCompatible = await lightningWallet?.isCompatible(lnAddr);
502 if ((credentials.coinTypeToSpendFrom == UnspentCoinType.lightning && lightningWallet != null) ||
@@ -506,12 +508,12 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
508 amount = credentials.outputs.first.cryptoAmount;
509 }
510
509 -
511 return lightningWallet!.createTransaction(
511 - lnAddr,
512 - amount.amount > BigInt.zero ? amount.amount : null,
513 - credentials.priority,
514 - credentials.outputs.first.sendAll,);
512 + lnAddr,
513 + amount.amount > BigInt.zero ? amount.amount : null,
514 + credentials.priority,
515 + credentials.outputs.first.sendAll,
516 + );
517 }
518
519 final tx = (await super.createTransaction(credentials)) as PendingBitcoinTransaction;
cw_bitcoin/lib/bitcoin_wallet_addresses.dart
+3 -5
@@ -137,7 +137,8 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
137 }
138
139 @override
140 - bool containsAddress(String address) => super.containsAddress(address) || address == lightningAddress;
140 + bool containsAddress(String address) =>
141 + super.containsAddress(address) || address == lightningAddress;
142
143 @override
144 String get addressForBuy {
@@ -153,12 +154,9 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
154
155 @override
156 String get addressForExchange {
156 -
157 final current = getFreshAddress();
158 final availableReceiveAddresses = receiveAddresses.where((element) =>
159 - !element.isUsed &&
160 - !element.isHidden &&
161 - !hiddenAddresses.contains(element.address));
159 + !element.isUsed && !element.isHidden && !hiddenAddresses.contains(element.address));
160
161 final bool isSilentPaymentsPage = addressPageType == SilentPaymentsAddresType.p2sp;
162 final bool isLightningPage = addressPageType == LightningAddressType.p2l;
cw_bitcoin/lib/bitcoin_wallet_creation_credentials.dart
+16 -16
@@ -59,27 +59,27 @@ class BitcoinRestoreWalletFromWIFCredentials extends WalletCredentials {
59 }
60
61 class BitcoinWalletFromKeysCredentials extends WalletCredentials {
62 - BitcoinWalletFromKeysCredentials({
63 - required String name,
64 - required String password,
65 - required this.xpub,
66 - WalletInfo? walletInfo,
67 - super.hardwareWalletType
68 - }) : super(name: name, password: password, walletInfo: walletInfo);
62 + BitcoinWalletFromKeysCredentials(
63 + {required String name,
64 + required String password,
65 + required this.xpub,
66 + WalletInfo? walletInfo,
67 + super.hardwareWalletType})
68 + : super(name: name, password: password, walletInfo: walletInfo);
69
70 final String xpub;
71 }
72
73 class LitecoinWalletFromKeysCredentials extends WalletCredentials {
74 - LitecoinWalletFromKeysCredentials({
75 - required String name,
76 - required String password,
77 - required this.xpub,
78 - required this.scanSecret,
79 - required this.spendPubkey,
80 - WalletInfo? walletInfo,
81 - super.hardwareWalletType
82 - }) : super(name: name, password: password, walletInfo: walletInfo);
74 + LitecoinWalletFromKeysCredentials(
75 + {required String name,
76 + required String password,
77 + required this.xpub,
78 + required this.scanSecret,
79 + required this.spendPubkey,
80 + WalletInfo? walletInfo,
81 + super.hardwareWalletType})
82 + : super(name: name, password: password, walletInfo: walletInfo);
83
84 final String xpub;
85 final String scanSecret;
cw_bitcoin/lib/bitcoin_wallet_keys.dart
+5 -8
@@ -1,15 +1,12 @@
1 class BitcoinWalletKeys {
2 - const BitcoinWalletKeys({required this.wif, required this.privateKey, required this.publicKey, required this.xpub});
2 + const BitcoinWalletKeys(
3 + {required this.wif, required this.privateKey, required this.publicKey, required this.xpub});
4
5 final String wif;
6 final String privateKey;
7 final String publicKey;
8 final String xpub;
9
9 - Map<String, String> toJson() => {
10 - 'wif': wif,
11 - 'privateKey': privateKey,
12 - 'publicKey': publicKey,
13 - 'xpub': xpub
14 - };
15 -}
\ No newline at end of file
10 + Map<String, String> toJson() =>
11 + {'wif': wif, 'privateKey': privateKey, 'publicKey': publicKey, 'xpub': xpub};
12 +}
cw_bitcoin/lib/bitcoin_wallet_service.dart
+13 -11
@@ -21,8 +21,7 @@ class BitcoinWalletService extends WalletService<
21 BitcoinRestoreWalletFromSeedCredentials,
22 BitcoinWalletFromKeysCredentials,
23 BitcoinRestoreWalletFromHardware> {
24 - BitcoinWalletService(this.unspentCoinsInfoSource,
25 - this.payjoinSessionSource, this.isDirect);
24 + BitcoinWalletService(this.unspentCoinsInfoSource, this.payjoinSessionSource, this.isDirect);
25
26 final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
27 final Box<PayjoinSession> payjoinSessionSource;
@@ -38,9 +37,12 @@ class BitcoinWalletService extends WalletService<
37
38 final String mnemonic;
39 final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
41 - derivationInfo.derivationType = credentials.derivationInfo?.derivationType ?? derivationInfo.derivationType;
42 - derivationInfo.derivationPath = credentials.derivationInfo?.derivationPath ?? derivationInfo.derivationPath;
43 - derivationInfo.description = credentials.derivationInfo?.description ?? derivationInfo.description;
40 + derivationInfo.derivationType =
41 + credentials.derivationInfo?.derivationType ?? derivationInfo.derivationType;
42 + derivationInfo.derivationPath =
43 + credentials.derivationInfo?.derivationPath ?? derivationInfo.derivationPath;
44 + derivationInfo.description =
45 + credentials.derivationInfo?.description ?? derivationInfo.description;
46 derivationInfo.scriptType = credentials.derivationInfo?.scriptType ?? derivationInfo.scriptType;
47 await derivationInfo.save();
48 switch (derivationInfo.derivationType) {
@@ -119,8 +121,9 @@ class BitcoinWalletService extends WalletService<
121 }
122 await WalletInfo.delete(walletInfo);
123
122 - final unspentCoinsToDelete = unspentCoinsInfoSource.values.where(
123 - (unspentCoin) => unspentCoin.walletId == walletInfo.id).toList();
124 + final unspentCoinsToDelete = unspentCoinsInfoSource.values
125 + .where((unspentCoin) => unspentCoin.walletId == walletInfo.id)
126 + .toList();
127
128 final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
129
@@ -135,11 +138,10 @@ class BitcoinWalletService extends WalletService<
138 final network = isTestnet == true ? BitcoinNetwork.testnet : BitcoinNetwork.mainnet;
139 credentials.walletInfo?.network = network.value;
140 final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
138 - derivationInfo.derivationPath =
139 - credentials.hwAccountData.derivationPath;
140 -
141 + derivationInfo.derivationPath = credentials.hwAccountData.derivationPath;
142 +
143 final xpub = convertAnyToXpub(credentials.hwAccountData.xpub!);
142 -
144 +
145 await credentials.walletInfo!.save();
146 final wallet = await BitcoinWallet(
147 password: credentials.password!,
cw_bitcoin/lib/electrum.dart
+17 -22
@@ -304,9 +304,9 @@ class ElectrumClient {
304 });
305
306 Future<Map<String, List<Map<String, dynamic>>>> getBatchHistory(
307 - List<String> scriptHashes, {
308 - int timeout = 10000,
309 - }) async {
307 + List<String> scriptHashes, {
308 + int timeout = 10000,
309 + }) async {
310 final paramsList = scriptHashes.map((h) => <Object>[h]).toList(growable: false);
311
312 final batchResults = await callBatchWithTimeout(
@@ -342,9 +342,9 @@ class ElectrumClient {
342 }
343
344 Future<Map<String, List<Map<String, dynamic>>>> getBatchUnspent(
345 - List<String> scriptHashes, {
346 - int timeout = 10000,
347 - }) async {
345 + List<String> scriptHashes, {
346 + int timeout = 10000,
347 + }) async {
348 final paramsList = scriptHashes.map((h) => <Object>[h]).toList(growable: false);
349
350 final batchResults = await callBatchWithTimeout(
@@ -380,9 +380,9 @@ class ElectrumClient {
380 }
381
382 Future<Map<String, Map<String, dynamic>>> getBatchBalance(
383 - List<String> scriptHashes, {
384 - int timeout = 10000,
385 - }) async {
383 + List<String> scriptHashes, {
384 + int timeout = 10000,
385 + }) async {
386 final paramsList = scriptHashes.map((h) => <Object>[h]).toList(growable: false);
387
388 final batchResults = await callBatchWithTimeout(
@@ -416,9 +416,9 @@ class ElectrumClient {
416 }
417
418 Future<Map<String, Map<String, dynamic>>> getBatchTransactionVerbose(
419 - List<String> hashes, {
420 - int timeout = 10000,
421 - }) async {
419 + List<String> hashes, {
420 + int timeout = 10000,
421 + }) async {
422 final result = <String, Map<String, dynamic>>{};
423 if (hashes.isEmpty) return result;
424
@@ -443,9 +443,9 @@ class ElectrumClient {
443 }
444
445 Future<Map<String, String?>> getBatchTransactionHex(
446 - List<String> hashes, {
447 - int timeout = 10000,
448 - }) async {
446 + List<String> hashes, {
447 + int timeout = 10000,
448 + }) async {
449 final result = <String, String?>{};
450 if (hashes.isEmpty) return result;
451
@@ -483,12 +483,8 @@ class ElectrumClient {
483 // Build the Batch Array
484 final List<Map<String, dynamic>> batchPayload = [];
485 for (int i = 0; i < paramsList.length; i++) {
486 - batchPayload.add({
487 - "jsonrpc": "2.0",
488 - "method": method,
489 - "params": paramsList[i],
490 - "id": "$batchBaseId-$i"
491 - });
486 + batchPayload.add(
487 + {"jsonrpc": "2.0", "method": method, "params": paramsList[i], "id": "$batchBaseId-$i"});
488 }
489
490 // Register the task
@@ -775,7 +771,6 @@ class ElectrumClient {
771 }
772
773 void _handleResponse(dynamic response) {
778 -
774 // Handle batch response
775 if (response is List) {
776 if (response.isEmpty) return;
cw_bitcoin/lib/electrum_transaction_history.dart
-1
@@ -1,6 +1,5 @@
1 import 'dart:convert';
2
3 -
3 import 'package:cw_bitcoin/electrum_transaction_info.dart';
4 import 'package:cw_core/encryption_file_utils.dart';
5 import 'package:cw_core/pathForWallet.dart';
cw_bitcoin/lib/electrum_transaction_info.dart
+3 -5
@@ -184,15 +184,13 @@ class ElectrumTransactionInfo extends TransactionInfo {
184
185 // MWEB HogEx
186 final isHogExTx = (BtcTransaction tx) {
187 - if (tx.inputs.isEmpty || tx.inputs.first.txIndex > 0 || tx.outputs.isEmpty)
188 - return false;
187 + if (tx.inputs.isEmpty || tx.inputs.first.txIndex > 0 || tx.outputs.isEmpty) return false;
188 final b = tx.outputs.first.scriptPubKey.toBytes();
189 return b.length == 34 && b[0] == 88 && b[1] == 32;
190 };
191 final firstInput = bundle.ins.isNotEmpty ? bundle.ins.first : null;
193 - final isHogEx = firstInput != null &&
194 - isHogExTx(bundle.originalTransaction) &&
195 - isHogExTx(firstInput);
192 + final isHogEx =
193 + firstInput != null && isHogExTx(bundle.originalTransaction) && isHogExTx(firstInput);
194
195 final fee = hasMissingInputTx ? null : inputAmount - totalOutAmount;
196 final walletCurrency = walletTypeToCryptoCurrency(type);
cw_bitcoin/lib/electrum_wallet.dart
+67 -100
@@ -156,7 +156,6 @@ abstract class ElectrumWalletBase
156 sideHdByType[type] = sideHd;
157 }
158 }
159 -
159 }
160
161 int _purposeForType(BitcoinAddressType type) {
@@ -195,7 +194,6 @@ abstract class ElectrumWalletBase
194 /// For LEGACY addresses, returns the wallet's legacy derivation base (derivationInfo.derivationPath)
195 /// which is already the account path used historically (e.g. m/0' or m/84'/0'/0').
196 String _accountDerivationPathForRecord(BaseBitcoinAddressRecord record) {
198 -
197 if (derivationInfo.derivationType == DerivationType.electrum) {
198 return derivationInfo.derivationPath ?? electrum_path; // m/0'
199 }
@@ -807,7 +805,7 @@ abstract class ElectrumWalletBase
805 node!.isElectrs = true;
806 // TODO figure out why condition was needed
807 // if (node!.isInBox) {
810 - node!.save();
808 + node!.save();
809 // }
810 return node!.isElectrs!;
811 }
@@ -873,7 +871,8 @@ abstract class ElectrumWalletBase
871
872 BigInt get networkDustAmount => BigInt.from(546);
873
876 - bool _isBelowDust(BigInt amount) => amount <= networkDustAmount && network != BitcoinNetwork.testnet;
874 + bool _isBelowDust(BigInt amount) =>
875 + amount <= networkDustAmount && network != BitcoinNetwork.testnet;
876
877 UtxoDetails _createUTXOS({
878 required bool sendAll,
@@ -961,8 +960,7 @@ abstract class ElectrumWalletBase
960
961 final baseDerivationPath = _accountDerivationPathForRecord(utx.bitcoinAddressRecord);
962
964 - final derivationPath =
965 - "${_hardenedDerivationPath(baseDerivationPath)}"
963 + final derivationPath = "${_hardenedDerivationPath(baseDerivationPath)}"
964 "/${utx.bitcoinAddressRecord.isHidden ? "1" : "0"}"
965 "/${utx.bitcoinAddressRecord.index}";
966 publicKeys[address.pubKeyHash()] = PublicKeyWithDerivationPath(pubKeyHex, derivationPath);
@@ -1139,7 +1137,8 @@ abstract class ElectrumWalletBase
1137 utxoDetails.utxos.length ==
1138 utxoDetails.availableInputs.length - utxoDetails.unconfirmedCoins.length;
1139
1142 - final amountLeftForChangeAndFee = utxoDetails.allInputsAmount - credentialsAmount.amount.toInt();
1140 + final amountLeftForChangeAndFee =
1141 + utxoDetails.allInputsAmount - credentialsAmount.amount.toInt();
1142
1143 if (amountLeftForChangeAndFee <= 0) {
1144 if (!spendingAllCoins) {
@@ -1175,11 +1174,9 @@ abstract class ElectrumWalletBase
1174 isChange: true,
1175 ));
1176
1178 -
1177 // Must match the address' account root (purpose/coinType) and legacy derivation when applicable.
1178 final changeBaseDerivationPath = _accountDerivationPathForRecord(changeAddress);
1181 - final changeDerivationPath =
1182 - "${_hardenedDerivationPath(changeBaseDerivationPath)}"
1179 + final changeDerivationPath = "${_hardenedDerivationPath(changeBaseDerivationPath)}"
1180 "/${changeAddress.isHidden ? "1" : "0"}"
1181 "/${changeAddress.index}";
1182 utxoDetails.publicKeys[address.pubKeyHash()] =
@@ -1242,7 +1239,8 @@ abstract class ElectrumWalletBase
1239 inputPrivKeyInfos: utxoDetails.inputPrivKeyInfos,
1240 vinOutpoints: utxoDetails.vinOutpoints,
1241 );
1245 - final leftover = utxoDetails.allInputsAmount - credentialsAmount.amount.toInt() - feeNoChange;
1242 + final leftover =
1243 + utxoDetails.allInputsAmount - credentialsAmount.amount.toInt() - feeNoChange;
1244
1245 if (leftover >= 0) {
1246 final finalFee = feeNoChange + leftover; // absorb tiny remainder
@@ -1827,16 +1825,15 @@ abstract class ElectrumWalletBase
1825 }
1826
1827 Future<List<List<BitcoinUnspent>?>> _fetchUnspentsRegular(
1830 - List<BitcoinAddressRecord> addresses,
1831 - ) async {
1828 + List<BitcoinAddressRecord> addresses,
1829 + ) async {
1830 final addressFutures = addresses.map((address) => fetchUnspent(address)).toList();
1831 return Future.wait(addressFutures);
1832 }
1833
1836 -
1834 Future<List<List<BitcoinUnspent>?>> _fetchUnspentsBatch(
1838 - List<BitcoinAddressRecord> addresses,
1839 - ) async {
1835 + List<BitcoinAddressRecord> addresses,
1836 + ) async {
1837 final byScriptHash = <String, BitcoinAddressRecord>{
1838 for (final address in addresses) address.getScriptHash(network): address,
1839 };
@@ -1845,7 +1842,7 @@ abstract class ElectrumWalletBase
1842
1843 try {
1844 final unspentByScriptHash =
1848 - await _processChunksToMap<String, String, List<Map<String, dynamic>>>(
1845 + await _processChunksToMap<String, String, List<Map<String, dynamic>>>(
1846 items: scriptHashes,
1847 chunkSize: addressHistoryChunkSize,
1848 processChunk: _getListUnspentBatch,
@@ -2131,10 +2128,7 @@ abstract class ElectrumWalletBase
2128
2129 final hd = _hdFor(record: addressRecord);
2130
2134 - final privkey = generateECPrivate(
2135 - hd: hd,
2136 - index: addressRecord.index,
2137 - network: network);
2131 + final privkey = generateECPrivate(hd: hd, index: addressRecord.index, network: network);
2132
2133 privateKeys.add(privkey);
2134
@@ -2197,8 +2191,7 @@ abstract class ElectrumWalletBase
2191 final deduction = (outputAmount - networkDustAmount >= remainingFee)
2192 ? remainingFee
2193 : outputAmount - networkDustAmount;
2200 - outputs[i] = BitcoinOutput(
2201 - address: output.address, value: outputAmount - deduction);
2194 + outputs[i] = BitcoinOutput(address: output.address, value: outputAmount - deduction);
2195 remainingFee -= deduction;
2196
2197 if (remainingFee <= BigInt.zero) break;
@@ -2464,7 +2457,8 @@ abstract class ElectrumWalletBase
2457 @override
2458 Future<Map<String, ElectrumTransactionInfo>> fetchTransactions() async {
2459 try {
2467 - final Map<String, ElectrumTransactionInfo> historiesWithDetails = {};;
2460 + final Map<String, ElectrumTransactionInfo> historiesWithDetails = {};
2461 + ;
2462
2463 printV('[BATCH_TEST] Fetching transactions with batch: $shouldUseBatchFetching');
2464
@@ -2473,19 +2467,16 @@ abstract class ElectrumWalletBase
2467 ? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
2468 : fetchTransactionsForAddressType(historiesWithDetails, type)));
2469 } else if (type == WalletType.bitcoinCash) {
2476 - await Future.wait(BITCOIN_CASH_ADDRESS_TYPES
2477 - .map((type) => shouldUseBatchFetching
2470 + await Future.wait(BITCOIN_CASH_ADDRESS_TYPES.map((type) => shouldUseBatchFetching
2471 ? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
2472 : fetchTransactionsForAddressType(historiesWithDetails, type)));
2473 } else if (type == WalletType.litecoin) {
2481 - await Future.wait(LITECOIN_ADDRESS_TYPES
2482 - .where((type) => type != SegwitAddresType.mweb)
2483 - .map((type) => shouldUseBatchFetching
2484 - ? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
2485 - : fetchTransactionsForAddressType(historiesWithDetails, type)));
2474 + await Future.wait(LITECOIN_ADDRESS_TYPES.where((type) => type != SegwitAddresType.mweb).map(
2475 + (type) => shouldUseBatchFetching
2476 + ? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
2477 + : fetchTransactionsForAddressType(historiesWithDetails, type)));
2478 } else if (type == WalletType.dogecoin) {
2487 - await Future.wait(DOGECOIN_ADDRESS_TYPES
2488 - .map((type) => shouldUseBatchFetching
2479 + await Future.wait(DOGECOIN_ADDRESS_TYPES.map((type) => shouldUseBatchFetching
2480 ? fetchTransactionsForAddressTypeBatch(historiesWithDetails, type)
2481 : fetchTransactionsForAddressType(historiesWithDetails, type)));
2482 }
@@ -2633,8 +2624,7 @@ abstract class ElectrumWalletBase
2624 }
2625
2626 Future<void> fetchTransactionsForAddressTypeBatch(
2636 - Map<String, ElectrumTransactionInfo> historiesWithDetails,
2637 - BitcoinAddressType type) async {
2627 + Map<String, ElectrumTransactionInfo> historiesWithDetails, BitcoinAddressType type) async {
2628 final addressesByType =
2629 walletAddresses.allAddresses.where((addr) => addr.type == type).toList();
2630 final receiveAddresses = addressesByType.where((addr) => !addr.isHidden).toList();
@@ -2676,14 +2666,13 @@ abstract class ElectrumWalletBase
2666 );
2667 }
2668
2679 -
2669 Future<void> fetchTransactionsForAddressesBranchBatch(
2681 - Map<String, ElectrumTransactionInfo> historiesWithDetails,
2682 - BitcoinAddressType type,
2683 - List<BitcoinAddressRecord> branchAddresses, {
2684 - required bool isHidden,
2685 - required bool isLegacyDerivation,
2686 - }) async {
2670 + Map<String, ElectrumTransactionInfo> historiesWithDetails,
2671 + BitcoinAddressType type,
2672 + List<BitcoinAddressRecord> branchAddresses, {
2673 + required bool isHidden,
2674 + required bool isLegacyDerivation,
2675 + }) async {
2676 if (branchAddresses.isEmpty) return;
2677
2678 final tip = await getCurrentChainTip();
@@ -2714,7 +2703,6 @@ abstract class ElectrumWalletBase
2703
2704 if (!shouldDiscover) return;
2705
2717 -
2706 final newAddresses = await walletAddresses.discoverAddressesBatch(
2707 currentBranch,
2708 isHidden,
@@ -2756,9 +2744,7 @@ abstract class ElectrumWalletBase
2744 }
2745
2746 Future<Map<String, ElectrumTransactionInfo>> _fetchBatchAddressHistory(
2759 - List<BitcoinAddressRecord> addressRecords,
2760 - int? currentHeight,
2761 - int historyChunkSize) async {
2747 + List<BitcoinAddressRecord> addressRecords, int? currentHeight, int historyChunkSize) async {
2748 String lastTxId = '';
2749 bool didUpdateHistory = false;
2750
@@ -2769,11 +2755,8 @@ abstract class ElectrumWalletBase
2755 final scriptHashes = addressRecords.map((a) => a.getScriptHash(network)).toList();
2756
2757 final historyByScriptHash =
2772 - await _processChunksToMap<String, String, List<Map<String, dynamic>>>(
2773 - items: scriptHashes,
2774 - chunkSize: historyChunkSize,
2775 - processChunk: _getHistoryBatch
2776 - );
2758 + await _processChunksToMap<String, String, List<Map<String, dynamic>>>(
2759 + items: scriptHashes, chunkSize: historyChunkSize, processChunk: _getHistoryBatch);
2760
2761 // Map scriptHash -> addressRecord
2762 final byScriptHash = <String, BitcoinAddressRecord>{};
@@ -2869,8 +2852,7 @@ abstract class ElectrumWalletBase
2852 .toList(growable: false);
2853
2854 final heightsByHash = <String, int?>{
2872 - for (final e in chunkHistory)
2873 - (e['tx_hash'] as String): (e['height'] as int?),
2855 + for (final e in chunkHistory) (e['tx_hash'] as String): (e['height'] as int?),
2856 };
2857
2858 final infosByHash = await fetchTransactionInfoBatch(
@@ -2909,40 +2891,35 @@ abstract class ElectrumWalletBase
2891 }
2892 }
2893
2912 - Future<Map<String, Map<String, dynamic>>> _getTransactionVerboseBatch(
2913 - List<String> hashes) {
2894 + Future<Map<String, Map<String, dynamic>>> _getTransactionVerboseBatch(List<String> hashes) {
2895 return electrumClient.getBatchTransactionVerbose(
2896 hashes,
2897 timeout: transactionBatchTimeoutMs,
2898 );
2899 }
2900
2920 - Future<Map<String, String?>> _getTransactionHexBatch(
2921 - List<String> hashes) {
2901 + Future<Map<String, String?>> _getTransactionHexBatch(List<String> hashes) {
2902 return electrumClient.getBatchTransactionHex(
2903 hashes,
2904 timeout: transactionBatchTimeoutMs,
2905 );
2906 }
2907
2928 - Future<Map<String, List<Map<String, dynamic>>>> _getHistoryBatch(
2929 - List<String> scriptHashes) {
2908 + Future<Map<String, List<Map<String, dynamic>>>> _getHistoryBatch(List<String> scriptHashes) {
2909 return electrumClient.getBatchHistory(
2910 scriptHashes,
2911 timeout: transactionBatchTimeoutMs,
2912 );
2913 }
2914
2936 - Future<Map<String, List<Map<String, dynamic>>>> _getListUnspentBatch(
2937 - List<String> scriptHashes) {
2915 + Future<Map<String, List<Map<String, dynamic>>>> _getListUnspentBatch(List<String> scriptHashes) {
2916 return electrumClient.getBatchUnspent(
2917 scriptHashes,
2918 timeout: transactionBatchTimeoutMs,
2919 );
2920 }
2921
2944 - Future<Map<String, Map<String, dynamic>>> _getBalanceBatch(
2945 - List<String> scriptHashes) {
2922 + Future<Map<String, Map<String, dynamic>>> _getBalanceBatch(List<String> scriptHashes) {
2923 return electrumClient.getBatchBalance(
2924 scriptHashes,
2925 timeout: transactionBatchTimeoutMs,
@@ -2956,8 +2933,7 @@ abstract class ElectrumWalletBase
2933 Duration retryDelay = const Duration(seconds: 2),
2934 }) async {
2935 final result = <String, ElectrumTransactionInfo?>{};
2959 - final uniqueHashes =
2960 - hashes.map((h) => h.trim()).where((h) => h.isNotEmpty).toSet().toList();
2936 + final uniqueHashes = hashes.map((h) => h.trim()).where((h) => h.isNotEmpty).toSet().toList();
2937
2938 if (uniqueHashes.isEmpty) return result;
2939
@@ -2990,9 +2966,8 @@ abstract class ElectrumWalletBase
2966 required Map<String, int?>? heightsByHash,
2967 }) async {
2968 for (var i = 0; i < txIds.length; i += transactionChunkSize) {
2993 - final end = (i + transactionChunkSize < txIds.length)
2994 - ? i + transactionChunkSize
2995 - : txIds.length;
2969 + final end =
2970 + (i + transactionChunkSize < txIds.length) ? i + transactionChunkSize : txIds.length;
2971 final chunk = txIds.sublist(i, end);
2972
2973 final bundlesByHash = await getTransactionExpandedBatch(
@@ -3024,9 +2999,8 @@ abstract class ElectrumWalletBase
2999 }
3000 }
3001
3027 - Future<Map<String, ElectrumTransactionBundle>> getTransactionExpandedBatch({
3028 - required List<String> hashes,
3029 - Map<String, int?>? heightsByHash}) async {
3002 + Future<Map<String, ElectrumTransactionBundle>> getTransactionExpandedBatch(
3003 + {required List<String> hashes, Map<String, int?>? heightsByHash}) async {
3004 final bundles = <String, ElectrumTransactionBundle>{};
3005 if (hashes.isEmpty) return bundles;
3006
@@ -3062,8 +3036,8 @@ abstract class ElectrumWalletBase
3036
3037 Future<Map<String, Map<String, dynamic>>> _fetchTransactionVerboseBatch(
3038 List<String> txIds) async {
3065 -
3066 - final verboseTransactionByHash = await _processChunksToMap<String, String, Map<String, dynamic>>(
3039 + final verboseTransactionByHash =
3040 + await _processChunksToMap<String, String, Map<String, dynamic>>(
3041 items: txIds,
3042 chunkSize: transactionChunkSize,
3043 processChunk: _getTransactionVerboseBatch,
@@ -3100,8 +3074,8 @@ abstract class ElectrumWalletBase
3074 }
3075
3076 Map<String, BtcTransaction> _parseTransactions(
3103 - Map<String, Map<String, dynamic>> verboseByHash,
3104 - ) {
3077 + Map<String, Map<String, dynamic>> verboseByHash,
3078 + ) {
3079 final result = <String, BtcTransaction>{};
3080
3081 for (final entry in verboseByHash.entries) {
@@ -3116,10 +3090,9 @@ abstract class ElectrumWalletBase
3090 return result;
3091 }
3092
3119 -
3093 Map<String, List<String>> _collectInputTxIdsByHash(
3121 - Map<String, BtcTransaction> originalByHash,
3122 - ) {
3094 + Map<String, BtcTransaction> originalByHash,
3095 + ) {
3096 final inputTxIdsByHash = <String, List<String>>{};
3097
3098 for (final entry in originalByHash.entries) {
@@ -3201,8 +3174,8 @@ abstract class ElectrumWalletBase
3174 }
3175
3176 Future<Map<int, int>> _fetchBlockTimestampsFromMempoolByHeights(
3204 - Set<int> heights,
3205 - ) async {
3177 + Set<int> heights,
3178 + ) async {
3179 final out = <int, int>{};
3180 if (heights.isEmpty) return out;
3181 if (!(await checkIfMempoolAPIIsEnabled())) return out;
@@ -3212,10 +3185,10 @@ abstract class ElectrumWalletBase
3185 try {
3186 final blockHashResp = await ProxyWrapper()
3187 .get(
3215 - clearnetUri: Uri.parse(
3216 - 'https://mempool.cakewallet.com/api/v1/block-height/$h',
3217 - ),
3218 - )
3188 + clearnetUri: Uri.parse(
3189 + 'https://mempool.cakewallet.com/api/v1/block-height/$h',
3190 + ),
3191 + )
3192 .timeout(const Duration(seconds: 15));
3193
3194 if (blockHashResp.statusCode != 200 || blockHashResp.body.isEmpty) return;
@@ -3225,10 +3198,10 @@ abstract class ElectrumWalletBase
3198
3199 final blockResp = await ProxyWrapper()
3200 .get(
3228 - clearnetUri: Uri.parse(
3229 - 'https://mempool.cakewallet.com/api/v1/block/$blockHash',
3230 - ),
3231 - )
3201 + clearnetUri: Uri.parse(
3202 + 'https://mempool.cakewallet.com/api/v1/block/$blockHash',
3203 + ),
3204 + )
3205 .timeout(const Duration(seconds: 15));
3206
3207 if (blockResp.statusCode != 200 || blockResp.body.isEmpty) return;
@@ -3276,7 +3249,6 @@ abstract class ElectrumWalletBase
3249 return result;
3250 }
3251
3279 -
3252 Future<void> updateTransactions() async {
3253 printV("updateTransactions() called!");
3254 try {
@@ -3368,8 +3340,7 @@ abstract class ElectrumWalletBase
3340 }
3341
3342 try {
3371 - final balancesByScriptHash =
3372 - await _processChunksToMap<String, String, Map<String, dynamic>>(
3343 + final balancesByScriptHash = await _processChunksToMap<String, String, Map<String, dynamic>>(
3344 items: scriptHashes,
3345 chunkSize: addressHistoryChunkSize,
3346 processChunk: _getBalanceBatch,
@@ -3415,7 +3386,8 @@ abstract class ElectrumWalletBase
3386 ? await fetchBalancesBatch(addresses)
3387 : await fetchBalancesRegular(addresses);
3388
3418 - printV('Fetched balances for ${addresses.length} addresses. Batch fetching: $shouldUseBatchFetching');
3389 + printV(
3390 + 'Fetched balances for ${addresses.length} addresses. Batch fetching: $shouldUseBatchFetching');
3391
3392 var totalFrozen = 0;
3393 var totalConfirmed = 0;
@@ -3544,17 +3516,14 @@ abstract class ElectrumWalletBase
3516 // that matches this received transaction, mark it as being from a peg out:
3517 for (final tx2 in transactionHistory.transactions.values) {
3518 final heightDiff = ((tx2.height ?? 0) - (tx.height ?? 0)).abs();
3547 - // this isn't a perfect matching algorithm since we don't have the right input/output information from these transaction models (the addresses are in different formats), but this should be more than good enough for now as it's extremely unlikely a user receives the EXACT same amount from 2 different sources and one of them is a peg out and the other isn't WITHIN 5 blocks of each other
3548 - if (tx2.additionalInfo["isPegOut"] == true &&
3549 - tx2.amount == tx.amount &&
3550 - heightDiff <= 5) {
3519 + // this isn't a perfect matching algorithm since we don't have the right input/output information from these transaction models (the addresses are in different formats), but this should be more than good enough for now as it's extremely unlikely a user receives the EXACT same amount from 2 different sources and one of them is a peg out and the other isn't WITHIN 5 blocks of each other
3520 + if (tx2.additionalInfo["isPegOut"] == true && tx2.amount == tx.amount && heightDiff <= 5) {
3521 tx.additionalInfo["fromPegOut"] = true;
3522 }
3523 }
3524 }
3525
3526 Future<void> checkIfBatchSupported() async {
3557 -
3527 if (_isBatchSupported != null) {
3528 printV('[BATCH_TEST] Already checked: $_isBatchSupported');
3529 return;
@@ -3580,9 +3549,7 @@ abstract class ElectrumWalletBase
3549 );
3550
3551 final hasError = result.any((item) =>
3583 - item is Map<String, dynamic> &&
3584 - item.containsKey('error') &&
3585 - item['error'] != null);
3552 + item is Map<String, dynamic> && item.containsKey('error') && item['error'] != null);
3553
3554 if (hasError) {
3555 _isBatchSupported = false;
cw_bitcoin/lib/electrum_wallet_addresses.dart
+111 -105
@@ -195,13 +195,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
195 }
196
197 if (addressPageType == LightningAddressType.p2l) {
198 - return lightningAddress ??
199 - "Error: Unable to fetch your Lightning address, please check your network connection.";
198 + return lightningAddress ??
199 + "Error: Unable to fetch your Lightning address, please check your network connection.";
200 }
201
202 - final typeMatchingAddressesAll = _addresses
203 - .where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr))
204 - .toList();
202 + final typeMatchingAddressesAll =
203 + _addresses.where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr)).toList();
204
205 // Prefer standard derivation addresses for the current/active address,
206 // but keep legacy addresses present in the overall address lists.
@@ -210,8 +209,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
209 ...typeMatchingAddressesAll.where((a) => a.isLegacyDerivation),
210 ];
211
213 - final typeMatchingReceiveAddressesAll =
214 - typeMatchingAddressesAll.where((addr) => !addr.isUsed && !hiddenAddresses.contains(addr.address)).toList();
212 + final typeMatchingReceiveAddressesAll = typeMatchingAddressesAll
213 + .where((addr) => !addr.isUsed && !hiddenAddresses.contains(addr.address))
214 + .toList();
215 final typeMatchingReceiveAddresses = <BitcoinAddressRecord>[
216 ...typeMatchingReceiveAddressesAll.where((a) => !a.isLegacyDerivation),
217 ...typeMatchingReceiveAddressesAll.where((a) => a.isLegacyDerivation),
@@ -354,34 +354,35 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
354 return acc;
355 });
356
357 - @override
358 - Future<void> init() async {
359 - if (walletInfo.type == WalletType.bitcoinCash) {
360 - await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
361 - } else if (walletInfo.type == WalletType.litecoin) {
362 - await _generateInitialAddresses(type: SegwitAddresType.p2wpkh);
363 - if ((Platform.isAndroid || Platform.isIOS) && !isHardwareWallet) {
364 - await _generateInitialAddresses(type: SegwitAddresType.mweb);
365 - }
366 - } else if (walletInfo.type == WalletType.dogecoin) {
357 + @override
358 + Future<void> init() async {
359 + if (walletInfo.type == WalletType.bitcoinCash) {
360 + await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
361 + } else if (walletInfo.type == WalletType.litecoin) {
362 + await _generateInitialAddresses(type: SegwitAddresType.p2wpkh);
363 + if ((Platform.isAndroid || Platform.isIOS) && !isHardwareWallet) {
364 + await _generateInitialAddresses(type: SegwitAddresType.mweb);
365 + }
366 + } else if (walletInfo.type == WalletType.dogecoin) {
367 + await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
368 + } else if (walletInfo.type == WalletType.bitcoin) {
369 + await _generateInitialAddresses(isLegacyDerivation: true);
370 + await _generateInitialAddresses();
371 + if (!isHardwareWallet) {
372 + await _generateInitialAddresses(type: P2pkhAddressType.p2pkh, isLegacyDerivation: true);
373 await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
368 - } else if (walletInfo.type == WalletType.bitcoin) {
369 - await _generateInitialAddresses(isLegacyDerivation: true);
370 - await _generateInitialAddresses();
371 - if (!isHardwareWallet) {
372 - await _generateInitialAddresses(type: P2pkhAddressType.p2pkh, isLegacyDerivation: true);
373 - await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
374
375 - await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh, isLegacyDerivation: true);
376 - await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
375 + await _generateInitialAddresses(
376 + type: P2shAddressType.p2wpkhInP2sh, isLegacyDerivation: true);
377 + await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
378
378 - await _generateInitialAddresses(type: SegwitAddresType.p2tr, isLegacyDerivation: true);
379 - await _generateInitialAddresses(type: SegwitAddresType.p2tr);
379 + await _generateInitialAddresses(type: SegwitAddresType.p2tr, isLegacyDerivation: true);
380 + await _generateInitialAddresses(type: SegwitAddresType.p2tr);
381
381 - await _generateInitialAddresses(type: SegwitAddresType.p2wsh, isLegacyDerivation: true);
382 - await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
383 - }
382 + await _generateInitialAddresses(type: SegwitAddresType.p2wsh, isLegacyDerivation: true);
383 + await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
384 }
385 + }
386
387 updateAddressesByMatch();
388 updateReceiveAddresses();
@@ -680,9 +681,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
681 @action
682 void updateReceiveAddresses() {
683 receiveAddresses.removeRange(0, receiveAddresses.length);
683 - final newAddresses = _addresses.where((addressRecord) =>
684 - !addressRecord.isHidden &&
685 - !addressRecord.isUsed);
684 + final newAddresses =
685 + _addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed);
686 receiveAddresses.addAll(newAddresses);
687 }
688
@@ -699,12 +699,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
699
700 @action
701 Future<void> discoverAddresses(
702 - List<BitcoinAddressRecord> addressList,
703 - bool isHidden,
704 - Future<String?> Function(BitcoinAddressRecord) getAddressHistory, {
705 - BitcoinAddressType type = SegwitAddresType.p2wpkh,
706 - required bool isLegacyDerivation,
707 - }) async {
702 + List<BitcoinAddressRecord> addressList,
703 + bool isHidden,
704 + Future<String?> Function(BitcoinAddressRecord) getAddressHistory, {
705 + BitcoinAddressType type = SegwitAddresType.p2wpkh,
706 + required bool isLegacyDerivation,
707 + }) async {
708 final newAddresses = await _createNewAddresses(
709 gap,
710 startIndex: addressList.length,
@@ -716,8 +716,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
716 addAddresses(newAddresses);
717 addressList.addAll(newAddresses);
718
719 - final addressesWithHistory =
720 - await Future.wait(newAddresses.map(getAddressHistory));
719 + final addressesWithHistory = await Future.wait(newAddresses.map(getAddressHistory));
720 final isLastAddressUsed = addressesWithHistory.last != null;
721
722 if (isLastAddressUsed) {
@@ -733,12 +732,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
732
733 @action
734 Future<List<BitcoinAddressRecord>> discoverAddressesBatch(
736 - List<BitcoinAddressRecord> addressList,
737 - bool isHidden,
738 - Future<Set<String>> Function(List<BitcoinAddressRecord>) getUsedAddresses, {
739 - BitcoinAddressType type = SegwitAddresType.p2wpkh,
740 - required bool isLegacyDerivation,
741 - }) async {
735 + List<BitcoinAddressRecord> addressList,
736 + bool isHidden,
737 + Future<Set<String>> Function(List<BitcoinAddressRecord>) getUsedAddresses, {
738 + BitcoinAddressType type = SegwitAddresType.p2wpkh,
739 + required bool isLegacyDerivation,
740 + }) async {
741 final newAddresses = await _createNewAddresses(
742 gap,
743 startIndex: addressList.length,
@@ -750,8 +749,8 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
749
750 final usedAddresses = await getUsedAddresses(newAddresses);
751
753 - final hasUsedAddressInGap = newAddresses.any(
754 - (addressRecord) => usedAddresses.contains(addressRecord.address));
752 + final hasUsedAddressInGap =
753 + newAddresses.any((addressRecord) => usedAddresses.contains(addressRecord.address));
754
755 if (!hasUsedAddressInGap) {
756 return newAddresses;
@@ -770,64 +769,69 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
769 return [...newAddresses, ...moreNewAddresses];
770 }
771
773 -
772 Future<void> _generateInitialAddresses(
775 - {BitcoinAddressType type = SegwitAddresType.p2wpkh,
776 - bool isLegacyDerivation = false }) async {
777 -
778 - // Legacy derivation produces the same addresses as standard for these types.
779 - // Don't generate a legacy set to avoid duplicates.
780 - if (isLegacyDerivation && (type == SegwitAddresType.p2wpkh || type == SegwitAddresType.p2wsh)) {
781 - return;
782 - }
773 + {BitcoinAddressType type = SegwitAddresType.p2wpkh, bool isLegacyDerivation = false}) async {
774 + // Legacy derivation produces the same addresses as standard for these types.
775 + // Don't generate a legacy set to avoid duplicates.
776 + if (isLegacyDerivation && (type == SegwitAddresType.p2wpkh || type == SegwitAddresType.p2wsh)) {
777 + return;
778 + }
779
784 - var countOfReceiveAddresses = 0;
785 - var countOfHiddenAddresses = 0;
780 + var countOfReceiveAddresses = 0;
781 + var countOfHiddenAddresses = 0;
782
787 - _addresses.forEach((addr) {
788 - if (addr.type == type && addr.isLegacyDerivation == isLegacyDerivation) {
789 - if (addr.isHidden) {
790 - countOfHiddenAddresses += 1;
791 - } else {
792 - countOfReceiveAddresses += 1;
793 - }
783 + _addresses.forEach((addr) {
784 + if (addr.type == type && addr.isLegacyDerivation == isLegacyDerivation) {
785 + if (addr.isHidden) {
786 + countOfHiddenAddresses += 1;
787 + } else {
788 + countOfReceiveAddresses += 1;
789 }
795 - });
796 -
797 - if (countOfReceiveAddresses < defaultReceiveAddressesCount) {
798 - final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses;
799 - final newAddresses = await _createNewAddresses(addressesCount,
800 - startIndex: countOfReceiveAddresses, isHidden: false, type: type, isLegacyDerivation: isLegacyDerivation);
801 - addAddresses(newAddresses);
790 }
791 + });
792
804 - if (countOfHiddenAddresses < defaultChangeAddressesCount) {
805 - final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses;
806 - final newAddresses = await _createNewAddresses(addressesCount,
807 - startIndex: countOfHiddenAddresses, isHidden: true, type: type, isLegacyDerivation: isLegacyDerivation);
808 - addAddresses(newAddresses);
809 - }
793 + if (countOfReceiveAddresses < defaultReceiveAddressesCount) {
794 + final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses;
795 + final newAddresses = await _createNewAddresses(addressesCount,
796 + startIndex: countOfReceiveAddresses,
797 + isHidden: false,
798 + type: type,
799 + isLegacyDerivation: isLegacyDerivation);
800 + addAddresses(newAddresses);
801 }
802
812 - Future<List<BitcoinAddressRecord>> _createNewAddresses(int count,
813 - {int startIndex = 0, bool isHidden = false, BitcoinAddressType? type, bool isLegacyDerivation = false}) async {
814 - final list = <BitcoinAddressRecord>[];
815 -
816 - for (var i = startIndex; i < count + startIndex; i++) {
817 -
818 - final addrType = type ?? addressPageType;
819 - final hd = _hdFor(isHidden: isHidden, type: addrType, isLegacyDerivation: isLegacyDerivation);
803 + if (countOfHiddenAddresses < defaultChangeAddressesCount) {
804 + final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses;
805 + final newAddresses = await _createNewAddresses(addressesCount,
806 + startIndex: countOfHiddenAddresses,
807 + isHidden: true,
808 + type: type,
809 + isLegacyDerivation: isLegacyDerivation);
810 + addAddresses(newAddresses);
811 + }
812 + }
813
821 - final address = BitcoinAddressRecord(
822 - await getAddressAsync(index: i, hd: hd, addressType: addrType),
823 - index: i,
824 - isHidden: isHidden,
825 - isLegacyDerivation: isLegacyDerivation,
826 - type: addrType,
827 - network: network,
828 - );
829 - list.add(address);
830 - }
814 + Future<List<BitcoinAddressRecord>> _createNewAddresses(int count,
815 + {int startIndex = 0,
816 + bool isHidden = false,
817 + BitcoinAddressType? type,
818 + bool isLegacyDerivation = false}) async {
819 + final list = <BitcoinAddressRecord>[];
820 +
821 + for (var i = startIndex; i < count + startIndex; i++) {
822 + final addrType = type ?? addressPageType;
823 + final hd = _hdFor(isHidden: isHidden, type: addrType, isLegacyDerivation: isLegacyDerivation);
824 +
825 + final address = BitcoinAddressRecord(
826 + await getAddressAsync(index: i, hd: hd, addressType: addrType),
827 + index: i,
828 + isHidden: isHidden,
829 + isLegacyDerivation: isLegacyDerivation,
830 + type: addrType,
831 + network: network,
832 + );
833 + list.add(address);
834 + }
835
836 return list;
837 }
@@ -868,8 +872,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
872 return;
873 }
874
871 - final mainHd = _hdFor(isHidden: false, type: element.type, isLegacyDerivation: element.isLegacyDerivation);
872 - final sideHd = _hdFor(isHidden: true, type: element.type, isLegacyDerivation: element.isLegacyDerivation);
875 + final mainHd = _hdFor(
876 + isHidden: false, type: element.type, isLegacyDerivation: element.isLegacyDerivation);
877 + final sideHd = _hdFor(
878 + isHidden: true, type: element.type, isLegacyDerivation: element.isLegacyDerivation);
879 if (!element.isHidden &&
880 element.address !=
881 await getAddressAsync(index: element.index, hd: mainHd, addressType: element.type)) {
@@ -897,7 +903,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
903 return _isAddressByType(addressRecord, addressPageType);
904 }
905
900 - bool _isAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) => addr.type == type;
906 + bool _isAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) => addr.type == type;
907
908 bool _isUnusedReceiveAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) =>
909 !addr.isHidden && !addr.isUsed && addr.type == type;
@@ -907,9 +913,9 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
913 final addressRecord = silentAddresses.firstWhere((addressRecord) =>
914 addressRecord.type == SilentPaymentsAddresType.p2sp && addressRecord.address == address);
915
910 - silentAddresses.remove(addressRecord);
911 - updateAddressesByMatch();
912 - }
916 + silentAddresses.remove(addressRecord);
917 + updateAddressesByMatch();
918 + }
919
920 Bip32Slip10Secp256k1 _hdFor({
921 required bool isHidden,
@@ -923,7 +929,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
929 if (hd == null) throw Exception("HD not found for type $type");
930 return hd;
931 }
926 -
932 +
933 @action
934 Future<void> setLightningAddress(String walletName, {String newAddress = ""}) async {
935 if (lightningWallet == null) return;
cw_bitcoin/lib/exceptions.dart
+1 -1
@@ -30,7 +30,7 @@ class BitcoinTransactionCommitFailed extends TransactionCommitFailed {
30
31 @override
32 String toString() {
33 - return errorMessage??"unknown error";
33 + return errorMessage ?? "unknown error";
34 }
35 }
36
cw_bitcoin/lib/hardware/bitbox_service.dart
+2 -1
@@ -67,7 +67,8 @@ class BitcoinBitboxService extends HardwareWalletService with BitcoinHardwareWal
67 Future<Uint8List> getMasterFingerprint() => manager.getMasterFingerprint();
68 }
69
70 -class LitecoinBitboxService extends HardwareWalletService with BitcoinHardwareWalletService, LitecoinHardwareWalletService {
70 +class LitecoinBitboxService extends HardwareWalletService
71 + with BitcoinHardwareWalletService, LitecoinHardwareWalletService {
72 LitecoinBitboxService(this.manager);
73
74 final BitboxManager manager;
cw_bitcoin/lib/hardware/litecoin_ledger_service.dart
+3 -3
@@ -12,7 +12,8 @@ import 'package:cw_core/hardware/hardware_wallet_service.dart';
12 import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
13 import 'package:ledger_litecoin/ledger_litecoin.dart';
14
15 -class LitecoinLedgerService extends HardwareWalletService with BitcoinHardwareWalletService, LitecoinHardwareWalletService {
15 +class LitecoinLedgerService extends HardwareWalletService
16 + with BitcoinHardwareWalletService, LitecoinHardwareWalletService {
17 LitecoinLedgerService(this.ledgerConnection)
18 : litecoinLedgerApp = LitecoinLedgerApp(ledgerConnection);
19
@@ -53,7 +54,6 @@ class LitecoinLedgerService extends HardwareWalletService with BitcoinHardwareWa
54 required List<PSBTReadyUtxoWithAddress> inputs,
55 required Map<String, PublicKeyWithDerivationPath> publicKeys,
56 }) {
56 -
57 final readyInputs = <LedgerTransaction>[];
58 for (final utxo in inputs) {
59 final publicKeyAndDerivationPath = publicKeys[utxo.ownerDetails.address.pubKeyHash()]!;
@@ -77,7 +77,7 @@ class LitecoinLedgerService extends HardwareWalletService with BitcoinHardwareWa
77 inputs: readyInputs,
78 outputs: outputs
79 .map((e) => TransactionOutput.fromBigInt((e as BitcoinOutput).value,
80 - Uint8List.fromList(e.address.toScriptPubKey().toBytes())))
80 + Uint8List.fromList(e.address.toScriptPubKey().toBytes())))
81 .toList(),
82 changePath: changePath,
83 sigHashType: 0x01,
cw_bitcoin/lib/lightning/lightning_wallet.dart
+17 -15
@@ -90,8 +90,7 @@ class LightningWallet {
90 lnurlDomain: lnurlDomain,
91 apiKey: apiKey,
92 privateEnabledDefault: true,
93 - maxDepositClaimFee: MaxFee.rate(satPerVbyte: BigInt.from(5))
94 - );
93 + maxDepositClaimFee: MaxFee.rate(satPerVbyte: BigInt.from(5)));
94
95 final connectRequest = ConnectRequest(
96 config: config,
@@ -105,8 +104,7 @@ class LightningWallet {
104 _logStream ??= initLogging().asBroadcastStream();
105
106 try {
108 - final logFile = File("$appPath/lightning.log")
109 - ..createSync();
107 + final logFile = File("$appPath/lightning.log")..createSync();
108 _subscribeToLogStream(logFile);
109 } catch (e) {
110 printV(e);
@@ -198,15 +196,17 @@ class LightningWallet {
196 }
197 }
198
201 - Future<PendingLightningTransaction> createTransaction(
202 - String address, BigInt? amountSats, BitcoinTransactionPriority? priority, bool feesIncluded) async {
199 + Future<PendingLightningTransaction> createTransaction(String address, BigInt? amountSats,
200 + BitcoinTransactionPriority? priority, bool feesIncluded) async {
201 final inputType = await sdk.parse(input: address);
202
203 final feePolicy = feesIncluded ? FeePolicy.feesIncluded : FeePolicy.feesExcluded;
204
205 if (inputType is InputType_Bolt11Invoice) {
206 final request = PrepareSendPaymentRequest(
209 - paymentRequest: inputType.field0.invoice.bolt11, amount: amountSats, feePolicy: feePolicy);
207 + paymentRequest: inputType.field0.invoice.bolt11,
208 + amount: amountSats,
209 + feePolicy: feePolicy);
210 final prepareResponse = await sdk.prepareSendPayment(request: request);
211
212 final paymentMethod = prepareResponse.paymentMethod;
@@ -392,14 +392,16 @@ class LightningWallet {
392 return _getElectrumTransactionInfoFromPayment(response.payment);
393 }
394
395 - Future<String> refundDeposit(String txId, int vout, String destinationAddress,
396 - BigInt feeRate) async {
397 - final response = await sdk.refundDeposit(request: RefundDepositRequest(
398 - txid: txId,
399 - vout: vout,
400 - destinationAddress: destinationAddress,
401 - fee: Fee.rate(satPerVbyte: feeRate),
402 - ),);
395 + Future<String> refundDeposit(
396 + String txId, int vout, String destinationAddress, BigInt feeRate) async {
397 + final response = await sdk.refundDeposit(
398 + request: RefundDepositRequest(
399 + txid: txId,
400 + vout: vout,
401 + destinationAddress: destinationAddress,
402 + fee: Fee.rate(satPerVbyte: feeRate),
403 + ),
404 + );
405
406 return response.txHex;
407 }
cw_bitcoin/lib/lightning/pending_lightning_transaction.dart
+1 -2
@@ -10,10 +10,9 @@ class PendingLightningTransaction with PendingTransaction {
10 required this.commitOverride,
11 });
12
13 -
13 final bool isSendAll;
14 Future<String> Function() commitOverride;
16 - final List<void Function()> _listeners =[];
15 + final List<void Function()> _listeners = [];
16
17 @override
18 String id;
cw_bitcoin/lib/litecoin_wallet.dart
+30 -26
@@ -175,7 +175,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
175 @override
176 bool get hasRescan => true;
177
178 -
178 final String? scanSecretOverride;
179 final String? spendPubkeyOverride;
180 List<int> get scanSecret => (scanSecretOverride != null && scanSecretOverride?.isNotEmpty == true)
@@ -232,8 +231,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
231 }
232
233 @override
235 - WalletKeysData get walletKeysData =>
236 - WalletKeysData(mnemonic: seed, xPub: xpub, passphrase: passphrase, scanSecret: scanSecretOverride, spendPubkey: spendPubkeyOverride);
234 + WalletKeysData get walletKeysData => WalletKeysData(
235 + mnemonic: seed,
236 + xPub: xpub,
237 + passphrase: passphrase,
238 + scanSecret: scanSecretOverride,
239 + spendPubkey: spendPubkeyOverride);
240
241 static Future<LitecoinWallet> open({
242 required String name,
@@ -1106,15 +1109,18 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
1109 for (final utxo in transaction.utxos) {
1110 if (utxo.utxo.scriptType != SegwitAddresType.mweb) {
1111 inputs.add(utxo.utxo.toInput());
1109 - txouts.add(TxOut(value: Int64(utxo.utxo.value.toInt()),
1110 - pkScript: utxo.ownerDetails.address.toScriptPubKey().toBytes()));
1112 + txouts.add(TxOut(
1113 + value: Int64(utxo.utxo.value.toInt()),
1114 + pkScript: utxo.ownerDetails.address.toScriptPubKey().toBytes()));
1115 }
1116 }
1117 var resp = await CwMweb.psbtCreate(PsbtCreateRequest(
1114 - rawTx: inputs.isEmpty ? null : BtcTransaction(
1115 - inputs: inputs,
1116 - outputs: isMweb ? [] : transaction.outputs,
1117 - ).toBytes(),
1118 + rawTx: inputs.isEmpty
1119 + ? null
1120 + : BtcTransaction(
1121 + inputs: inputs,
1122 + outputs: isMweb ? [] : transaction.outputs,
1123 + ).toBytes(),
1124 witnessUtxo: txouts,
1125 ));
1126 for (final utxo in transaction.utxos) {
@@ -1127,17 +1133,18 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
1133 ));
1134 }
1135 }
1130 - if (isMweb) for (final output in transaction.outputs) {
1131 - var address = addressFromOutputScript(output.scriptPubKey, LitecoinNetwork.mainnet);
1132 - if (output.scriptPubKey.getAddressType() == SegwitAddresType.mweb) {
1133 - address = SegwitBech32Encoder.encode("ltcmweb", 0, output.scriptPubKey.toBytes());
1136 + if (isMweb)
1137 + for (final output in transaction.outputs) {
1138 + var address = addressFromOutputScript(output.scriptPubKey, LitecoinNetwork.mainnet);
1139 + if (output.scriptPubKey.getAddressType() == SegwitAddresType.mweb) {
1140 + address = SegwitBech32Encoder.encode("ltcmweb", 0, output.scriptPubKey.toBytes());
1141 + }
1142 + resp = await CwMweb.psbtAddRecipient(PsbtAddRecipientRequest(
1143 + psbtB64: resp.psbtB64,
1144 + recipient: PsbtRecipient(address: address, value: Int64(output.amount.toInt())),
1145 + feeRatePerKb: Int64.parseInt(transaction.feeRate) * 1000,
1146 + ));
1147 }
1135 - resp = await CwMweb.psbtAddRecipient(PsbtAddRecipientRequest(
1136 - psbtB64: resp.psbtB64,
1137 - recipient: PsbtRecipient(address: address, value: Int64(output.amount.toInt())),
1138 - feeRatePerKb: Int64.parseInt(transaction.feeRate) * 1000,
1139 - ));
1140 - }
1148 return base64.decode(resp.psbtB64);
1149 }
1150
@@ -1203,7 +1210,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
1210 for (final utxo in tx.utxos) {
1211 if (utxo.utxo.scriptType == SegwitAddresType.mweb) {
1212 hasMwebInput = true;
1206 -
1213 } else {
1214 // check if any of the inputs of this transaction are hog-ex:
1215 // this list is only non-mweb inputs:
@@ -1256,9 +1262,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
1262 final utxo = unspentCoins
1263 .firstWhere((utxo) => utxo.hash == e.value.txId && utxo.vout == e.value.txIndex);
1264 final key = generateECPrivate(
1259 - hd: utxo.bitcoinAddressRecord.isHidden
1260 - ? sideHd
1261 - : mainHd,
1265 + hd: utxo.bitcoinAddressRecord.isHidden ? sideHd : mainHd,
1266 index: utxo.bitcoinAddressRecord.index,
1267 network: network);
1268 final digest = tx2.getTransactionSegwitDigit(
@@ -1284,8 +1288,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
1288 }
1289 }
1290
1287 - void addTransactionListener(PendingBitcoinTransaction tx,
1288 - List<String> inputAddresses, bool isPegIn, bool isPegOut) {
1291 + void addTransactionListener(
1292 + PendingBitcoinTransaction tx, List<String> inputAddresses, bool isPegIn, bool isPegOut) {
1293 tx.addListener((transaction) async {
1294 final addresses = <String>{};
1295 transaction.inputAddresses?.addAll(inputAddresses);
@@ -1575,7 +1579,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
1579 rawTx: rawTx,
1580 ownerDetails: utxo.ownerDetails,
1581 ownerDerivationPath: publicKeyAndDerivationPath.derivationPath,
1578 - ownerMasterFingerprint:masterFingerprint,
1582 + ownerMasterFingerprint: masterFingerprint,
1583 ownerPublicKey: publicKeyAndDerivationPath.publicKey,
1584 ));
1585 }
cw_bitcoin/lib/litecoin_wallet_addresses.dart
+13 -7
@@ -59,9 +59,11 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
59 ? hex.decode(scanSecretOverride!)
60 : mwebHd?.childKey(Bip32KeyIndex(0x80000000)).privateKey.privKey.raw ?? List.filled(32, 0);
61
62 - List<int> get spendPubkey => (spendPubkeyOverride != null && spendPubkeyOverride?.isNotEmpty == true)
63 - ? hex.decode(spendPubkeyOverride!)
64 - : mwebHd?.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed ?? List.filled(32, 0);
62 + List<int> get spendPubkey =>
63 + (spendPubkeyOverride != null && spendPubkeyOverride?.isNotEmpty == true)
64 + ? hex.decode(spendPubkeyOverride!)
65 + : mwebHd?.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed ??
66 + List.filled(32, 0);
67
68 @override
69 Future<void> init() async {
@@ -81,7 +83,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
83 return null;
84 }
85 if ((scanSecret.length < 1 || scanSecret.reduce((a, b) => a + b) == 0) &&
84 - (spendPubkey.length < 1 || spendPubkey.reduce((a, b) => a + b) == 0)) {
86 + (spendPubkey.length < 1 || spendPubkey.reduce((a, b) => a + b) == 0)) {
87 return null;
88 }
89
@@ -230,12 +232,16 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
232 // don't use mweb addresses for exchange refund address:
233
234 final current = getFreshAddress();
233 - final bool isMweb = receiveAddresses
234 - .any((e) => e.address == current && e.type == SegwitAddresType.mweb);
235 + final bool isMweb =
236 + receiveAddresses.any((e) => e.address == current && e.type == SegwitAddresType.mweb);
237
238 if (isMweb) {
239 final segwit = receiveAddresses
238 - .where((e) => e.type == SegwitAddresType.p2wpkh && !e.isUsed && !e.isHidden && !hiddenAddresses.contains(e.address))
240 + .where((e) =>
241 + e.type == SegwitAddresType.p2wpkh &&
242 + !e.isUsed &&
243 + !e.isHidden &&
244 + !hiddenAddresses.contains(e.address))
245 .map((e) => e.address)
246 .toList();
247
cw_bitcoin/lib/litecoin_wallet_service.dart
+9 -8
@@ -48,7 +48,8 @@ class LitecoinWalletService extends WalletService<
48 password: credentials.password!,
49 passphrase: credentials.passphrase,
50 walletInfo: credentials.walletInfo!,
51 - derivationInfo: credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
51 + derivationInfo:
52 + credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
53 unspentCoinsInfo: unspentCoinsInfoSource,
54 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
55 );
@@ -64,7 +65,6 @@ class LitecoinWalletService extends WalletService<
65
66 @override
67 Future<LitecoinWallet> openWallet(String name, String password) async {
67 -
68 final walletInfo = await WalletInfo.get(name, getType());
69 if (walletInfo == null) {
70 throw Exception('Wallet not found');
@@ -125,8 +125,9 @@ class LitecoinWalletService extends WalletService<
125 }
126 }
127
128 - final unspentCoinsToDelete = unspentCoinsInfoSource.values.where(
129 - (unspentCoin) => unspentCoin.walletId == walletInfo.id).toList();
128 + final unspentCoinsToDelete = unspentCoinsInfoSource.values
129 + .where((unspentCoin) => unspentCoin.walletId == walletInfo.id)
130 + .toList();
131
132 final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
133
@@ -150,8 +151,7 @@ class LitecoinWalletService extends WalletService<
151 final network = isTestnet == true ? LitecoinNetwork.testnet : LitecoinNetwork.mainnet;
152 credentials.walletInfo?.network = network.value;
153 final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
153 - derivationInfo.derivationPath =
154 - credentials.hwAccountData.derivationPath;
154 + derivationInfo.derivationPath = credentials.hwAccountData.derivationPath;
155 await derivationInfo.save();
156 credentials.walletInfo!.save();
157
@@ -170,7 +170,7 @@ class LitecoinWalletService extends WalletService<
170
171 @override
172 Future<LitecoinWallet> restoreFromKeys(LitecoinWalletFromKeysCredentials credentials,
173 - {bool? isTestnet}) async {
173 + {bool? isTestnet}) async {
174 final network = isTestnet == true ? LitecoinNetwork.testnet : LitecoinNetwork.mainnet;
175 credentials.walletInfo?.network = network.value;
176
@@ -202,7 +202,8 @@ class LitecoinWalletService extends WalletService<
202 passphrase: credentials.passphrase,
203 mnemonic: credentials.mnemonic,
204 walletInfo: credentials.walletInfo!,
205 - derivationInfo: credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
205 + derivationInfo:
206 + credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
207 unspentCoinsInfo: unspentCoinsInfoSource,
208 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
209 );
cw_bitcoin/lib/payjoin/manager.dart
+13 -18
@@ -108,16 +108,14 @@ class PayjoinManager {
108 Future<Sender> initSender(
109 String pjUriString, String originalPsbt, int networkFeesSatPerVb) async {
110 try {
111 - final pjUri =
112 - (await PayjoinUri.Uri.fromStr(pjUriString)).checkPjSupported();
111 + final pjUri = (await PayjoinUri.Uri.fromStr(pjUriString)).checkPjSupported();
112 final minFeeRateSatPerKwu = BigInt.from(networkFeesSatPerVb * 250);
113 final senderBuilder = await SenderBuilder.fromPsbtAndUri(
114 psbtBase64: originalPsbt,
115 pjUri: pjUri,
116 );
117 final persister = PayjoinSenderPersister.impl();
119 - final newSender =
120 - await senderBuilder.buildRecommended(minFeeRate: minFeeRateSatPerKwu);
118 + final newSender = await senderBuilder.buildRecommended(minFeeRate: minFeeRateSatPerKwu);
119 final senderToken = await newSender.persist(persister: persister);
120
121 return Sender.load(token: senderToken, persister: persister);
@@ -133,8 +131,7 @@ class PayjoinManager {
131 bool isTestnet = false,
132 }) async {
133 final pjUri = Uri.parse(pjUrl).queryParameters['pj']!;
136 - await _payjoinStorage.insertSenderSession(
137 - sender, pjUri, _wallet.id, amount);
134 + await _payjoinStorage.insertSenderSession(sender, pjUri, _wallet.id, amount);
135
136 return _spawnSender(isTestnet: isTestnet, sender: sender, pjUri: pjUri);
137 }
@@ -207,8 +204,7 @@ class PayjoinManager {
204 return completer.future;
205 }
206
210 - Future<Receiver> getUnusedReceiver(String address,
211 - [bool isTestnet = false]) async {
207 + Future<Receiver> getUnusedReceiver(String address, [bool isTestnet = false]) async {
208 final session = _payjoinStorage.getUnusedActiveReceiverSession(_wallet.id);
209
210 if (session != null) {
@@ -220,7 +216,8 @@ class PayjoinManager {
216 return initReceiver(address);
217 }
218
223 - Future<Receiver> initReceiver(String address, [bool isTestnet = false, int retryCount = 0]) async {
219 + Future<Receiver> initReceiver(String address,
220 + [bool isTestnet = false, int retryCount = 0]) async {
221 if (retryCount > 0) writePayjoinLog("Retrying initReceiver ${retryCount + 1} attempt");
222
223 try {
@@ -245,7 +242,6 @@ class PayjoinManager {
242 } catch (e) {
243 writePayjoinLog(e.toString());
244 if (e.toString().contains("error sending request for url") && retryCount < 5) {
248 -
245 return initReceiver(address, isTestnet, ++retryCount);
246 } else {
247 rethrow;
@@ -273,13 +269,11 @@ class PayjoinManager {
269 rawAmount = getOutputAmountFromTx(tx, _wallet);
270 break;
271 case PayjoinReceiverRequestTypes.checkIsOwned:
276 - (_wallet.walletAddresses as BitcoinWalletAddresses)
277 - .newPayjoinReceiver();
272 + (_wallet.walletAddresses as BitcoinWalletAddresses).newPayjoinReceiver();
273 _payjoinStorage.markReceiverSessionInProgress(receiver.id());
274
275 final inputScript = message['input_script'] as Uint8List;
281 - final isOwned =
282 - _wallet.isMine(Script.fromRaw(byteData: inputScript));
276 + final isOwned = _wallet.isMine(Script.fromRaw(byteData: inputScript));
277 mainToIsolateSendPort?.send({
278 'requestId': message['requestId'],
279 'result': isOwned,
@@ -288,8 +282,7 @@ class PayjoinManager {
282
283 case PayjoinReceiverRequestTypes.checkIsReceiverOutput:
284 final outputScript = message['output_script'] as Uint8List;
291 - final isReceiverOutput =
292 - _wallet.isMine(Script.fromRaw(byteData: outputScript));
285 + final isReceiverOutput = _wallet.isMine(Script.fromRaw(byteData: outputScript));
286 mainToIsolateSendPort?.send({
287 'requestId': message['requestId'],
288 'result': isReceiverOutput,
@@ -310,7 +303,8 @@ class PayjoinManager {
303
304 case PayjoinReceiverRequestTypes.processPsbt:
305 final psbt = message['psbt'] as String;
313 - writePayjoinLog("Receiver(${receiver.id()}) PayjoinReceiverRequestTypes.processPsbt: $psbt");
306 + writePayjoinLog(
307 + "Receiver(${receiver.id()}) PayjoinReceiverRequestTypes.processPsbt: $psbt");
308
309 final signedPsbt = await _wallet.signPsbt(psbt, utxos);
310 mainToIsolateSendPort?.send({
@@ -322,7 +316,8 @@ class PayjoinManager {
316 case PayjoinReceiverRequestTypes.proposalSent:
317 _cleanupSession(receiver.id());
318 final psbt = message['psbt'] as String;
325 - writePayjoinLog("Receiver(${receiver.id()}) PayjoinReceiverRequestTypes.proposalSent: $psbt");
319 + writePayjoinLog(
320 + "Receiver(${receiver.id()}) PayjoinReceiverRequestTypes.proposalSent: $psbt");
321
322 await _payjoinStorage.markReceiverSessionComplete(
323 receiver.id(), getTxIdFromPsbtV0(psbt), rawAmount);
cw_bitcoin/lib/payjoin/payjoin_receive_worker.dart
+11 -20
@@ -47,8 +47,7 @@ class PayjoinReceiverWorker {
47 try {
48 final receiver = Receiver.fromJson(json: receiverJson);
49
50 - final uncheckedProposal =
51 - await worker.receiveUncheckedProposal(receiver);
50 + final uncheckedProposal = await worker.receiveUncheckedProposal(receiver);
51
52 final originalTx = await uncheckedProposal.extractTxToScheduleBroadcast();
53 sendPort.send({
@@ -112,8 +111,7 @@ class PayjoinReceiverWorker {
111 final httpRequest = await client.post(url,
112 headers: {'Content-Type': request.contentType}, body: request.body);
113
115 - final proposal = await session.processRes(
116 - body: httpRequest.bodyBytes, ctx: extractReq.$2);
114 + final proposal = await session.processRes(body: httpRequest.bodyBytes, ctx: extractReq.$2);
115 if (proposal != null) return proposal;
116 sleep(Duration(seconds: 2));
117 }
@@ -140,8 +138,7 @@ class PayjoinReceiverWorker {
138 return await finalProposal.psbt();
139 }
140
143 - Future<PayjoinProposal> processPayjoinProposal(
144 - UncheckedProposal proposal) async {
141 + Future<PayjoinProposal> processPayjoinProposal(UncheckedProposal proposal) async {
142 await proposal.extractTxToScheduleBroadcast();
143 // TODO Handle this. send to the main port on a timer?
144
@@ -174,20 +171,17 @@ class PayjoinReceiverWorker {
171 );
172 final pj5 = await pj4.commitOutputs();
173
177 - final listUnspent =
178 - await _sendRequest(PayjoinReceiverRequestTypes.getCandidateInputs);
174 + final listUnspent = await _sendRequest(PayjoinReceiverRequestTypes.getCandidateInputs);
175 final unspent = listUnspent as List<UtxoWithPrivateKey>;
176 if (unspent.isEmpty) throw RecoverableError('No unspent outputs available');
177
182 - final candidateInputs =
183 - await Future.wait(unspent.map(_inputPairFromUtxo));
178 + final candidateInputs = await Future.wait(unspent.map(_inputPairFromUtxo));
179
180 // Prefer a UTXO that avoids the Unnecessary Input Heuristic (UIH2);
181 // fall back to the first candidate if none preserves privacy.
182 InputPair selectedUtxo = candidateInputs.first;
183 try {
189 - selectedUtxo =
190 - await pj5.tryPreservingPrivacy(candidateInputs: candidateInputs);
184 + selectedUtxo = await pj5.tryPreservingPrivacy(candidateInputs: candidateInputs);
185 } catch (_) {}
186
187 final pj6 = await pj5.contributeInputs(replacementInputs: [selectedUtxo]);
@@ -196,8 +190,8 @@ class PayjoinReceiverWorker {
190 // Finalize proposal
191 final payjoinProposal = await pj7.finalizeProposal(
192 processPsbt: (String psbt) async {
199 - final result = await _sendRequest(
200 - PayjoinReceiverRequestTypes.processPsbt, {'psbt': psbt});
193 + final result =
194 + await _sendRequest(PayjoinReceiverRequestTypes.processPsbt, {'psbt': psbt});
195 return result as String;
196 },
197 // TODO set maxFeeRateSatPerVb
@@ -213,15 +207,12 @@ class PayjoinReceiverWorker {
207 Future<InputPair> _inputPairFromUtxo(UtxoWithPrivateKey utxo) async {
208 final txout = TxOut(
209 value: utxo.utxo.value,
216 - scriptPubkey: Uint8List.fromList(
217 - utxo.ownerDetails.address.toScriptPubKey().toBytes()),
210 + scriptPubkey: Uint8List.fromList(utxo.ownerDetails.address.toScriptPubKey().toBytes()),
211 );
212
220 - final psbtin =
221 - PsbtInput(witnessUtxo: txout, redeemScript: null, witnessScript: null);
213 + final psbtin = PsbtInput(witnessUtxo: txout, redeemScript: null, witnessScript: null);
214
223 - final previousOutput =
224 - OutPoint(txid: utxo.utxo.txHash, vout: utxo.utxo.vout);
215 + final previousOutput = OutPoint(txid: utxo.utxo.txHash, vout: utxo.utxo.vout);
216
217 final txin = TxIn(
218 previousOutput: previousOutput,
cw_bitcoin/lib/payjoin/payjoin_send_worker.dart
+3 -5
@@ -46,11 +46,11 @@ class PayjoinSenderWorker {
46 sendPort.send(e);
47 }
48 }
49 +
50 final client = ProxyWrapper().getHttpIOClient();
51
52 /// Run a payjoin sender (V2 protocol first, fallback to V1).
53 Future<String> runSender(Sender sender) async {
53 -
54 try {
55 return await _runSenderV2(sender);
56 } catch (e) {
@@ -70,13 +70,11 @@ class PayjoinSenderWorker {
70 Future<String> _runSenderV2(Sender sender) async {
71 try {
72 final postRequest = await sender.extractV2(
73 - ohttpProxyUrl:
74 - await pj_uri.Url.fromStr(PayjoinManager.randomOhttpRelayUrl()),
73 + ohttpProxyUrl: await pj_uri.Url.fromStr(PayjoinManager.randomOhttpRelayUrl()),
74 );
75
76 final postResult = await _postRequest(postRequest.$1);
78 - final getContext =
79 - await postRequest.$2.processResponse(response: postResult);
77 + final getContext = await postRequest.$2.processResponse(response: postResult);
78
79 sendPort.send({'type': PayjoinSenderRequestTypes.requestPosted, "pj": pjUrl});
80
cw_bitcoin/lib/payjoin/storage.dart
+15 -21
@@ -23,16 +23,14 @@ class PayjoinStorage {
23 ),
24 );
25
26 - PayjoinSession? getUnusedActiveReceiverSession(String walletId) =>
27 - _payjoinSessionSources.values
28 - .where((session) =>
29 - session.walletId == walletId &&
30 - session.status == PayjoinSessionStatus.created.name &&
31 - !session.isSenderSession)
32 - .firstOrNull;
33 -
34 - Future<void> markReceiverSessionComplete(
35 - String sessionId, String txId, String amount) async {
26 + PayjoinSession? getUnusedActiveReceiverSession(String walletId) => _payjoinSessionSources.values
27 + .where((session) =>
28 + session.walletId == walletId &&
29 + session.status == PayjoinSessionStatus.created.name &&
30 + !session.isSenderSession)
31 + .firstOrNull;
32 +
33 + Future<void> markReceiverSessionComplete(String sessionId, String txId, String amount) async {
34 final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
35
36 session.status = PayjoinSessionStatus.success.name;
@@ -41,8 +39,7 @@ class PayjoinStorage {
39 await session.save();
40 }
41
44 - Future<void> markReceiverSessionUnrecoverable(
45 - String sessionId, String reason) async {
42 + Future<void> markReceiverSessionUnrecoverable(String sessionId, String reason) async {
43 final session = _payjoinSessionSources.get("$_receiverPrefix${sessionId}")!;
44
45 session.status = PayjoinSessionStatus.unrecoverable.name;
@@ -92,13 +89,10 @@ class PayjoinStorage {
89 await session.save();
90 }
91
95 - List<PayjoinSession> readAllOpenSessions(String walletId) =>
96 - _payjoinSessionSources.values
97 - .where((session) =>
98 - session.walletId == walletId &&
99 - ![
100 - PayjoinSessionStatus.success.name,
101 - PayjoinSessionStatus.unrecoverable.name
102 - ].contains(session.status))
103 - .toList();
92 + List<PayjoinSession> readAllOpenSessions(String walletId) => _payjoinSessionSources.values
93 + .where((session) =>
94 + session.walletId == walletId &&
95 + ![PayjoinSessionStatus.success.name, PayjoinSessionStatus.unrecoverable.name]
96 + .contains(session.status))
97 + .toList();
98 }
cw_bitcoin/lib/psbt/signer.dart
+19 -38
@@ -40,8 +40,7 @@ extension PsbtSigner on PsbtV2 {
40 return tx.buffer();
41 }
42
43 - Future<void> signWithUTXO(
44 - List<UtxoWithPrivateKey> utxos, UTXOSignerCallBack signer,
43 + Future<void> signWithUTXO(List<UtxoWithPrivateKey> utxos, UTXOSignerCallBack signer,
44 [UTXOGetterCallBack? getTaprootPair]) async {
45 final raw = BytesUtils.toHexString(extractUnsignedTX(getSegwit: false));
46 final tx = BtcTransaction.fromRaw(raw);
@@ -53,8 +52,8 @@ extension PsbtSigner on PsbtV2 {
52
53 if (utxos.any((e) => e.utxo.isP2tr())) {
54 for (final input in tx.inputs) {
56 - final utxo = utxos.firstWhereOrNull(
57 - (u) => u.utxo.txHash == input.txId && u.utxo.vout == input.txIndex);
55 + final utxo = utxos
56 + .firstWhereOrNull((u) => u.utxo.txHash == input.txId && u.utxo.vout == input.txIndex);
57
58 if (utxo == null) {
59 final trPair = await getTaprootPair!.call(input.txId, input.txIndex);
@@ -81,8 +80,8 @@ extension PsbtSigner on PsbtV2 {
80 : BitcoinOpCodeConst.SIGHASH_ALL;
81
82 /// We generate transaction digest for current input
84 - final digest = _generateTransactionDigest(
85 - script, i, utxo.utxo, tx, taprootAmounts, taprootScripts);
83 + final digest =
84 + _generateTransactionDigest(script, i, utxo.utxo, tx, taprootAmounts, taprootScripts);
85
86 /// now we need sign the transaction digest
87 final sig = signer(digest, utxo, utxo.privateKey, sighash);
@@ -90,21 +89,14 @@ extension PsbtSigner on PsbtV2 {
89 if (utxo.utxo.isP2tr()) {
90 setInputTapKeySig(i, Uint8List.fromList(BytesUtils.fromHexString(sig)));
91 } else {
93 - setInputPartialSig(
94 - i,
95 - Uint8List.fromList(BytesUtils.fromHexString(utxo.public().toHex())),
92 + setInputPartialSig(i, Uint8List.fromList(BytesUtils.fromHexString(utxo.public().toHex())),
93 Uint8List.fromList(BytesUtils.fromHexString(sig)));
94 }
95 }
96 }
97
101 - List<int> _generateTransactionDigest(
102 - Script scriptPubKeys,
103 - int input,
104 - BitcoinUtxo utxo,
105 - BtcTransaction transaction,
106 - List<BigInt> taprootAmounts,
107 - List<Script> tapRootPubKeys) {
98 + List<int> _generateTransactionDigest(Script scriptPubKeys, int input, BitcoinUtxo utxo,
99 + BtcTransaction transaction, List<BigInt> taprootAmounts, List<Script> tapRootPubKeys) {
100 if (utxo.isSegwit()) {
101 if (utxo.isP2tr()) {
102 return transaction.getTransactionTaprootDigset(
@@ -116,8 +108,7 @@ extension PsbtSigner on PsbtV2 {
108 return transaction.getTransactionSegwitDigit(
109 txInIndex: input, script: scriptPubKeys, amount: utxo.value);
110 }
119 - return transaction.getTransactionDigest(
120 - txInIndex: input, script: scriptPubKeys);
111 + return transaction.getTransactionDigest(txInIndex: input, script: scriptPubKeys);
112 }
113
114 Script _findLockingScript(UtxoWithAddress utxo, bool isTaproot) {
@@ -172,11 +163,10 @@ extension PsbtSigner on PsbtV2 {
163 }
164 }
165
175 -typedef UTXOSignerCallBack = String Function(List<int> trDigest,
176 - UtxoWithAddress utxo, ECPrivate privateKey, int sighash);
166 +typedef UTXOSignerCallBack = String Function(
167 + List<int> trDigest, UtxoWithAddress utxo, ECPrivate privateKey, int sighash);
168
178 -typedef UTXOGetterCallBack = Future<TaprootAmountScriptPair> Function(
179 - String txId, int vout);
169 +typedef UTXOGetterCallBack = Future<TaprootAmountScriptPair> Function(String txId, int vout);
170
171 class TaprootAmountScriptPair {
172 final BigInt value;
@@ -216,23 +206,17 @@ class UtxoWithPrivateKey extends UtxoWithAddress {
206 }
207
208 return UtxoWithPrivateKey(
219 - utxo: input.utxo,
220 - ownerDetails: input.ownerDetails,
221 - privateKey: key.privkey);
209 + utxo: input.utxo, ownerDetails: input.ownerDetails, privateKey: key.privkey);
210 }
211
224 - factory UtxoWithPrivateKey.fromUnspent(
225 - BitcoinUnspent input, BitcoinWalletBase wallet) {
226 - final address =
227 - RegexUtils.addressTypeFromStr(input.address, BitcoinNetwork.mainnet);
212 + factory UtxoWithPrivateKey.fromUnspent(BitcoinUnspent input, BitcoinWalletBase wallet) {
213 + final address = RegexUtils.addressTypeFromStr(input.address, BitcoinNetwork.mainnet);
214
229 - final newHd =
230 - input.bitcoinAddressRecord.isHidden ? wallet.sideHd : wallet.mainHd;
215 + final newHd = input.bitcoinAddressRecord.isHidden ? wallet.sideHd : wallet.mainHd;
216
217 ECPrivate privkey;
218 if (input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord) {
234 - final unspentAddress =
235 - input.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord;
219 + final unspentAddress = input.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord;
220 privkey = wallet.walletAddresses.silentAddress!.b_spend.tweakAdd(
221 BigintUtils.fromBytes(
222 BytesUtils.fromHexString(unspentAddress.silentPaymentTweak!),
@@ -240,9 +224,7 @@ class UtxoWithPrivateKey extends UtxoWithAddress {
224 );
225 } else {
226 privkey = generateECPrivate(
243 - hd: newHd,
244 - index: input.bitcoinAddressRecord.index,
245 - network: BitcoinNetwork.mainnet);
227 + hd: newHd, index: input.bitcoinAddressRecord.index, network: BitcoinNetwork.mainnet);
228 }
229
230 return UtxoWithPrivateKey(
@@ -251,8 +233,7 @@ class UtxoWithPrivateKey extends UtxoWithAddress {
233 value: BigInt.from(input.value),
234 vout: input.vout,
235 scriptType: input.bitcoinAddressRecord.type,
254 - isSilentPayment:
255 - input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord,
236 + isSilentPayment: input.bitcoinAddressRecord is BitcoinSilentPaymentAddressRecord,
237 ),
238 ownerDetails: UtxoAddressDetails(
239 publicKey: privkey.getPublic().toHex(),
cw_bitcoin/lib/psbt/transaction_builder.dart
+14 -17
@@ -11,7 +11,10 @@ class PSBTTransactionBuild {
11 final PsbtV2 psbt = PsbtV2();
12
13 PSBTTransactionBuild(
14 - {required List<PSBTReadyUtxoWithAddress> inputs, required List<BitcoinBaseOutput> outputs, required List<OutputInfo> cwOutputs, bool enableRBF = true}) {
14 + {required List<PSBTReadyUtxoWithAddress> inputs,
15 + required List<BitcoinBaseOutput> outputs,
16 + required List<OutputInfo> cwOutputs,
17 + bool enableRBF = true}) {
18 psbt.setGlobalTxVersion(2);
19 psbt.setGlobalInputCount(inputs.length);
20 psbt.setGlobalOutputCount(outputs.length);
@@ -23,10 +26,10 @@ class PSBTTransactionBuild {
26 printV(input.utxo.isSegwit());
27 printV(input.utxo.isP2shSegwit());
28
26 - psbt.setInputPreviousTxId(i, Uint8List.fromList(hex.decode(input.utxo.txHash).reversed.toList()));
29 + psbt.setInputPreviousTxId(
30 + i, Uint8List.fromList(hex.decode(input.utxo.txHash).reversed.toList()));
31 psbt.setInputOutputIndex(i, input.utxo.vout);
32 psbt.setInputSequence(i, enableRBF ? 0xfffffffd : 0xffffffff);
29 -
33
34 if (input.utxo.isSegwit()) {
35 setInputSegwit(i, input);
@@ -48,10 +51,10 @@ class PSBTTransactionBuild {
51 if (cwOutputs.isNotEmpty) {
52 try {
53 final cwOutput = cwOutputs
51 - .where((e) => [e.address, e.extractedAddress]
52 - .map((e) => e?.toLowerCase())
53 - .contains(output.address.toAddress().toLowerCase()))
54 - .firstOrNull;
54 + .where((e) => [e.address, e.extractedAddress]
55 + .map((e) => e?.toLowerCase())
56 + .contains(output.address.toAddress().toLowerCase()))
57 + .firstOrNull;
58 if (cwOutput != null &&
59 cwOutput.extra.containsKey('bip353_name') &&
60 cwOutput.extra.containsKey('bip353_proof')) {
@@ -80,20 +83,14 @@ class PSBTTransactionBuild {
83
84 void setInputP2pkh(int i, PSBTReadyUtxoWithAddress input) {
85 psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx)));
83 - psbt.setInputBip32Derivation(
84 - i,
85 - Uint8List.fromList(hex.decode(input.ownerPublicKey)),
86 - input.ownerMasterFingerprint,
87 - BIPPath.fromString(input.ownerDerivationPath).toPathArray());
86 + psbt.setInputBip32Derivation(i, Uint8List.fromList(hex.decode(input.ownerPublicKey)),
87 + input.ownerMasterFingerprint, BIPPath.fromString(input.ownerDerivationPath).toPathArray());
88 }
89
90 void setInputSegwit(int i, PSBTReadyUtxoWithAddress input) {
91 psbt.setInputNonWitnessUtxo(i, Uint8List.fromList(hex.decode(input.rawTx)));
92 - psbt.setInputBip32Derivation(
93 - i,
94 - Uint8List.fromList(hex.decode(input.ownerPublicKey)),
95 - input.ownerMasterFingerprint,
96 - BIPPath.fromString(input.ownerDerivationPath).toPathArray());
92 + psbt.setInputBip32Derivation(i, Uint8List.fromList(hex.decode(input.ownerPublicKey)),
93 + input.ownerMasterFingerprint, BIPPath.fromString(input.ownerDerivationPath).toPathArray());
94
95 psbt.setInputWitnessUtxo(i, Uint8List.fromList(bigIntToUint64LE(input.utxo.value)),
96 Uint8List.fromList(input.ownerDetails.address.toScriptPubKey().toBytes()));
cw_bitcoin/lib/psbt/utils.dart
+1 -3
@@ -10,9 +10,7 @@ import 'package:ledger_bitcoin/psbt.dart';
10 String getTxIdFromPsbtV0(String psbt) {
11 final psbtV2 = PsbtV2()..deserializeV0(base64.decode(psbt));
12
13 - return BtcTransaction.fromRaw(
14 - BytesUtils.toHexString(psbtV2.extractUnsignedTX(false)))
15 - .txId();
13 + return BtcTransaction.fromRaw(BytesUtils.toHexString(psbtV2.extractUnsignedTX(false))).txId();
14 }
15
16 String getOutputAmountFromPsbt(String psbtV0, BitcoinWalletBase wallet) {
cw_bitcoin/lib/psbt/v0_deserialize.dart
+4 -3
@@ -7,10 +7,10 @@ import 'package:ledger_bitcoin/src/utils/buffer_reader.dart';
7 import 'package:ledger_bitcoin/src/utils/uint8list_extension.dart' as ext;
8
9 extension PsbtSigner on PsbtV2 {
10 -
10 void deserializeV0(Uint8List psbt) {
11 final bufferReader = BufferReader(psbt);
13 - if (!listEquals(bufferReader.readSlice(5), Uint8List.fromList([0x70, 0x73, 0x62, 0x74, 0xff]))) {
12 + if (!listEquals(
13 + bufferReader.readSlice(5), Uint8List.fromList([0x70, 0x73, 0x62, 0x74, 0xff]))) {
14 throw Exception("Invalid magic bytes");
15 }
16 while (_readKeyPair(globalMap, bufferReader)) {}
@@ -26,7 +26,8 @@ extension PsbtSigner on PsbtV2 {
26 while (_readKeyPair(inputMaps[i], bufferReader)) {}
27 final input = tx.inputs[i];
28 setInputOutputIndex(i, input.txIndex);
29 - setInputPreviousTxId(i, Uint8List.fromList(BytesUtils.fromHexString(input.txId).reversed.toList()));
29 + setInputPreviousTxId(
30 + i, Uint8List.fromList(BytesUtils.fromHexString(input.txId).reversed.toList()));
31 setInputSequence(i, Uint8List.fromList(input.sequence).readUint32LE(0));
32 }
33 for (var i = 0; i < getGlobalOutputCount(); i++) {
cw_bitcoin/lib/psbt/v0_finalizer.dart
+2 -5
@@ -18,7 +18,6 @@ import "package:ledger_bitcoin/src/utils/buffer_writer.dart";
18 /// through PSBT_IN_PARTIAL_SIG or PSBT_IN_TAP_KEY_SIG
19 extension InputFinalizer on PsbtV2 {
20 void finalizeV0() {
21 -
21 // First check that each input has a signature
22 for (var i = 0; i < getGlobalInputCount(); i++) {
23 if (_isFinalized(i)) continue;
@@ -31,8 +30,7 @@ extension InputFinalizer on PsbtV2 {
30 }
31 if (legacyPubkeys.isNotEmpty) {
32 if (legacyPubkeys.length > 1) {
34 - throw Exception(
35 - 'Expected exactly one signature, got ${legacyPubkeys.length}');
33 + throw Exception('Expected exactly one signature, got ${legacyPubkeys.length}');
34 }
35 if (taprootSig != null) {
36 throw Exception('Both taproot and non-taproot signatures present.');
@@ -55,8 +53,7 @@ extension InputFinalizer on PsbtV2 {
53 setInputFinalScriptwitness(i, witnessBuf.buffer());
54 if (isWrappedSegwit) {
55 if (redeemScript.isEmpty) {
58 - throw Exception(
59 - "Expected non-empty redeemscript. Can't finalize input $i");
56 + throw Exception("Expected non-empty redeemscript. Can't finalize input $i");
57 }
58 final scriptSigBuf = BufferWriter()
59 ..writeUInt8(redeemScript.length) // Push redeemScript length
cw_bitcoin/lib/utils.dart
+1 -1
@@ -52,4 +52,4 @@ String generateP2TRAddress({
52 }) =>
53 ECPublic.fromBip32(hd.childKey(Bip32KeyIndex(index)).publicKey)
54 .toTaprootAddress()
55 - .toAddress(network);
\ No newline at end of file
55 + .toAddress(network);
cw_bitcoin_cash/lib/src/bitcoin_cash_wallet_service.dart
+4 -4
@@ -87,8 +87,9 @@ class BitcoinCashWalletService extends WalletService<
87 }
88 await WalletInfo.delete(walletInfo);
89
90 - final unspentCoinsToDelete = unspentCoinsInfoSource.values.where(
91 - (unspentCoin) => unspentCoin.walletId == walletInfo.id).toList();
90 + final unspentCoinsToDelete = unspentCoinsInfoSource.values
91 + .where((unspentCoin) => unspentCoin.walletId == walletInfo.id)
92 + .toList();
93
94 final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
95
@@ -122,8 +123,7 @@ class BitcoinCashWalletService extends WalletService<
123 walletInfo: credentials.walletInfo!,
124 unspentCoinsInfo: unspentCoinsInfoSource,
125 encryptionFileUtils: encryptionFileUtilsFor(isDirect),
125 - passphrase: credentials.passphrase
126 - );
126 + passphrase: credentials.passphrase);
127 await wallet.save();
128 await wallet.init();
129 return wallet;
cw_bitcoin_cash/lib/src/exceptions/exceptions.dart
+1 -1
@@ -1 +1 @@
1 -export 'bitcoin_cash_mnemonic_is_incorrect_exception.dart';
\ No newline at end of file
1 +export 'bitcoin_cash_mnemonic_is_incorrect_exception.dart';
cw_core/lib/account.dart
+1 -1
@@ -9,4 +9,4 @@ class Account {
9 final int id;
10 final String label;
11 final String? balance;
12 -}
\ No newline at end of file
12 +}
cw_core/lib/account_list.dart
-1
@@ -1,7 +1,6 @@
1 import 'package:mobx/mobx.dart';
2
3 abstract class AccountList<T> {
4 -
4 ObservableList<T> get accounts;
5
6 void update();
cw_core/lib/address_info.part.dart
+1 -3
@@ -41,7 +41,5 @@ class AddressInfoAdapter extends TypeAdapter<AddressInfo> {
41 @override
42 bool operator ==(Object other) =>
43 identical(this, other) ||
44 - other is AddressInfoAdapter &&
45 - runtimeType == other.runtimeType &&
46 - typeId == other.typeId;
44 + other is AddressInfoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
45 }
cw_core/lib/amount/amount_sanitizer.dart
-1
@@ -10,7 +10,6 @@ String _smartAmountSanitizer(String amount) {
10 return amount.replaceAll(",", ".");
11 }
12
13 -
13 extension SanitizerUserAmounts on String {
14 String sanitized() => _smartAmountSanitizer(this);
15 }
cw_core/lib/amount_converter.dart
+4 -5
@@ -9,19 +9,18 @@ class AmountConverter {
9 amount = amount.replaceAll(',', '');
10 final parts = amount.split('.');
11 final whole = parts[0].isEmpty ? '0' : parts[0];
12 - final frac = parts.length > 1 ? parts[1] : '';
12 + final frac = parts.length > 1 ? parts[1] : '';
13
14 final fracPadded = (frac + '0' * decimals).substring(0, decimals);
15
16 final pow10 = BigInt.from(10).pow(decimals);
17 final wholeBI = BigInt.parse(whole);
18 - final fracBI = fracPadded.isEmpty ? BigInt.zero : BigInt.parse(fracPadded);
18 + final fracBI = fracPadded.isEmpty ? BigInt.zero : BigInt.parse(fracPadded);
19
20 final res = wholeBI * pow10 + fracBI;
21 return neg ? '-${res.toString()}' : res.toString();
22 }
23
24 -
24 static String fromBaseUnits(String units, int decimals) {
25 units = units.trim();
26 if (units.isEmpty) return '0';
@@ -35,14 +34,14 @@ class AmountConverter {
34 if (units.length <= decimals) {
35 final s = units.padLeft(decimals + 1, '0'); // ensures at least "0xxxx"
36 final intPart = s.substring(0, s.length - decimals);
38 - var fracPart = s.substring(s.length - decimals);
37 + var fracPart = s.substring(s.length - decimals);
38 fracPart = fracPart.replaceFirst(RegExp(r'0+$'), '');
39 final out = fracPart.isEmpty ? intPart : '$intPart.$fracPart';
40 return neg ? '-$out' : out;
41 }
42
43 final intPart = units.substring(0, units.length - decimals);
45 - var fracPart = units.substring(units.length - decimals);
44 + var fracPart = units.substring(units.length - decimals);
45 fracPart = fracPart.replaceFirst(RegExp(r'0+$'), '');
46 final out = fracPart.isEmpty ? intPart : '$intPart.$fracPart';
47 return neg ? '-$out' : out;
cw_core/lib/balance_card_style_settings.dart
+13 -17
@@ -14,13 +14,13 @@ class BalanceCardStyleSettings {
14
15 BalanceCardStyleSettings(
16 {required this.walletInfoId,
17 - required this.accountIndex,
18 - required this.gradientIndex,
19 - required this.useSpecialDesign,
20 - required this.backgroundImagePath,
21 - this.iconStyleIndex = 0,
22 - this.isGradientOnly = false,
23 - required this.cardOrder});
17 + required this.accountIndex,
18 + required this.gradientIndex,
19 + required this.useSpecialDesign,
20 + required this.backgroundImagePath,
21 + this.iconStyleIndex = 0,
22 + this.isGradientOnly = false,
23 + required this.cardOrder});
24
25 static const tableName = "BalanceCardStyleSettings";
26
@@ -59,21 +59,17 @@ class BalanceCardStyleSettings {
59 int iconStyleIndex = 0,
60 int? gradientIndexOverride,
61 }) {
62 - final int gradientIndex = gradientIndexOverride ??
63 - CardDesign.allGradients.indexOf(design.gradient);
62 + final int gradientIndex =
63 + gradientIndexOverride ?? CardDesign.allGradients.indexOf(design.gradient);
64 return BalanceCardStyleSettings(
65 walletInfoId: walletInfoId,
66 accountIndex: accountIndex,
67 gradientIndex: gradientIndex,
68 - useSpecialDesign:
69 - design.backgroundType == CardDesignBackgroundTypes.svgFull,
68 + useSpecialDesign: design.backgroundType == CardDesignBackgroundTypes.svgFull,
69 backgroundImagePath:
71 - design.backgroundType == CardDesignBackgroundTypes.image
72 - ? design.imagePath
73 - : "",
70 + design.backgroundType == CardDesignBackgroundTypes.image ? design.imagePath : "",
71 iconStyleIndex: iconStyleIndex,
75 - isGradientOnly:
76 - design.backgroundType == CardDesignBackgroundTypes.gradientOnly,
72 + isGradientOnly: design.backgroundType == CardDesignBackgroundTypes.gradientOnly,
73 cardOrder: cardOrder,
74 );
75 }
@@ -104,4 +100,4 @@ class BalanceCardStyleSettings {
100 Future<void> insert() async {
101 db!.insert(tableName, toJson(), conflictAlgorithm: ConflictAlgorithm.replace);
102 }
107 -}
\ No newline at end of file
103 +}
cw_core/lib/card_design.dart
+123 -110
@@ -12,14 +12,13 @@ class CardColorCombination {
12
13 const CardColorCombination(
14 {required this.textColor,
15 - required this.textColorSecondary,
16 - required this.backgroundImageColor});
15 + required this.textColorSecondary,
16 + required this.backgroundImageColor});
17
18 static const light = CardColorCombination(
19 textColor: Color.fromARGB(200, 255, 255, 255),
20 textColorSecondary: Colors.white54,
21 - backgroundImageColor: Color.fromARGB(200, 0, 0, 0)
22 - );
21 + backgroundImageColor: Color.fromARGB(200, 0, 0, 0));
22
23 static const dark = CardColorCombination(
24 textColor: Color.fromARGB(200, 0, 0, 0),
@@ -50,10 +49,11 @@ class CardDesign {
49
50 const CardDesign(
51 {this.backgroundType = CardDesignBackgroundTypes.svgIcon,
53 - this.gradient = const LinearGradient(colors: [Colors.black], begin: Alignment.topCenter, end: Alignment.bottomCenter),
54 - this.imagePath = "assets/new-ui/blank.svg",
55 - this.colors = CardColorCombination.dark,
56 - this.preColoredIcon = false});
52 + this.gradient = const LinearGradient(
53 + colors: [Colors.black], begin: Alignment.topCenter, end: Alignment.bottomCenter),
54 + this.imagePath = "assets/new-ui/blank.svg",
55 + this.colors = CardColorCombination.dark,
56 + this.preColoredIcon = false});
57
58 static const LinearGradient gradientOrange = LinearGradient(
59 colors: <Color>[Color(0xFFFF7C02), Color(0xFFFF5602)],
@@ -129,71 +129,50 @@ class CardDesign {
129
130 static const genericDefault = CardDesign(gradient: gradientBlue);
131
132 - static const gradientOnlyDesign = CardDesign(
133 - backgroundType: CardDesignBackgroundTypes.gradientOnly,
134 - gradient: gradientBlue);
135 -
136 - static const btc = CardDesign(
137 - imagePath: "assets/new-ui/balance_card_icons/bitcoin.svg");
138 -
139 - static const eth = CardDesign(
140 - imagePath: "assets/new-ui/balance_card_icons/ethereum.svg");
132 + static const gradientOnlyDesign =
133 + CardDesign(backgroundType: CardDesignBackgroundTypes.gradientOnly, gradient: gradientBlue);
134
142 - static const btcln = CardDesign(
143 - imagePath: "assets/new-ui/balance_card_icons/lightning.svg");
135 + static const btc = CardDesign(imagePath: "assets/new-ui/balance_card_icons/bitcoin.svg");
136
145 - static const xmr = CardDesign(
146 - imagePath: "assets/new-ui/balance_card_icons/monero.svg");
137 + static const eth = CardDesign(imagePath: "assets/new-ui/balance_card_icons/ethereum.svg");
138
148 - static const ltc = CardDesign(
149 - imagePath: "assets/new-ui/balance_card_icons/litecoin.svg");
139 + static const btcln = CardDesign(imagePath: "assets/new-ui/balance_card_icons/lightning.svg");
140
151 - static const bch = CardDesign(
152 - imagePath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
141 + static const xmr = CardDesign(imagePath: "assets/new-ui/balance_card_icons/monero.svg");
142
154 - static const doge = CardDesign(
155 - imagePath: "assets/new-ui/balance_card_icons/dogecoin.svg");
143 + static const ltc = CardDesign(imagePath: "assets/new-ui/balance_card_icons/litecoin.svg");
144
157 - static const base = CardDesign(
158 - imagePath: "assets/new-ui/balance_card_icons/base.svg");
145 + static const bch = CardDesign(imagePath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
146
160 - static const pol = CardDesign(
161 - imagePath: "assets/new-ui/balance_card_icons/polygon.svg");
147 + static const doge = CardDesign(imagePath: "assets/new-ui/balance_card_icons/dogecoin.svg");
148
163 - static const sol = CardDesign(
164 - imagePath: "assets/new-ui/balance_card_icons/solana.svg");
149 + static const base = CardDesign(imagePath: "assets/new-ui/balance_card_icons/base.svg");
150
166 - static const tron = CardDesign(
167 - imagePath: "assets/new-ui/balance_card_icons/tron.svg");
151 + static const pol = CardDesign(imagePath: "assets/new-ui/balance_card_icons/polygon.svg");
152
169 - static const nano = CardDesign(
170 - imagePath: "assets/new-ui/balance_card_icons/nano.svg");
153 + static const sol = CardDesign(imagePath: "assets/new-ui/balance_card_icons/solana.svg");
154
172 - static const zano = CardDesign(
173 - imagePath: "assets/new-ui/balance_card_icons/zano.svg");
155 + static const tron = CardDesign(imagePath: "assets/new-ui/balance_card_icons/tron.svg");
156
175 - static const wow = CardDesign(
176 - imagePath: "assets/new-ui/balance_card_icons/wownero.svg");
157 + static const nano = CardDesign(imagePath: "assets/new-ui/balance_card_icons/nano.svg");
158
178 - static const dcr = CardDesign(
179 - imagePath: "assets/new-ui/balance_card_icons/decred.svg");
159 + static const zano = CardDesign(imagePath: "assets/new-ui/balance_card_icons/zano.svg");
160
181 - static const arbitrum = CardDesign(
182 - imagePath: "assets/new-ui/balance_card_icons/arbitrum.svg");
161 + static const wow = CardDesign(imagePath: "assets/new-ui/balance_card_icons/wownero.svg");
162
184 - static const zec = CardDesign(
185 - imagePath: "assets/new-ui/balance_card_icons/zcash.svg");
163 + static const dcr = CardDesign(imagePath: "assets/new-ui/balance_card_icons/decred.svg");
164
187 - static const bnb = CardDesign(
188 - imagePath: "assets/new-ui/balance_card_icons/bnb.svg");
165 + static const arbitrum = CardDesign(imagePath: "assets/new-ui/balance_card_icons/arbitrum.svg");
166
167 + static const zec = CardDesign(imagePath: "assets/new-ui/balance_card_icons/zcash.svg");
168
169 + static const bnb = CardDesign(imagePath: "assets/new-ui/balance_card_icons/bnb.svg");
170
171 static const ethSpecial = CardDesign(
172 gradient: const LinearGradient(
173 colors: <Color>[Color(0xFF6259FF), Color(0xFF3B20E6)],
195 - begin: Alignment.topCenter, end: Alignment.bottomCenter
196 - ),
174 + begin: Alignment.topCenter,
175 + end: Alignment.bottomCenter),
176 backgroundType: CardDesignBackgroundTypes.svgFull,
177 colors: CardColorCombination.light,
178 imagePath: "assets/new-ui/balance_card_backgrounds/ethereum.svg");
@@ -201,24 +180,24 @@ class CardDesign {
180 static const btcSpecial = CardDesign(
181 gradient: const LinearGradient(
182 colors: <Color>[Color(0xFFFFBF00), Color(0xFFFF6A00)],
204 - begin: Alignment.topCenter, end: Alignment.bottomCenter
205 - ),
183 + begin: Alignment.topCenter,
184 + end: Alignment.bottomCenter),
185 backgroundType: CardDesignBackgroundTypes.svgFull,
186 imagePath: "assets/new-ui/balance_card_backgrounds/bitcoin.svg");
187
188 static const xmrSpecial = CardDesign(
189 gradient: const LinearGradient(
190 colors: <Color>[Color(0xFFFF5900), Color(0xFFE62E00)],
212 - begin: Alignment.topCenter, end: Alignment.bottomCenter
213 - ),
191 + begin: Alignment.topCenter,
192 + end: Alignment.bottomCenter),
193 backgroundType: CardDesignBackgroundTypes.svgFull,
194 imagePath: "assets/new-ui/balance_card_backgrounds/monero.svg");
195
196 static const ltcSpecial = CardDesign(
197 gradient: const LinearGradient(
198 colors: <Color>[Color(0xFF2145BF), Color(0xFF072071)],
220 - begin: Alignment.topCenter, end: Alignment.bottomCenter
221 - ),
199 + begin: Alignment.topCenter,
200 + end: Alignment.bottomCenter),
201 backgroundType: CardDesignBackgroundTypes.svgFull,
202 colors: CardColorCombination.light,
203 imagePath: "assets/new-ui/balance_card_backgrounds/litecoin.svg");
@@ -226,8 +205,8 @@ class CardDesign {
205 static const lnSpecial = CardDesign(
206 gradient: const LinearGradient(
207 colors: <Color>[Color(0xFFFFBF00), Color(0xFFFF6A00)],
229 - begin: Alignment.topCenter, end: Alignment.bottomCenter
230 - ),
208 + begin: Alignment.topCenter,
209 + end: Alignment.bottomCenter),
210 backgroundType: CardDesignBackgroundTypes.svgFull,
211 colors: CardColorCombination.dark,
212 imagePath: "assets/new-ui/balance_card_backgrounds/lightning.svg");
@@ -235,8 +214,8 @@ class CardDesign {
214 static const tronSpecial = CardDesign(
215 gradient: const LinearGradient(
216 colors: <Color>[Color(0xFFFF1313), Color(0xFFB40000)],
238 - begin: Alignment.topCenter, end: Alignment.bottomCenter
239 - ),
217 + begin: Alignment.topCenter,
218 + end: Alignment.bottomCenter),
219 backgroundType: CardDesignBackgroundTypes.svgFull,
220 colors: CardColorCombination.light,
221 imagePath: "assets/new-ui/balance_card_backgrounds/tron.svg");
@@ -244,8 +223,8 @@ class CardDesign {
223 static const solSpecial = CardDesign(
224 gradient: const LinearGradient(
225 colors: <Color>[Color(0xFF4701AA), Color(0xFF19004B)],
247 - begin: Alignment.topCenter, end: Alignment.bottomCenter
248 - ),
226 + begin: Alignment.topCenter,
227 + end: Alignment.bottomCenter),
228 backgroundType: CardDesignBackgroundTypes.svgFull,
229 colors: CardColorCombination.light,
230 imagePath: "assets/new-ui/balance_card_backgrounds/solana.svg");
@@ -253,40 +232,40 @@ class CardDesign {
232 static const bchSpecial = CardDesign(
233 gradient: const LinearGradient(
234 colors: <Color>[Color(0xFF36DA4C), Color(0xFF008D57)],
256 - begin: Alignment.topCenter, end: Alignment.bottomCenter
257 - ),
235 + begin: Alignment.topCenter,
236 + end: Alignment.bottomCenter),
237 backgroundType: CardDesignBackgroundTypes.svgFull,
238 imagePath: "assets/new-ui/balance_card_backgrounds/bitcoin-cash.svg");
239
240 static const wowSpecial = CardDesign(
241 gradient: const LinearGradient(
242 colors: <Color>[Color(0xFFFF6CD3), Color(0xFFF200A9)],
264 - begin: Alignment.topCenter, end: Alignment.bottomCenter
265 - ),
243 + begin: Alignment.topCenter,
244 + end: Alignment.bottomCenter),
245 backgroundType: CardDesignBackgroundTypes.svgFull,
246 imagePath: "assets/new-ui/balance_card_backgrounds/wownero.svg");
247
248 static const dogeSpecial = CardDesign(
249 gradient: const LinearGradient(
250 colors: <Color>[Color(0xFFCBA818), Color(0xFF885D00)],
272 - begin: Alignment.topCenter, end: Alignment.bottomCenter
273 - ),
251 + begin: Alignment.topCenter,
252 + end: Alignment.bottomCenter),
253 backgroundType: CardDesignBackgroundTypes.svgFull,
254 imagePath: "assets/new-ui/balance_card_backgrounds/dogecoin.svg");
255
256 static const nanoSpecial = CardDesign(
257 gradient: const LinearGradient(
258 colors: <Color>[Color(0xFF209CE9), Color(0xFF0073CB)],
280 - begin: Alignment.topCenter, end: Alignment.bottomCenter
281 - ),
259 + begin: Alignment.topCenter,
260 + end: Alignment.bottomCenter),
261 backgroundType: CardDesignBackgroundTypes.svgFull,
262 imagePath: "assets/new-ui/balance_card_backgrounds/nano.svg");
263
264 static const polSpecial = CardDesign(
265 gradient: const LinearGradient(
266 colors: <Color>[Color(0xFF863FE3), Color(0xFF59098E)],
288 - begin: Alignment.topCenter, end: Alignment.bottomCenter
289 - ),
267 + begin: Alignment.topCenter,
268 + end: Alignment.bottomCenter),
269 backgroundType: CardDesignBackgroundTypes.svgFull,
270 colors: CardColorCombination.light,
271 imagePath: "assets/new-ui/balance_card_backgrounds/polygon.svg");
@@ -294,8 +273,8 @@ class CardDesign {
273 static const dcrSpecial = CardDesign(
274 gradient: const LinearGradient(
275 colors: <Color>[Color(0xFF2871FF), Color(0xFF0057FF)],
297 - begin: Alignment.topCenter, end: Alignment.bottomCenter
298 - ),
276 + begin: Alignment.topCenter,
277 + end: Alignment.bottomCenter),
278 colors: CardColorCombination.light,
279 backgroundType: CardDesignBackgroundTypes.svgFull,
280 imagePath: "assets/new-ui/balance_card_backgrounds/decred.svg");
@@ -303,8 +282,8 @@ class CardDesign {
282 static const zanoSpecial = CardDesign(
283 gradient: const LinearGradient(
284 colors: <Color>[Color(0xFF0004B4), Color(0xFF170069)],
306 - begin: Alignment.topCenter, end: Alignment.bottomCenter
307 - ),
285 + begin: Alignment.topCenter,
286 + end: Alignment.bottomCenter),
287 colors: CardColorCombination.black,
288 backgroundType: CardDesignBackgroundTypes.svgFull,
289 imagePath: "assets/new-ui/balance_card_backgrounds/zano.svg");
@@ -312,8 +291,8 @@ class CardDesign {
291 static const baseSpecial = CardDesign(
292 gradient: const LinearGradient(
293 colors: <Color>[Color(0xFF003CFF), Color(0xFF000087)],
315 - begin: Alignment.topCenter, end: Alignment.bottomCenter
316 - ),
294 + begin: Alignment.topCenter,
295 + end: Alignment.bottomCenter),
296 colors: CardColorCombination.light,
297 backgroundType: CardDesignBackgroundTypes.svgFull,
298 imagePath: "assets/new-ui/balance_card_backgrounds/base.svg");
@@ -321,8 +300,8 @@ class CardDesign {
300 static const arbitrumSpecial = CardDesign(
301 gradient: const LinearGradient(
302 colors: <Color>[Color(0xFF173F76), Color(0xFF031A39)],
324 - begin: Alignment.topCenter, end: Alignment.bottomCenter
325 - ),
303 + begin: Alignment.topCenter,
304 + end: Alignment.bottomCenter),
305 colors: CardColorCombination.light,
306 backgroundType: CardDesignBackgroundTypes.svgFull,
307 imagePath: "assets/new-ui/balance_card_backgrounds/arbitrum.svg");
@@ -330,16 +309,16 @@ class CardDesign {
309 static const zecSpecial = CardDesign(
310 gradient: const LinearGradient(
311 colors: <Color>[Color(0xFFF6C527), Color(0xFFCD8C00)],
333 - begin: Alignment.topCenter, end: Alignment.bottomCenter
334 - ),
312 + begin: Alignment.topCenter,
313 + end: Alignment.bottomCenter),
314 backgroundType: CardDesignBackgroundTypes.svgFull,
315 imagePath: "assets/new-ui/balance_card_backgrounds/zcash.svg");
316
317 static const bnbSpecial = CardDesign(
318 gradient: const LinearGradient(
319 colors: <Color>[Color(0xFF603000), Color(0xFFF0B90B)],
341 - begin: Alignment.topCenter, end: Alignment.bottomCenter
342 - ),
320 + begin: Alignment.topCenter,
321 + end: Alignment.bottomCenter),
322 colors: CardColorCombination.light,
323 backgroundType: CardDesignBackgroundTypes.svgFull,
324 imagePath: "assets/new-ui/balance_card_backgrounds/bnb.svg");
@@ -351,12 +330,14 @@ class CardDesign {
330 backgroundType: backgroundType,
331 preColoredIcon: preColoredIcon);
332
354 - CardDesign withGradientAndColorCombination(Gradient gradient, CardColorCombination cardColorCombination) => CardDesign(
355 - gradient: gradient,
356 - colors: cardColorCombination,
357 - imagePath: imagePath,
358 - backgroundType: backgroundType,
359 - preColoredIcon: preColoredIcon);
333 + CardDesign withGradientAndColorCombination(
334 + Gradient gradient, CardColorCombination cardColorCombination) =>
335 + CardDesign(
336 + gradient: gradient,
337 + colors: cardColorCombination,
338 + imagePath: imagePath,
339 + backgroundType: backgroundType,
340 + preColoredIcon: preColoredIcon);
341
342 CardDesign withIcon(CardIconPath icon) => CardDesign(
343 gradient: gradient,
@@ -374,8 +355,10 @@ class CardDesign {
355
356 static const Map<CryptoCurrency, _CurrencyIconNames> _iconNames = {
357 CryptoCurrency.arbEth: _CurrencyIconNames(ticker: 'arb', longName: 'arbitrum'),
377 - CryptoCurrency.baseEth: _CurrencyIconNames(ticker: 'base', longName: 'base', chainFile: 'base_icon'),
378 - CryptoCurrency.bch: _CurrencyIconNames(ticker: 'bch', longName: 'bitcoin_cash', chainFile: 'bitcoin-cash'),
358 + CryptoCurrency.baseEth:
359 + _CurrencyIconNames(ticker: 'base', longName: 'base', chainFile: 'base_icon'),
360 + CryptoCurrency.bch:
361 + _CurrencyIconNames(ticker: 'bch', longName: 'bitcoin_cash', chainFile: 'bitcoin-cash'),
362 CryptoCurrency.btc: _CurrencyIconNames(ticker: 'btc', longName: 'bitcoin', outlineFile: 'BTC'),
363 CryptoCurrency.bnb: _CurrencyIconNames(ticker: 'bnb', longName: 'bnb'),
364 CryptoCurrency.dcr: _CurrencyIconNames(ticker: 'dcr', longName: 'decred'),
@@ -383,13 +366,13 @@ class CardDesign {
366 CryptoCurrency.eth: _CurrencyIconNames(ticker: 'eth', longName: 'ethereum'),
367 CryptoCurrency.btcln: _CurrencyIconNames(ticker: 'ln', longName: 'lightning'),
368 CryptoCurrency.ltc: _CurrencyIconNames(ticker: 'ltc', longName: 'litecoin'),
386 - CryptoCurrency.xmr: _CurrencyIconNames(
387 - ticker: 'xmr', longName: 'monero', ogPath: 'assets/images/xmr-og.webp'),
369 + CryptoCurrency.xmr:
370 + _CurrencyIconNames(ticker: 'xmr', longName: 'monero', ogPath: 'assets/images/xmr-og.webp'),
371 CryptoCurrency.nano: _CurrencyIconNames(ticker: 'xno', longName: 'nano'),
372 CryptoCurrency.maticpoly: _CurrencyIconNames(ticker: 'pol', longName: 'polygon'),
373 CryptoCurrency.sol: _CurrencyIconNames(ticker: 'sol', longName: 'solana'),
391 - CryptoCurrency.trx: _CurrencyIconNames(
392 - ticker: 'trx', longName: 'tron', ogPath: '$_ogIconPrefix/tron-og.svg'),
374 + CryptoCurrency.trx:
375 + _CurrencyIconNames(ticker: 'trx', longName: 'tron', ogPath: '$_ogIconPrefix/tron-og.svg'),
376 CryptoCurrency.zano: _CurrencyIconNames(ticker: 'zano', longName: 'zano'),
377 CryptoCurrency.zec: _CurrencyIconNames(ticker: 'zec', longName: 'zcash'),
378 };
@@ -408,7 +391,40 @@ class CardDesign {
391 ];
392 }
393
411 - static const List<CardDesign> all = [genericDefault, btc, eth, xmr, ltc, eth, pol, doge, base, sol, btcln, tron, zano, dcr, arbitrum, zec, bnb, ethSpecial, btcSpecial, xmrSpecial, ltcSpecial, lnSpecial, tronSpecial, bchSpecial, wowSpecial, dogeSpecial, polSpecial, dcrSpecial, zanoSpecial, arbitrumSpecial, zecSpecial, bnbSpecial];
394 + static const List<CardDesign> all = [
395 + genericDefault,
396 + btc,
397 + eth,
398 + xmr,
399 + ltc,
400 + eth,
401 + pol,
402 + doge,
403 + base,
404 + sol,
405 + btcln,
406 + tron,
407 + zano,
408 + dcr,
409 + arbitrum,
410 + zec,
411 + bnb,
412 + ethSpecial,
413 + btcSpecial,
414 + xmrSpecial,
415 + ltcSpecial,
416 + lnSpecial,
417 + tronSpecial,
418 + bchSpecial,
419 + wowSpecial,
420 + dogeSpecial,
421 + polSpecial,
422 + dcrSpecial,
423 + zanoSpecial,
424 + arbitrumSpecial,
425 + zecSpecial,
426 + bnbSpecial
427 + ];
428
429 static CardDesign forCurrencySpecial(CryptoCurrency currency) {
430 return specialDesignsForCurrencies[currency] ?? genericDefault;
@@ -437,7 +453,6 @@ class CardDesign {
453 CryptoCurrency.zec: zec,
454 CryptoCurrency.dcr: dcr,
455 CryptoCurrency.bnb: bnb,
440 -
456 };
457
458 static const Map<CryptoCurrency, CardDesign> specialDesignsForCurrencies = {
@@ -504,9 +519,9 @@ class CardDesign {
519
520 if (setting.isGradientOnly) {
521 final gradient = gradientForStoredIndex(setting.gradientIndex, walletCurrency);
507 - final textColors = preferredColorCombinations[gradient]
508 - ?? specialDesignsForCurrencies[walletCurrency]?.colors
509 - ?? gradientOnlyDesign.colors;
522 + final textColors = preferredColorCombinations[gradient] ??
523 + specialDesignsForCurrencies[walletCurrency]?.colors ??
524 + gradientOnlyDesign.colors;
525 return gradientOnlyDesign.withGradientAndColorCombination(gradient, textColors);
526 }
527
@@ -521,11 +536,9 @@ class CardDesign {
536 }
537
538 if (!setting.useSpecialDesign && setting.gradientIndex == -1) {
524 - final specialColors =
525 - specialDesignsForCurrencies[walletCurrency] ?? genericDefault;
539 + final specialColors = specialDesignsForCurrencies[walletCurrency] ?? genericDefault;
540 final design = CardDesign.forCurrencyIcon(walletCurrency)
527 - .withGradientAndColorCombination(
528 - specialColors.gradient, specialColors.colors);
541 + .withGradientAndColorCombination(specialColors.gradient, specialColors.colors);
542 return design.withIconStyleIndex(setting.iconStyleIndex, walletCurrency);
543 }
544 if (setting.useSpecialDesign) {
@@ -534,9 +547,9 @@ class CardDesign {
547 if (setting.gradientIndex != -1) {
548 final baseIcon = CardDesign.forCurrencyIcon(walletCurrency);
549 final gradient = gradientForStoredIndex(setting.gradientIndex, walletCurrency);
537 - final textColors = preferredColorCombinations[gradient]
538 - ?? specialDesignsForCurrencies[walletCurrency]?.colors
539 - ?? baseIcon.colors;
550 + final textColors = preferredColorCombinations[gradient] ??
551 + specialDesignsForCurrencies[walletCurrency]?.colors ??
552 + baseIcon.colors;
553 return baseIcon
554 .withGradientAndColorCombination(gradient, textColors)
555 .withIconStyleIndex(setting.iconStyleIndex, walletCurrency);
@@ -561,4 +574,4 @@ class _CurrencyIconNames {
574 this.chainFile,
575 this.ogPath,
576 });
564 -}
\ No newline at end of file
577 +}
cw_core/lib/crypto_amount_format.dart
-1
@@ -37,7 +37,6 @@ extension MaxDecimals on String {
37 return parts.join(".");
38 }
39
40 -
40 /// Format a stringified number to a localized representation
41 /// 1.000.000,00 in de_DE
42 /// 1’000’000.00 in de_CH
cw_core/lib/crypto_currency.dart
+848 -149
@@ -161,143 +161,846 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
161
162 // well technically not currencies but since we had them a long time ago and don't want to break
163 // the app for users who had contacts saved for them
164 - static const zcashCurrencies = [ zec, zaddr, tzec ];
164 + static const zcashCurrencies = [zec, zaddr, tzec];
165
166 // title, tag (if applicable), fullName (if unique), raw, name, iconPath
167 - static const xmr = CryptoCurrency(title: 'XMR', fullName: 'Monero', raw: 0, name: 'xmr', iconPath: 'assets/new-ui/crypto_full_icons/monero.svg', decimals: 12, flatIconPath: "assets/new-ui/balance_card_icons/monero.svg");
168 - static const ada = CryptoCurrency(title: 'ADA', fullName: 'Cardano', raw: 1, name: 'ada', iconPath: 'assets/images/ada_icon.png', decimals: 6);
169 - static const bch = CryptoCurrency(title: 'BCH', fullName: 'Bitcoin Cash', raw: 2, name: 'bch', iconPath: 'assets/new-ui/crypto_full_icons/bitcoin-cash.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
170 - static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'BNB', raw: 3, name: 'bnb', iconPath: 'assets/new-ui/crypto_full_icons/bnb.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/bnb.svg", chainIconPath: "assets/new-ui/chain_badges/bnb.svg");
171 - static const btc = CryptoCurrency(title: 'BTC', fullName: 'Bitcoin', raw: 4, name: 'btc', iconPath: 'assets/new-ui/crypto_full_icons/bitcoin.svg' ,decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/bitcoin.svg");
172 - static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/new-ui/crypto_full_icons/dai.svg', decimals: 18, groups: const {CurrencyGroups.stablecoin});
173 - static const dash = CryptoCurrency(title: 'DASH', fullName: 'Dash', raw: 6, name: 'dash', iconPath: 'assets/images/dash_icon.png', decimals: 8);
174 - static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png', decimals: 4);
175 - static const eth = CryptoCurrency(title: 'ETH', fullName: 'Ethereum', raw: 8, name: 'eth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/ethereum.svg", chainIconPath: "assets/new-ui/chain_badges/ethereum.svg");
176 - static const ltc = CryptoCurrency(title: 'LTC', fullName: 'Litecoin', raw: 9, name: 'ltc', iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/litecoin.svg", chainIconPath: "assets/new-ui/chain_badges/mweb.svg");
177 - static const nano = CryptoCurrency(title: 'XNO', fullName: 'Nano', raw: 10, name: 'xno', iconPath: 'assets/new-ui/crypto_full_icons/nano.svg', decimals: 30, flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
178 - static const trx = CryptoCurrency(title: 'TRX', fullName: 'TRON', raw: 11, name: 'trx', iconPath: 'assets/new-ui/crypto_full_icons/tron.svg', decimals: 6, flatIconPath: "assets/new-ui/balance_card_icons/tron.svg", chainIconPath: "assets/new-ui/chain_badges/tron.svg");
179 - static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'Tether', raw: 12, name: 'usdt', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
180 - static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
181 - static const xlm = CryptoCurrency(title: 'XLM', fullName: 'Stellar', raw: 14, name: 'xlm', iconPath: 'assets/images/xlm_icon.png', decimals: 7);
182 - static const xrp = CryptoCurrency(title: 'XRP', fullName: 'Ripple', raw: 15, name: 'xrp', iconPath: 'assets/images/xrp_icon.png', decimals: 6);
183 - static const xhv = CryptoCurrency(title: 'XHV', fullName: 'Haven Protocol', raw: 16, name: 'xhv', iconPath: 'assets/images/xhv_logo.png', decimals: 12);
184 -
185 - static const xag = CryptoCurrency(title: 'XAG', tag: 'XHV', raw: 17, name: 'xag', decimals: 12);
167 + static const xmr = CryptoCurrency(
168 + title: 'XMR',
169 + fullName: 'Monero',
170 + raw: 0,
171 + name: 'xmr',
172 + iconPath: 'assets/new-ui/crypto_full_icons/monero.svg',
173 + decimals: 12,
174 + flatIconPath: "assets/new-ui/balance_card_icons/monero.svg");
175 + static const ada = CryptoCurrency(
176 + title: 'ADA',
177 + fullName: 'Cardano',
178 + raw: 1,
179 + name: 'ada',
180 + iconPath: 'assets/images/ada_icon.png',
181 + decimals: 6);
182 + static const bch = CryptoCurrency(
183 + title: 'BCH',
184 + fullName: 'Bitcoin Cash',
185 + raw: 2,
186 + name: 'bch',
187 + iconPath: 'assets/new-ui/crypto_full_icons/bitcoin-cash.svg',
188 + decimals: 8,
189 + flatIconPath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
190 + static const bnb = CryptoCurrency(
191 + title: 'BNB',
192 + tag: 'BSC',
193 + fullName: 'BNB',
194 + raw: 3,
195 + name: 'bnb',
196 + iconPath: 'assets/new-ui/crypto_full_icons/bnb.svg',
197 + decimals: 18,
198 + flatIconPath: "assets/new-ui/balance_card_icons/bnb.svg",
199 + chainIconPath: "assets/new-ui/chain_badges/bnb.svg");
200 + static const btc = CryptoCurrency(
201 + title: 'BTC',
202 + fullName: 'Bitcoin',
203 + raw: 4,
204 + name: 'btc',
205 + iconPath: 'assets/new-ui/crypto_full_icons/bitcoin.svg',
206 + decimals: 8,
207 + flatIconPath: "assets/new-ui/balance_card_icons/bitcoin.svg");
208 + static const dai = CryptoCurrency(
209 + title: 'DAI',
210 + tag: 'ETH',
211 + fullName: 'Dai',
212 + raw: 5,
213 + name: 'dai',
214 + iconPath: 'assets/new-ui/crypto_full_icons/dai.svg',
215 + decimals: 18,
216 + groups: const {CurrencyGroups.stablecoin});
217 + static const dash = CryptoCurrency(
218 + title: 'DASH',
219 + fullName: 'Dash',
220 + raw: 6,
221 + name: 'dash',
222 + iconPath: 'assets/images/dash_icon.png',
223 + decimals: 8);
224 + static const eos = CryptoCurrency(
225 + title: 'EOS',
226 + fullName: 'EOS',
227 + raw: 7,
228 + name: 'eos',
229 + iconPath: 'assets/images/eos_icon.png',
230 + decimals: 4);
231 + static const eth = CryptoCurrency(
232 + title: 'ETH',
233 + fullName: 'Ethereum',
234 + raw: 8,
235 + name: 'eth',
236 + iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
237 + decimals: 18,
238 + flatIconPath: "assets/new-ui/balance_card_icons/ethereum.svg",
239 + chainIconPath: "assets/new-ui/chain_badges/ethereum.svg");
240 + static const ltc = CryptoCurrency(
241 + title: 'LTC',
242 + fullName: 'Litecoin',
243 + raw: 9,
244 + name: 'ltc',
245 + iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg',
246 + decimals: 8,
247 + flatIconPath: "assets/new-ui/balance_card_icons/litecoin.svg",
248 + chainIconPath: "assets/new-ui/chain_badges/mweb.svg");
249 + static const nano = CryptoCurrency(
250 + title: 'XNO',
251 + fullName: 'Nano',
252 + raw: 10,
253 + name: 'xno',
254 + iconPath: 'assets/new-ui/crypto_full_icons/nano.svg',
255 + decimals: 30,
256 + flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
257 + static const trx = CryptoCurrency(
258 + title: 'TRX',
259 + fullName: 'TRON',
260 + raw: 11,
261 + name: 'trx',
262 + iconPath: 'assets/new-ui/crypto_full_icons/tron.svg',
263 + decimals: 6,
264 + flatIconPath: "assets/new-ui/balance_card_icons/tron.svg",
265 + chainIconPath: "assets/new-ui/chain_badges/tron.svg");
266 + static const usdt = CryptoCurrency(
267 + title: 'USDT',
268 + tag: 'OMNI',
269 + fullName: 'Tether',
270 + raw: 12,
271 + name: 'usdt',
272 + iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
273 + decimals: 6,
274 + groups: const {CurrencyGroups.stablecoin});
275 + static const usdterc20 = CryptoCurrency(
276 + title: 'USDT',
277 + tag: 'ETH',
278 + fullName: 'Tether',
279 + raw: 13,
280 + name: 'usdterc20',
281 + iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
282 + decimals: 6,
283 + groups: const {CurrencyGroups.stablecoin});
284 + static const xlm = CryptoCurrency(
285 + title: 'XLM',
286 + fullName: 'Stellar',
287 + raw: 14,
288 + name: 'xlm',
289 + iconPath: 'assets/images/xlm_icon.png',
290 + decimals: 7);
291 + static const xrp = CryptoCurrency(
292 + title: 'XRP',
293 + fullName: 'Ripple',
294 + raw: 15,
295 + name: 'xrp',
296 + iconPath: 'assets/images/xrp_icon.png',
297 + decimals: 6);
298 + static const xhv = CryptoCurrency(
299 + title: 'XHV',
300 + fullName: 'Haven Protocol',
301 + raw: 16,
302 + name: 'xhv',
303 + iconPath: 'assets/images/xhv_logo.png',
304 + decimals: 12);
305 +
306 + static const xag = CryptoCurrency(title: 'XAG', tag: 'XHV', raw: 17, name: 'xag', decimals: 12);
307 static const xau = CryptoCurrency(title: 'XAU', tag: 'XHV', raw: 18, name: 'xau', decimals: 12);
187 - static const xaud = CryptoCurrency(title: 'XAUD', tag: 'XHV', raw: 19, name: 'xaud', decimals: 12);
188 - static const xbtc = CryptoCurrency(title: 'XBTC', tag: 'XHV', raw: 20, name: 'xbtc', decimals: 12);
189 - static const xcad = CryptoCurrency(title: 'XCAD', tag: 'XHV', raw: 21, name: 'xcad', decimals: 12);
190 - static const xchf = CryptoCurrency(title: 'XCHF', tag: 'XHV', raw: 22, name: 'xchf', decimals: 12);
191 - static const xcny = CryptoCurrency(title: 'XCNY', tag: 'XHV', raw: 23, name: 'xcny', decimals: 12);
192 - static const xeur = CryptoCurrency(title: 'XEUR', tag: 'XHV', raw: 24, name: 'xeur', decimals: 12);
193 - static const xgbp = CryptoCurrency(title: 'XGBP', tag: 'XHV', raw: 25, name: 'xgbp', decimals: 12);
194 - static const xjpy = CryptoCurrency(title: 'XJPY', tag: 'XHV', raw: 26, name: 'xjpy', decimals: 12);
195 - static const xnok = CryptoCurrency(title: 'XNOK', tag: 'XHV', raw: 27, name: 'xnok', decimals: 12);
196 - static const xnzd = CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28, name: 'xnzd', decimals: 12);
197 - static const xusd = CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29, name: 'xusd', decimals: 12);
198 -
199 - static const ape = CryptoCurrency(title: 'APE', tag: 'ETH', fullName: 'ApeCoin', raw: 30, name: 'ape', iconPath: 'assets/images/ape_icon.png', decimals: 18);
200 - static const avaxc = CryptoCurrency(title: 'AVAX', tag: 'AVAXC', fullName: 'Avalanche', raw: 31, name: 'avaxc', iconPath: 'assets/new-ui/crypto_full_icons/avax.svg', decimals: 9);
201 - static const btt = CryptoCurrency(title: 'BTT', tag: 'ETH', fullName: 'BitTorrent', raw: 32, name: 'btt', iconPath: 'assets/images/btt_icon.png', decimals: 18);
202 - static const bttc = CryptoCurrency(title: 'BTTC', tag: 'TRX', fullName: 'BitTorrent-NEW', raw: 33, name: 'bttc', iconPath: 'assets/images/btt_icon.png', decimals: 18);
203 - static const doge = CryptoCurrency(title: 'DOGE', fullName: 'Dogecoin', raw: 34, name: 'doge', iconPath: 'assets/new-ui/crypto_full_icons/dogecoin.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/dogecoin.svg");
204 - static const firo = CryptoCurrency(title: 'FIRO', raw: 35, name: 'firo', iconPath: 'assets/images/firo_icon.png', decimals: 8);
205 - static const usdttrc20 = CryptoCurrency(title: 'USDT', tag: 'TRX', fullName: 'Tether', raw: 36, name: 'usdttrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
206 - static const hbar = CryptoCurrency(title: 'HBAR', fullName: 'Hedera', raw: 37, name: 'hbar', iconPath: 'assets/images/hbar_icon.png', decimals: 8);
207 - static const sc = CryptoCurrency(title: 'SC', fullName: 'Siacoin', raw: 38, name: 'sc', iconPath: 'assets/images/sc_icon.png', decimals: 16);
208 - static const sol = CryptoCurrency(title: 'SOL', fullName: 'Solana', raw: 39, name: 'sol', iconPath: 'assets/new-ui/crypto_full_icons/solana.svg', decimals: 9, flatIconPath: "assets/new-ui/balance_card_icons/solana.svg", chainIconPath: "assets/new-ui/chain_badges/solana.svg");
209 - static const usdc = CryptoCurrency(title: 'USDC', tag: 'ETH', fullName: 'USDC', raw: 40, name: 'usdc', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
210 - static const usdcsol = CryptoCurrency(title: 'USDC', tag: 'SOL', fullName: 'USDC Coin', raw: 41, name: 'usdcsol', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
211 - static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', fullName: 'Shielded Zcash', raw: 42, name: 'zaddr', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8);
212 - static const tzec = CryptoCurrency(title: 'tZEC', tag: 'ZEC', fullName: 'Transparent Zcash', raw: 43, name: 'zec', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8);
213 - static const zen = CryptoCurrency(title: 'ZEN', fullName: 'Horizen', raw: 44, name: 'zen', iconPath: 'assets/images/zen_icon.png', decimals: 8);
214 - static const xvg = CryptoCurrency(title: 'XVG', fullName: 'Verge', raw: 45, name: 'xvg', iconPath: 'assets/images/xvg_icon.png', decimals: 8);
215 -
216 - static const usdcpoly = CryptoCurrency(title: 'USDC', tag: 'POL', fullName: 'USDC', raw: 46, name: 'usdcpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
217 - static const dcr = CryptoCurrency(title: 'DCR', fullName: 'Decred', raw: 47, name: 'dcr', iconPath: 'assets/new-ui/crypto_full_icons/decred.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/decred.svg");
218 - static const kmd = CryptoCurrency(title: 'KMD', fullName: 'Komodo', raw: 48, name: 'kmd', iconPath: 'assets/images/kmd_icon.png', decimals: 8);
219 - static const mana = CryptoCurrency(title: 'MANA', tag: 'ETH', fullName: 'Decentraland', raw: 49, name: 'mana', iconPath: 'assets/images/mana_icon.png', decimals: 18);
220 - static const maticpoly = CryptoCurrency(title: 'POL', tag: 'POL', fullName: 'Polygon', raw: 50, name: 'maticpoly', iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg", chainIconPath: "assets/new-ui/chain_badges/polygon.svg");
221 - static const matic = CryptoCurrency(title: 'MATIC', tag: 'ETH', fullName: 'Polygon', raw: 51, name: 'matic', iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg");
222 - static const mkr = CryptoCurrency(title: 'MKR', tag: 'ETH', fullName: 'Maker', raw: 52, name: 'mkr', iconPath: 'assets/images/mkr_icon.png', decimals: 18);
223 - static const near = CryptoCurrency(title: 'NEAR', fullName: 'NEAR Protocol', raw: 53, name: 'near', iconPath: 'assets/images/near_icon.png', decimals: 24);
224 - static const oxt = CryptoCurrency(title: 'OXT', tag: 'ETH', fullName: 'Orchid', raw: 54, name: 'oxt', iconPath: 'assets/images/oxt_icon.png', decimals: 18);
225 - static const paxg = CryptoCurrency(title: 'PAXG', tag: 'ETH', fullName: 'Pax Gold', raw: 55, name: 'paxg', iconPath: 'assets/new-ui/crypto_full_icons/paxg.svg', decimals: 18);
226 - static const pivx = CryptoCurrency(title: 'PIVX', raw: 56, name: 'pivx', iconPath: 'assets/images/pivx_icon.png', decimals: 8);
227 - static const rune = CryptoCurrency(title: 'RUNE', fullName: 'Thorchain', raw: 57, name: 'rune', iconPath: 'assets/images/rune_icon.png', decimals: 18);
228 - static const rvn = CryptoCurrency(title: 'RVN', fullName: 'Ravencoin', raw: 58, name: 'rvn', iconPath: 'assets/images/rvn_icon.png', decimals: 8);
229 - static const scrt = CryptoCurrency(title: 'SCRT', fullName: 'Secret Network', raw: 59, name: 'scrt', iconPath: 'assets/images/scrt_icon.png', decimals: 6);
230 - static const uni = CryptoCurrency(title: 'UNI', tag: 'ETH', fullName: 'Uniswap', raw: 60, name: 'uni', iconPath: 'assets/images/uni_icon.png', decimals: 18);
231 - static const stx = CryptoCurrency(title: 'STX', fullName: 'Stacks', raw: 61, name: 'stx', iconPath: 'assets/images/stx_icon.png', decimals: 8);
232 - static const btcln = CryptoCurrency(title: 'BTC', tag: 'LN', fullName: 'Bitcoin Lightning Network', raw: 62, name: 'btcln', iconPath: 'assets/new-ui/crypto_full_icons/lightning.svg', chainIconPath: "assets/new-ui/chain_badges/lightning.svg", decimals: 8);
233 - static const shib = CryptoCurrency(title: 'SHIB', tag: 'ETH', fullName: 'Shiba Inu', raw: 63, name: 'shib', iconPath: 'assets/images/shib_icon.png', decimals: 18);
234 - static const aave = CryptoCurrency(title: 'AAVE', tag: 'ETH', fullName: 'Aave', raw: 64, name: 'aave', iconPath: 'assets/images/aave_icon.png', decimals: 18);
235 - static const arb = CryptoCurrency(title: 'ARB', fullName: 'Arbitrum', raw: 65, name: 'arb', iconPath: 'assets/new-ui/crypto_full_icons/arbitrum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg", chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
236 - static const bat = CryptoCurrency(title: 'BAT', tag: 'ETH', fullName: 'Basic Attention Token', raw: 66, name: 'bat', iconPath: 'assets/images/bat_icon.png', decimals: 18);
237 - static const comp = CryptoCurrency(title: 'COMP', tag: 'ETH', fullName: 'Compound', raw: 67, name: 'comp', iconPath: 'assets/images/comp_icon.png', decimals: 18);
238 - static const cro = CryptoCurrency(title: 'CRO', tag: 'ETH', fullName: 'Crypto.com Cronos', raw: 68, name: 'cro', iconPath: 'assets/images/cro_icon.png', decimals: 8);
239 - static const ens = CryptoCurrency(title: 'ENS', tag: 'ETH', fullName: 'Ethereum Name Service', raw: 69, name: 'ens', iconPath: 'assets/images/ens_icon.png', decimals: 18);
240 - static const ftm = CryptoCurrency(title: 'FTM', tag: 'ETH', fullName: 'Fantom', raw: 70, name: 'ftm', iconPath: 'assets/images/ftm_icon.png', decimals: 18);
241 - static const frax = CryptoCurrency(title: 'FRAX', tag: 'ETH', fullName: 'Frax', raw: 71, name: 'frax', iconPath: 'assets/images/frax_icon.png', decimals: 18);
242 - static const gusd = CryptoCurrency(title: 'GUSD', tag: 'ETH', fullName: 'Gemini USD', raw: 72, name: 'gusd', iconPath: 'assets/images/gusd_icon.png', decimals: 2);
243 - static const gtc = CryptoCurrency(title: 'GTC', tag: 'ETH', fullName: 'Gitcoin', raw: 73, name: 'gtc', iconPath: 'assets/images/gtc_icon.png', decimals: 18);
244 - static const grt = CryptoCurrency(title: 'GRT', tag: 'ETH', fullName: 'The Graph', raw: 74, name: 'grt', iconPath: 'assets/images/grt_icon.png', decimals: 18);
245 - static const ldo = CryptoCurrency(title: 'LDO', tag: 'ETH', fullName: 'Lido DAO', raw: 75, name: 'ldo', iconPath: 'assets/images/ldo_icon.png', decimals: 18);
246 - static const nexo = CryptoCurrency(title: 'NEXO', tag: 'ETH', fullName: 'Nexo', raw: 76, name: 'nexo', iconPath: 'assets/images/nexo_icon.png', decimals: 18);
247 - static const cake = CryptoCurrency(title: 'CAKE', tag: 'BSC', fullName: 'PancakeSwap', raw: 77, name: 'cake', iconPath: 'assets/images/cake_icon.png', decimals: 18);
248 - static const pepe = CryptoCurrency(title: 'PEPE', tag: 'ETH', fullName: 'Pepe', raw: 78, name: 'pepe', iconPath: 'assets/images/pepe_icon.png', decimals: 18);
249 - static const storj = CryptoCurrency(title: 'STORJ', tag: 'ETH', fullName: 'Storj', raw: 79, name: 'storj', iconPath: 'assets/images/storj_icon.png', decimals: 8);
250 - static const tusd = CryptoCurrency(title: 'TUSD', tag: 'ETH', fullName: 'TrueUSD', raw: 80, name: 'tusd', iconPath: 'assets/images/tusd_icon.png', decimals: 18);
251 - static const wbtc = CryptoCurrency(title: 'WBTC', tag: 'ETH', fullName: 'Wrapped Bitcoin', raw: 81, name: 'wbtc', iconPath: 'assets/new-ui/crypto_full_icons/wbtc.svg', decimals: 8);
252 - static const weth = CryptoCurrency(title: 'WETH', tag: 'ETH', fullName: 'Wrapped Ethereum', raw: 82, name: 'weth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18);
253 - static const zrx = CryptoCurrency(title: 'ZRX', tag: 'ETH', fullName: '0x Protocol', raw: 83, name: 'zrx', iconPath: 'assets/images/zrx_icon.png', decimals: 18);
254 - static const dydx = CryptoCurrency(title: 'DYDX', tag: 'ETH', fullName: 'dYdX', raw: 84, name: 'dydx', iconPath: 'assets/images/dydx_icon.png', decimals: 18);
255 - static const steth = CryptoCurrency(title: 'STETH', tag: 'ETH', fullName: 'Lido Staked Ethereum', raw: 85, name: 'steth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18);
256 - static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29,flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
257 - static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POL', fullName: 'Tether (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
258 - static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POL', fullName: 'USDC (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6);
259 - static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8);
260 - static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8);
261 - static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'Tether', raw: 91, name: 'usdtsol', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
262 - static const usdcTrc20 = CryptoCurrency(title: 'USDC', tag: 'TRX', fullName: 'USDC Coin', raw: 92, name: 'usdctrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
263 - static const tbtc = CryptoCurrency(title: 'tBTC', fullName: 'Testnet Bitcoin', raw: 93, name: 'tbtc', iconPath: 'assets/images/tbtc.png', decimals: 8);
264 - static const wow = CryptoCurrency(title: 'WOW', fullName: 'Wownero', raw: 94, name: 'wow', iconPath: 'assets/images/crypto/wownero.svg', decimals: 11);
265 - static const ton = CryptoCurrency(title: 'TON', fullName: 'Toncoin', raw: 95, name: 'ton', iconPath: 'assets/new-ui/crypto_full_icons/ton.svg', decimals: 8);
266 - static const zano = CryptoCurrency(title: 'ZANO', tag: 'ZANO', fullName: 'Zano', raw: 96, name: 'zano', iconPath: 'assets/new-ui/crypto_full_icons/zano.svg', decimals: 12, flatIconPath: "assets/new-ui/balance_card_icons/zano.svg", chainIconPath: "assets/new-ui/chain_badges/zano.svg");
267 - static const flip = CryptoCurrency(title: 'FLIP', tag: 'ETH', fullName: 'Chainflip', raw: 97, name: 'flip', iconPath: 'assets/images/flip_icon.png', decimals: 18);
268 - static const deuro = CryptoCurrency(title: 'DEURO', tag: 'ETH', fullName: 'Decentralized Euro', raw: 98, name: 'deuro', iconPath: 'assets/images/deuro_icon.png',decimals: 18, groups: const {CurrencyGroups.stablecoin});
269 - static const usdtbsc = CryptoCurrency(title: 'USDT', tag: 'BSC', fullName: 'USDT Binance coin', raw: 99, name: 'usdtbsc', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 18, groups: const {CurrencyGroups.stablecoin});
270 - static const ndeps = CryptoCurrency(title: 'NDEPS', tag: 'ETH', fullName: 'Native Decentralized Euro Protocol Share', raw: 100, name: 'ndeps', iconPath: 'assets/images/ndeps_icon.png', decimals: 18);
271 - static const deps = CryptoCurrency(title: 'DEPS', tag: 'ETH', fullName: 'Decentralized Euro Protocol Share', raw: 101, name: 'deps', iconPath: 'assets/images/deps_icon.png', decimals: 18);
272 - static const kbtc = CryptoCurrency(title: 'KBTC', tag: 'ETH', fullName: 'Kraken Wrapped Bitcoin', raw: 102, name: 'kbtc', iconPath: 'assets/images/kbtc_icon.png', decimals: 8);
273 - static const cbbtc = CryptoCurrency(title: 'CBBTC', tag: 'ETH', fullName: 'Coinbase Wrapped BTC', raw: 103, name: 'cbbtc', iconPath: 'assets/images/cbbtc_icon.png', decimals: 8);
274 - static const baseEth = CryptoCurrency(title: 'ETH', tag: 'BASE', fullName: 'Ethereum', raw: 104, name: 'baseth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/base.svg", chainIconPath: "assets/new-ui/chain_badges/base.svg");
275 - static const usde = CryptoCurrency(title: 'USDE', tag: 'BASE', fullName: 'Ethena USDE', raw: 105, name: 'usde', iconPath: 'assets/new-ui/crypto_full_icons/usde.svg', decimals: 18);
276 - static const arbEth = CryptoCurrency(title: 'ETH', tag: 'ARB', fullName: 'Ethereum', raw: 106, name: 'arbeth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg", chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
277 - static const zec = CryptoCurrency(title: 'ZEC', fullName: 'Zcash', raw: 107, name: 'zec', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8,flatIconPath: "assets/new-ui/balance_card_icons/zcash.svg");
278 - static const usdcArb = CryptoCurrency(title: 'USDC', tag: 'ARB', fullName: 'USDC Coin', raw: 108, name: 'usdcarb', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
279 - static const usdtArb = CryptoCurrency(title: 'USDT', tag: 'ARB', fullName: 'USDT Tether', raw: 109, name: 'usdtarb', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
280 - static const ltcmweb = CryptoCurrency(title: 'LTC', fullName: 'Litecoin MWeb', raw: 110, name: 'ltcmweb', iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg', decimals: 8);
281 -
282 - static final Map<int, CryptoCurrency> _rawCurrencyMap =
283 - [...all, ...havenCurrencies, ...zcashCurrencies].fold<Map<int, CryptoCurrency>>(<int, CryptoCurrency>{}, (acc, item) {
284 - acc.addAll({item.raw: item});
285 - return acc;
286 - });
287 -
288 - static final Map<String, CryptoCurrency> _nameCurrencyMap =
289 - [...all, ...havenCurrencies, ...zcashCurrencies].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
290 - acc.addAll({item.name: item});
291 - return acc;
292 - });
293 -
294 - static final Map<String, CryptoCurrency> _fullNameCurrencyMap =
295 - [...all, ...havenCurrencies, ...zcashCurrencies].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
296 - if(item.fullName != null){
297 - acc.addAll({item.fullName!.toLowerCase(): item});
298 - }
299 - return acc;
300 - });
308 + static const xaud =
309 + CryptoCurrency(title: 'XAUD', tag: 'XHV', raw: 19, name: 'xaud', decimals: 12);
310 + static const xbtc =
311 + CryptoCurrency(title: 'XBTC', tag: 'XHV', raw: 20, name: 'xbtc', decimals: 12);
312 + static const xcad =
313 + CryptoCurrency(title: 'XCAD', tag: 'XHV', raw: 21, name: 'xcad', decimals: 12);
314 + static const xchf =
315 + CryptoCurrency(title: 'XCHF', tag: 'XHV', raw: 22, name: 'xchf', decimals: 12);
316 + static const xcny =
317 + CryptoCurrency(title: 'XCNY', tag: 'XHV', raw: 23, name: 'xcny', decimals: 12);
318 + static const xeur =
319 + CryptoCurrency(title: 'XEUR', tag: 'XHV', raw: 24, name: 'xeur', decimals: 12);
320 + static const xgbp =
321 + CryptoCurrency(title: 'XGBP', tag: 'XHV', raw: 25, name: 'xgbp', decimals: 12);
322 + static const xjpy =
323 + CryptoCurrency(title: 'XJPY', tag: 'XHV', raw: 26, name: 'xjpy', decimals: 12);
324 + static const xnok =
325 + CryptoCurrency(title: 'XNOK', tag: 'XHV', raw: 27, name: 'xnok', decimals: 12);
326 + static const xnzd =
327 + CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28, name: 'xnzd', decimals: 12);
328 + static const xusd =
329 + CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29, name: 'xusd', decimals: 12);
330 +
331 + static const ape = CryptoCurrency(
332 + title: 'APE',
333 + tag: 'ETH',
334 + fullName: 'ApeCoin',
335 + raw: 30,
336 + name: 'ape',
337 + iconPath: 'assets/images/ape_icon.png',
338 + decimals: 18);
339 + static const avaxc = CryptoCurrency(
340 + title: 'AVAX',
341 + tag: 'AVAXC',
342 + fullName: 'Avalanche',
343 + raw: 31,
344 + name: 'avaxc',
345 + iconPath: 'assets/new-ui/crypto_full_icons/avax.svg',
346 + decimals: 9);
347 + static const btt = CryptoCurrency(
348 + title: 'BTT',
349 + tag: 'ETH',
350 + fullName: 'BitTorrent',
351 + raw: 32,
352 + name: 'btt',
353 + iconPath: 'assets/images/btt_icon.png',
354 + decimals: 18);
355 + static const bttc = CryptoCurrency(
356 + title: 'BTTC',
357 + tag: 'TRX',
358 + fullName: 'BitTorrent-NEW',
359 + raw: 33,
360 + name: 'bttc',
361 + iconPath: 'assets/images/btt_icon.png',
362 + decimals: 18);
363 + static const doge = CryptoCurrency(
364 + title: 'DOGE',
365 + fullName: 'Dogecoin',
366 + raw: 34,
367 + name: 'doge',
368 + iconPath: 'assets/new-ui/crypto_full_icons/dogecoin.svg',
369 + decimals: 8,
370 + flatIconPath: "assets/new-ui/balance_card_icons/dogecoin.svg");
371 + static const firo = CryptoCurrency(
372 + title: 'FIRO', raw: 35, name: 'firo', iconPath: 'assets/images/firo_icon.png', decimals: 8);
373 + static const usdttrc20 = CryptoCurrency(
374 + title: 'USDT',
375 + tag: 'TRX',
376 + fullName: 'Tether',
377 + raw: 36,
378 + name: 'usdttrc20',
379 + iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
380 + decimals: 6,
381 + groups: const {CurrencyGroups.stablecoin});
382 + static const hbar = CryptoCurrency(
383 + title: 'HBAR',
384 + fullName: 'Hedera',
385 + raw: 37,
386 + name: 'hbar',
387 + iconPath: 'assets/images/hbar_icon.png',
388 + decimals: 8);
389 + static const sc = CryptoCurrency(
390 + title: 'SC',
391 + fullName: 'Siacoin',
392 + raw: 38,
393 + name: 'sc',
394 + iconPath: 'assets/images/sc_icon.png',
395 + decimals: 16);
396 + static const sol = CryptoCurrency(
397 + title: 'SOL',
398 + fullName: 'Solana',
399 + raw: 39,
400 + name: 'sol',
401 + iconPath: 'assets/new-ui/crypto_full_icons/solana.svg',
402 + decimals: 9,
403 + flatIconPath: "assets/new-ui/balance_card_icons/solana.svg",
404 + chainIconPath: "assets/new-ui/chain_badges/solana.svg");
405 + static const usdc = CryptoCurrency(
406 + title: 'USDC',
407 + tag: 'ETH',
408 + fullName: 'USDC',
409 + raw: 40,
410 + name: 'usdc',
411 + iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
412 + decimals: 6,
413 + groups: const {CurrencyGroups.stablecoin});
414 + static const usdcsol = CryptoCurrency(
415 + title: 'USDC',
416 + tag: 'SOL',
417 + fullName: 'USDC Coin',
418 + raw: 41,
419 + name: 'usdcsol',
420 + iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
421 + decimals: 6,
422 + groups: const {CurrencyGroups.stablecoin});
423 + static const zaddr = CryptoCurrency(
424 + title: 'ZZEC',
425 + tag: 'ZEC',
426 + fullName: 'Shielded Zcash',
427 + raw: 42,
428 + name: 'zaddr',
429 + iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg',
430 + decimals: 8);
431 + static const tzec = CryptoCurrency(
432 + title: 'tZEC',
433 + tag: 'ZEC',
434 + fullName: 'Transparent Zcash',
435 + raw: 43,
436 + name: 'zec',
437 + iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg',
438 + decimals: 8);
439 + static const zen = CryptoCurrency(
440 + title: 'ZEN',
441 + fullName: 'Horizen',
442 + raw: 44,
443 + name: 'zen',
444 + iconPath: 'assets/images/zen_icon.png',
445 + decimals: 8);
446 + static const xvg = CryptoCurrency(
447 + title: 'XVG',
448 + fullName: 'Verge',
449 + raw: 45,
450 + name: 'xvg',
451 + iconPath: 'assets/images/xvg_icon.png',
452 + decimals: 8);
453 +
454 + static const usdcpoly = CryptoCurrency(
455 + title: 'USDC',
456 + tag: 'POL',
457 + fullName: 'USDC',
458 + raw: 46,
459 + name: 'usdcpoly',
460 + iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
461 + decimals: 6,
462 + groups: const {CurrencyGroups.stablecoin});
463 + static const dcr = CryptoCurrency(
464 + title: 'DCR',
465 + fullName: 'Decred',
466 + raw: 47,
467 + name: 'dcr',
468 + iconPath: 'assets/new-ui/crypto_full_icons/decred.svg',
469 + decimals: 8,
470 + flatIconPath: "assets/new-ui/balance_card_icons/decred.svg");
471 + static const kmd = CryptoCurrency(
472 + title: 'KMD',
473 + fullName: 'Komodo',
474 + raw: 48,
475 + name: 'kmd',
476 + iconPath: 'assets/images/kmd_icon.png',
477 + decimals: 8);
478 + static const mana = CryptoCurrency(
479 + title: 'MANA',
480 + tag: 'ETH',
481 + fullName: 'Decentraland',
482 + raw: 49,
483 + name: 'mana',
484 + iconPath: 'assets/images/mana_icon.png',
485 + decimals: 18);
486 + static const maticpoly = CryptoCurrency(
487 + title: 'POL',
488 + tag: 'POL',
489 + fullName: 'Polygon',
490 + raw: 50,
491 + name: 'maticpoly',
492 + iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg',
493 + decimals: 18,
494 + flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg",
495 + chainIconPath: "assets/new-ui/chain_badges/polygon.svg");
496 + static const matic = CryptoCurrency(
497 + title: 'MATIC',
498 + tag: 'ETH',
499 + fullName: 'Polygon',
500 + raw: 51,
501 + name: 'matic',
502 + iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg',
503 + decimals: 18,
504 + flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg");
505 + static const mkr = CryptoCurrency(
506 + title: 'MKR',
507 + tag: 'ETH',
508 + fullName: 'Maker',
509 + raw: 52,
510 + name: 'mkr',
511 + iconPath: 'assets/images/mkr_icon.png',
512 + decimals: 18);
513 + static const near = CryptoCurrency(
514 + title: 'NEAR',
515 + fullName: 'NEAR Protocol',
516 + raw: 53,
517 + name: 'near',
518 + iconPath: 'assets/images/near_icon.png',
519 + decimals: 24);
520 + static const oxt = CryptoCurrency(
521 + title: 'OXT',
522 + tag: 'ETH',
523 + fullName: 'Orchid',
524 + raw: 54,
525 + name: 'oxt',
526 + iconPath: 'assets/images/oxt_icon.png',
527 + decimals: 18);
528 + static const paxg = CryptoCurrency(
529 + title: 'PAXG',
530 + tag: 'ETH',
531 + fullName: 'Pax Gold',
532 + raw: 55,
533 + name: 'paxg',
534 + iconPath: 'assets/new-ui/crypto_full_icons/paxg.svg',
535 + decimals: 18);
536 + static const pivx = CryptoCurrency(
537 + title: 'PIVX', raw: 56, name: 'pivx', iconPath: 'assets/images/pivx_icon.png', decimals: 8);
538 + static const rune = CryptoCurrency(
539 + title: 'RUNE',
540 + fullName: 'Thorchain',
541 + raw: 57,
542 + name: 'rune',
543 + iconPath: 'assets/images/rune_icon.png',
544 + decimals: 18);
545 + static const rvn = CryptoCurrency(
546 + title: 'RVN',
547 + fullName: 'Ravencoin',
548 + raw: 58,
549 + name: 'rvn',
550 + iconPath: 'assets/images/rvn_icon.png',
551 + decimals: 8);
552 + static const scrt = CryptoCurrency(
553 + title: 'SCRT',
554 + fullName: 'Secret Network',
555 + raw: 59,
556 + name: 'scrt',
557 + iconPath: 'assets/images/scrt_icon.png',
558 + decimals: 6);
559 + static const uni = CryptoCurrency(
560 + title: 'UNI',
561 + tag: 'ETH',
562 + fullName: 'Uniswap',
563 + raw: 60,
564 + name: 'uni',
565 + iconPath: 'assets/images/uni_icon.png',
566 + decimals: 18);
567 + static const stx = CryptoCurrency(
568 + title: 'STX',
569 + fullName: 'Stacks',
570 + raw: 61,
571 + name: 'stx',
572 + iconPath: 'assets/images/stx_icon.png',
573 + decimals: 8);
574 + static const btcln = CryptoCurrency(
575 + title: 'BTC',
576 + tag: 'LN',
577 + fullName: 'Bitcoin Lightning Network',
578 + raw: 62,
579 + name: 'btcln',
580 + iconPath: 'assets/new-ui/crypto_full_icons/lightning.svg',
581 + chainIconPath: "assets/new-ui/chain_badges/lightning.svg",
582 + decimals: 8);
583 + static const shib = CryptoCurrency(
584 + title: 'SHIB',
585 + tag: 'ETH',
586 + fullName: 'Shiba Inu',
587 + raw: 63,
588 + name: 'shib',
589 + iconPath: 'assets/images/shib_icon.png',
590 + decimals: 18);
591 + static const aave = CryptoCurrency(
592 + title: 'AAVE',
593 + tag: 'ETH',
594 + fullName: 'Aave',
595 + raw: 64,
596 + name: 'aave',
597 + iconPath: 'assets/images/aave_icon.png',
598 + decimals: 18);
599 + static const arb = CryptoCurrency(
600 + title: 'ARB',
601 + fullName: 'Arbitrum',
602 + raw: 65,
603 + name: 'arb',
604 + iconPath: 'assets/new-ui/crypto_full_icons/arbitrum.svg',
605 + decimals: 18,
606 + flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg",
607 + chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
608 + static const bat = CryptoCurrency(
609 + title: 'BAT',
610 + tag: 'ETH',
611 + fullName: 'Basic Attention Token',
612 + raw: 66,
613 + name: 'bat',
614 + iconPath: 'assets/images/bat_icon.png',
615 + decimals: 18);
616 + static const comp = CryptoCurrency(
617 + title: 'COMP',
618 + tag: 'ETH',
619 + fullName: 'Compound',
620 + raw: 67,
621 + name: 'comp',
622 + iconPath: 'assets/images/comp_icon.png',
623 + decimals: 18);
624 + static const cro = CryptoCurrency(
625 + title: 'CRO',
626 + tag: 'ETH',
627 + fullName: 'Crypto.com Cronos',
628 + raw: 68,
629 + name: 'cro',
630 + iconPath: 'assets/images/cro_icon.png',
631 + decimals: 8);
632 + static const ens = CryptoCurrency(
633 + title: 'ENS',
634 + tag: 'ETH',
635 + fullName: 'Ethereum Name Service',
636 + raw: 69,
637 + name: 'ens',
638 + iconPath: 'assets/images/ens_icon.png',
639 + decimals: 18);
640 + static const ftm = CryptoCurrency(
641 + title: 'FTM',
642 + tag: 'ETH',
643 + fullName: 'Fantom',
644 + raw: 70,
645 + name: 'ftm',
646 + iconPath: 'assets/images/ftm_icon.png',
647 + decimals: 18);
648 + static const frax = CryptoCurrency(
649 + title: 'FRAX',
650 + tag: 'ETH',
651 + fullName: 'Frax',
652 + raw: 71,
653 + name: 'frax',
654 + iconPath: 'assets/images/frax_icon.png',
655 + decimals: 18);
656 + static const gusd = CryptoCurrency(
657 + title: 'GUSD',
658 + tag: 'ETH',
659 + fullName: 'Gemini USD',
660 + raw: 72,
661 + name: 'gusd',
662 + iconPath: 'assets/images/gusd_icon.png',
663 + decimals: 2);
664 + static const gtc = CryptoCurrency(
665 + title: 'GTC',
666 + tag: 'ETH',
667 + fullName: 'Gitcoin',
668 + raw: 73,
669 + name: 'gtc',
670 + iconPath: 'assets/images/gtc_icon.png',
671 + decimals: 18);
672 + static const grt = CryptoCurrency(
673 + title: 'GRT',
674 + tag: 'ETH',
675 + fullName: 'The Graph',
676 + raw: 74,
677 + name: 'grt',
678 + iconPath: 'assets/images/grt_icon.png',
679 + decimals: 18);
680 + static const ldo = CryptoCurrency(
681 + title: 'LDO',
682 + tag: 'ETH',
683 + fullName: 'Lido DAO',
684 + raw: 75,
685 + name: 'ldo',
686 + iconPath: 'assets/images/ldo_icon.png',
687 + decimals: 18);
688 + static const nexo = CryptoCurrency(
689 + title: 'NEXO',
690 + tag: 'ETH',
691 + fullName: 'Nexo',
692 + raw: 76,
693 + name: 'nexo',
694 + iconPath: 'assets/images/nexo_icon.png',
695 + decimals: 18);
696 + static const cake = CryptoCurrency(
697 + title: 'CAKE',
698 + tag: 'BSC',
699 + fullName: 'PancakeSwap',
700 + raw: 77,
701 + name: 'cake',
702 + iconPath: 'assets/images/cake_icon.png',
703 + decimals: 18);
704 + static const pepe = CryptoCurrency(
705 + title: 'PEPE',
706 + tag: 'ETH',
707 + fullName: 'Pepe',
708 + raw: 78,
709 + name: 'pepe',
710 + iconPath: 'assets/images/pepe_icon.png',
711 + decimals: 18);
712 + static const storj = CryptoCurrency(
713 + title: 'STORJ',
714 + tag: 'ETH',
715 + fullName: 'Storj',
716 + raw: 79,
717 + name: 'storj',
718 + iconPath: 'assets/images/storj_icon.png',
719 + decimals: 8);
720 + static const tusd = CryptoCurrency(
721 + title: 'TUSD',
722 + tag: 'ETH',
723 + fullName: 'TrueUSD',
724 + raw: 80,
725 + name: 'tusd',
726 + iconPath: 'assets/images/tusd_icon.png',
727 + decimals: 18);
728 + static const wbtc = CryptoCurrency(
729 + title: 'WBTC',
730 + tag: 'ETH',
731 + fullName: 'Wrapped Bitcoin',
732 + raw: 81,
733 + name: 'wbtc',
734 + iconPath: 'assets/new-ui/crypto_full_icons/wbtc.svg',
735 + decimals: 8);
736 + static const weth = CryptoCurrency(
737 + title: 'WETH',
738 + tag: 'ETH',
739 + fullName: 'Wrapped Ethereum',
740 + raw: 82,
741 + name: 'weth',
742 + iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
743 + decimals: 18);
744 + static const zrx = CryptoCurrency(
745 + title: 'ZRX',
746 + tag: 'ETH',
747 + fullName: '0x Protocol',
748 + raw: 83,
749 + name: 'zrx',
750 + iconPath: 'assets/images/zrx_icon.png',
751 + decimals: 18);
752 + static const dydx = CryptoCurrency(
753 + title: 'DYDX',
754 + tag: 'ETH',
755 + fullName: 'dYdX',
756 + raw: 84,
757 + name: 'dydx',
758 + iconPath: 'assets/images/dydx_icon.png',
759 + decimals: 18);
760 + static const steth = CryptoCurrency(
761 + title: 'STETH',
762 + tag: 'ETH',
763 + fullName: 'Lido Staked Ethereum',
764 + raw: 85,
765 + name: 'steth',
766 + iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
767 + decimals: 18);
768 + static const banano = CryptoCurrency(
769 + title: 'BAN',
770 + fullName: 'Banano',
771 + raw: 86,
772 + name: 'banano',
773 + iconPath: 'assets/images/nano_icon.png',
774 + decimals: 29,
775 + flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
776 + static const usdtPoly = CryptoCurrency(
777 + title: 'USDT',
778 + tag: 'POL',
779 + fullName: 'Tether (PoS)',
780 + raw: 87,
781 + name: 'usdtpoly',
782 + iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
783 + decimals: 6,
784 + groups: const {CurrencyGroups.stablecoin});
785 + static const usdcEPoly = CryptoCurrency(
786 + title: 'USDC.E',
787 + tag: 'POL',
788 + fullName: 'USDC (PoS)',
789 + raw: 88,
790 + name: 'usdcepoly',
791 + iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
792 + decimals: 6);
793 + static const kaspa = CryptoCurrency(
794 + title: 'KAS',
795 + fullName: 'Kaspa',
796 + raw: 89,
797 + name: 'kas',
798 + iconPath: 'assets/images/kaspa_icon.png',
799 + decimals: 8);
800 + static const digibyte = CryptoCurrency(
801 + title: 'DGB',
802 + fullName: 'DigiByte',
803 + raw: 90,
804 + name: 'dgb',
805 + iconPath: 'assets/images/digibyte.png',
806 + decimals: 8);
807 + static const usdtSol = CryptoCurrency(
808 + title: 'USDT',
809 + tag: 'SOL',
810 + fullName: 'Tether',
811 + raw: 91,
812 + name: 'usdtsol',
813 + iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
814 + decimals: 6,
815 + groups: const {CurrencyGroups.stablecoin});
816 + static const usdcTrc20 = CryptoCurrency(
817 + title: 'USDC',
818 + tag: 'TRX',
819 + fullName: 'USDC Coin',
820 + raw: 92,
821 + name: 'usdctrc20',
822 + iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
823 + decimals: 6,
824 + groups: const {CurrencyGroups.stablecoin});
825 + static const tbtc = CryptoCurrency(
826 + title: 'tBTC',
827 + fullName: 'Testnet Bitcoin',
828 + raw: 93,
829 + name: 'tbtc',
830 + iconPath: 'assets/images/tbtc.png',
831 + decimals: 8);
832 + static const wow = CryptoCurrency(
833 + title: 'WOW',
834 + fullName: 'Wownero',
835 + raw: 94,
836 + name: 'wow',
837 + iconPath: 'assets/images/crypto/wownero.svg',
838 + decimals: 11);
839 + static const ton = CryptoCurrency(
840 + title: 'TON',
841 + fullName: 'Toncoin',
842 + raw: 95,
843 + name: 'ton',
844 + iconPath: 'assets/new-ui/crypto_full_icons/ton.svg',
845 + decimals: 8);
846 + static const zano = CryptoCurrency(
847 + title: 'ZANO',
848 + tag: 'ZANO',
849 + fullName: 'Zano',
850 + raw: 96,
851 + name: 'zano',
852 + iconPath: 'assets/new-ui/crypto_full_icons/zano.svg',
853 + decimals: 12,
854 + flatIconPath: "assets/new-ui/balance_card_icons/zano.svg",
855 + chainIconPath: "assets/new-ui/chain_badges/zano.svg");
856 + static const flip = CryptoCurrency(
857 + title: 'FLIP',
858 + tag: 'ETH',
859 + fullName: 'Chainflip',
860 + raw: 97,
861 + name: 'flip',
862 + iconPath: 'assets/images/flip_icon.png',
863 + decimals: 18);
864 + static const deuro = CryptoCurrency(
865 + title: 'DEURO',
866 + tag: 'ETH',
867 + fullName: 'Decentralized Euro',
868 + raw: 98,
869 + name: 'deuro',
870 + iconPath: 'assets/images/deuro_icon.png',
871 + decimals: 18,
872 + groups: const {CurrencyGroups.stablecoin});
873 + static const usdtbsc = CryptoCurrency(
874 + title: 'USDT',
875 + tag: 'BSC',
876 + fullName: 'USDT Binance coin',
877 + raw: 99,
878 + name: 'usdtbsc',
879 + iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
880 + decimals: 18,
881 + groups: const {CurrencyGroups.stablecoin});
882 + static const ndeps = CryptoCurrency(
883 + title: 'NDEPS',
884 + tag: 'ETH',
885 + fullName: 'Native Decentralized Euro Protocol Share',
886 + raw: 100,
887 + name: 'ndeps',
888 + iconPath: 'assets/images/ndeps_icon.png',
889 + decimals: 18);
890 + static const deps = CryptoCurrency(
891 + title: 'DEPS',
892 + tag: 'ETH',
893 + fullName: 'Decentralized Euro Protocol Share',
894 + raw: 101,
895 + name: 'deps',
896 + iconPath: 'assets/images/deps_icon.png',
897 + decimals: 18);
898 + static const kbtc = CryptoCurrency(
899 + title: 'KBTC',
900 + tag: 'ETH',
901 + fullName: 'Kraken Wrapped Bitcoin',
902 + raw: 102,
903 + name: 'kbtc',
904 + iconPath: 'assets/images/kbtc_icon.png',
905 + decimals: 8);
906 + static const cbbtc = CryptoCurrency(
907 + title: 'CBBTC',
908 + tag: 'ETH',
909 + fullName: 'Coinbase Wrapped BTC',
910 + raw: 103,
911 + name: 'cbbtc',
912 + iconPath: 'assets/images/cbbtc_icon.png',
913 + decimals: 8);
914 + static const baseEth = CryptoCurrency(
915 + title: 'ETH',
916 + tag: 'BASE',
917 + fullName: 'Ethereum',
918 + raw: 104,
919 + name: 'baseth',
920 + iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
921 + decimals: 18,
922 + flatIconPath: "assets/new-ui/balance_card_icons/base.svg",
923 + chainIconPath: "assets/new-ui/chain_badges/base.svg");
924 + static const usde = CryptoCurrency(
925 + title: 'USDE',
926 + tag: 'BASE',
927 + fullName: 'Ethena USDE',
928 + raw: 105,
929 + name: 'usde',
930 + iconPath: 'assets/new-ui/crypto_full_icons/usde.svg',
931 + decimals: 18);
932 + static const arbEth = CryptoCurrency(
933 + title: 'ETH',
934 + tag: 'ARB',
935 + fullName: 'Ethereum',
936 + raw: 106,
937 + name: 'arbeth',
938 + iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg',
939 + decimals: 18,
940 + flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg",
941 + chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
942 + static const zec = CryptoCurrency(
943 + title: 'ZEC',
944 + fullName: 'Zcash',
945 + raw: 107,
946 + name: 'zec',
947 + iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg',
948 + decimals: 8,
949 + flatIconPath: "assets/new-ui/balance_card_icons/zcash.svg");
950 + static const usdcArb = CryptoCurrency(
951 + title: 'USDC',
952 + tag: 'ARB',
953 + fullName: 'USDC Coin',
954 + raw: 108,
955 + name: 'usdcarb',
956 + iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg',
957 + decimals: 6,
958 + groups: const {CurrencyGroups.stablecoin});
959 + static const usdtArb = CryptoCurrency(
960 + title: 'USDT',
961 + tag: 'ARB',
962 + fullName: 'USDT Tether',
963 + raw: 109,
964 + name: 'usdtarb',
965 + iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg',
966 + decimals: 6,
967 + groups: const {CurrencyGroups.stablecoin});
968 + static const ltcmweb = CryptoCurrency(
969 + title: 'LTC',
970 + fullName: 'Litecoin MWeb',
971 + raw: 110,
972 + name: 'ltcmweb',
973 + iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg',
974 + decimals: 8);
975 +
976 + static final Map<int, CryptoCurrency> _rawCurrencyMap = [
977 + ...all,
978 + ...havenCurrencies,
979 + ...zcashCurrencies
980 + ].fold<Map<int, CryptoCurrency>>(<int, CryptoCurrency>{}, (acc, item) {
981 + acc.addAll({item.raw: item});
982 + return acc;
983 + });
984 +
985 + static final Map<String, CryptoCurrency> _nameCurrencyMap = [
986 + ...all,
987 + ...havenCurrencies,
988 + ...zcashCurrencies
989 + ].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
990 + acc.addAll({item.name: item});
991 + return acc;
992 + });
993 +
994 + static final Map<String, CryptoCurrency> _fullNameCurrencyMap = [
995 + ...all,
996 + ...havenCurrencies,
997 + ...zcashCurrencies
998 + ].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
999 + if (item.fullName != null) {
1000 + acc.addAll({item.fullName!.toLowerCase(): item});
1001 + }
1002 + return acc;
1003 + });
1004
1005 // Scheme to currency mapping for URI scheme
1006 static final Map<String, CryptoCurrency> _schemeCurrencyMap = {
@@ -324,7 +1027,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
1027 static CryptoCurrency deserialize({required int raw}) {
1028 if (CryptoCurrency._rawCurrencyMap[raw] == null) {
1029 final s = 'Unexpected token: $raw for CryptoCurrency deserialize';
327 - throw ArgumentError.value(raw, 'raw', s);
1030 + throw ArgumentError.value(raw, 'raw', s);
1031 }
1032 return CryptoCurrency._rawCurrencyMap[raw]!;
1033 }
@@ -334,10 +1037,8 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
1037 return _rawCurrencyMap[raw];
1038 }
1039
337 -
1040 // TODO: refactor this
1041 static CryptoCurrency fromString(String name, {CryptoCurrency? walletCurrency}) {
340 -
1042 final schemeMatch = _schemeCurrencyMap[name.toLowerCase()];
1043 if (schemeMatch != null) return schemeMatch;
1044
@@ -357,7 +1058,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
1058
1059 if (CryptoCurrency._nameCurrencyMap[name.toLowerCase()] == null) {
1060 final s = 'Unexpected token: $name for CryptoCurrency fromString';
360 - throw ArgumentError.value(name, 'name', s);
1061 + throw ArgumentError.value(name, 'name', s);
1062 }
1063
1064 return CryptoCurrency._nameCurrencyMap[name.toLowerCase()]!;
@@ -366,36 +1067,34 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
1067 static CryptoCurrency fromFullName(String name) {
1068 if (CryptoCurrency._fullNameCurrencyMap[name.split("(").first.trim().toLowerCase()] == null) {
1069 final s = 'Unexpected token: $name for CryptoCurrency fromFullName';
369 - throw ArgumentError.value(name, 'Fullname', s);
1070 + throw ArgumentError.value(name, 'Fullname', s);
1071 }
1072 return CryptoCurrency._fullNameCurrencyMap[name.split("(").first.trim().toLowerCase()]!;
1073 }
1074
1075 static CryptoCurrency? safeParseCurrencyFromString(
375 - String? raw, {
376 - String? tag,
377 - CryptoCurrency? walletCurrency,
378 - }) {
1076 + String? raw, {
1077 + String? tag,
1078 + CryptoCurrency? walletCurrency,
1079 + }) {
1080 if (raw == null || raw.isEmpty) return null;
1081
381 - if(tag?.toLowerCase() == "lightning") tag = "LN";
1082 + if (tag?.toLowerCase() == "lightning") tag = "LN";
1083
1084 if (tag != null && tag.isNotEmpty) {
1085 final match = CryptoCurrency.all.firstWhereOrNull(
385 - (e) =>
386 - e.title.toUpperCase() == raw.toUpperCase() &&
1086 + (e) =>
1087 + e.title.toUpperCase() == raw.toUpperCase() &&
1088 e.tag?.toUpperCase() == tag?.toUpperCase(),
1089 );
1090 if (match != null) return match;
1091 return null;
1092 }
1093
393 -
1094 // Try for native currency with same title and tag
1095 if (tag == null || tag.isEmpty) {
1096 final match = CryptoCurrency.all.firstWhereOrNull(
397 - (e) =>
398 - e.title.toUpperCase() == raw.toUpperCase() && (e.tag == raw.toUpperCase()),
1097 + (e) => e.title.toUpperCase() == raw.toUpperCase() && (e.tag == raw.toUpperCase()),
1098 );
1099
1100 if (match != null) return match;
cw_core/lib/currency_for_wallet_type.dart
+2 -1
@@ -90,7 +90,8 @@ int? getChainIdByCryptoCurrency(CryptoCurrency currency) {
90 }
91 }
92
93 -CryptoCurrency getCryptoCurrencyForWalletListItem(WalletType type, {bool isTestnet = false, int? chainId}) {
93 +CryptoCurrency getCryptoCurrencyForWalletListItem(WalletType type,
94 + {bool isTestnet = false, int? chainId}) {
95 if (type == WalletType.arbitrum) {
96 return CryptoCurrency.arb;
97 }
cw_core/lib/db/sqlite_debug.dart
+1 -1
@@ -100,7 +100,7 @@ class _SqliteErrorHandlerState extends State<SqliteErrorHandler> {
100 final dbFile = File("${(await getAppDir()).path}/cake.db");
101 final jsonText = JsonEncoder.withIndent(" ").convert(await dumpCustomDb(dbFile.path));
102 setState(() {
103 - log = jsonText;
103 + log = jsonText;
104 });
105 } catch (e, s) {
106 setState(() {
cw_core/lib/encryption_file_utils.dart
+27 -28
@@ -3,40 +3,39 @@ import 'dart:typed_data';
3 import 'package:cw_core/utils/file.dart' as file;
4 import 'package:cake_backup/backup.dart' as cwb;
5
6 -EncryptionFileUtils encryptionFileUtilsFor(bool direct)
7 - => direct
8 - ? XChaCha20EncryptionFileUtils()
9 - : Salsa20EncryhptionFileUtils();
6 +EncryptionFileUtils encryptionFileUtilsFor(bool direct) =>
7 + direct ? XChaCha20EncryptionFileUtils() : Salsa20EncryhptionFileUtils();
8
9 abstract class EncryptionFileUtils {
12 - Future<void> write({required String path, required String password, required String data});
13 - Future<String> read({required String path, required String password});
10 + Future<void> write({required String path, required String password, required String data});
11 + Future<String> read({required String path, required String password});
12 }
13
14 class Salsa20EncryhptionFileUtils extends EncryptionFileUtils {
17 - // Requires legacy complex key + iv as password
18 - @override
19 - Future<void> write({required String path, required String password, required String data}) async
20 - => await file.write(path: path, password: password, data: data);
15 + // Requires legacy complex key + iv as password
16 + @override
17 + Future<void> write(
18 + {required String path, required String password, required String data}) async =>
19 + await file.write(path: path, password: password, data: data);
20
22 - // Requires legacy complex key + iv as password
23 - @override
24 - Future<String> read({required String path, required String password}) async
25 - => await file.read(path: path, password: password);
21 + // Requires legacy complex key + iv as password
22 + @override
23 + Future<String> read({required String path, required String password}) async =>
24 + await file.read(path: path, password: password);
25 }
26
27 class XChaCha20EncryptionFileUtils extends EncryptionFileUtils {
29 - @override
30 - Future<void> write({required String path, required String password, required String data}) async {
31 - final encrypted = await cwb.encrypt(password, Uint8List.fromList(data.codeUnits));
32 - await File(path).writeAsBytes(encrypted);
33 - }
34 -
35 - @override
36 - Future<String> read({required String path, required String password}) async {
37 - final file = File(path);
38 - final encrypted = await file.readAsBytes();
39 - final bytes = await cwb.decrypt(password, encrypted);
40 - return String.fromCharCodes(bytes);
41 - }
42 -}
\ No newline at end of file
28 + @override
29 + Future<void> write({required String path, required String password, required String data}) async {
30 + final encrypted = await cwb.encrypt(password, Uint8List.fromList(data.codeUnits));
31 + await File(path).writeAsBytes(encrypted);
32 + }
33 +
34 + @override
35 + Future<String> read({required String path, required String password}) async {
36 + final file = File(path);
37 + final encrypted = await file.readAsBytes();
38 + final bytes = await cwb.decrypt(password, encrypted);
39 + return String.fromCharCodes(bytes);
40 + }
41 +}
cw_core/lib/erc20_token.part.dart
+2 -4
@@ -1,4 +1,4 @@
1 - // GENERATED CODE - DO NOT MODIFY BY HAND
1 +// GENERATED CODE - DO NOT MODIFY BY HAND
2
3 part of 'erc20_token.dart';
4
@@ -55,7 +55,5 @@ class Erc20TokenAdapter extends TypeAdapter<Erc20Token> {
55 @override
56 bool operator ==(Object other) =>
57 identical(this, other) ||
58 - other is Erc20TokenAdapter &&
59 - runtimeType == other.runtimeType &&
60 - typeId == other.typeId;
58 + other is Erc20TokenAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
59 }
cw_core/lib/exceptions.dart
+1 -1
@@ -69,4 +69,4 @@ class WalletDeprecationException implements Exception {
69 String toString() => "Wallet type no longer supported";
70
71 WalletDeprecationException({required this.seed, required this.curr});
72 -}
\ No newline at end of file
72 +}
cw_core/lib/format_amount.dart
+3 -3
@@ -1,8 +1,8 @@
1 String formatAmount(String amount) {
2 - if ((!amount.contains('.'))&&(!amount.contains(','))) {
2 + if ((!amount.contains('.')) && (!amount.contains(','))) {
3 return amount + '.00';
4 - } else if ((amount.endsWith('.'))||(amount.endsWith(','))) {
4 + } else if ((amount.endsWith('.')) || (amount.endsWith(','))) {
5 return amount + '00';
6 }
7 return amount;
8 -}
\ No newline at end of file
8 +}
cw_core/lib/format_fixed.dart
+3 -6
@@ -1,7 +1,6 @@
1 import 'package:cw_core/parse_fixed.dart';
2
3 -String formatFixed(BigInt value, int? decimals,
4 - {int? fractionalDigits, bool trimZeros = true}) {
3 +String formatFixed(BigInt value, int? decimals, {int? fractionalDigits, bool trimZeros = true}) {
4 decimals ??= 0;
5 fractionalDigits ??= decimals;
6
@@ -10,10 +9,8 @@ String formatFixed(BigInt value, int? decimals,
9 var negative = value.isNegative;
10 if (negative) value = value * BigInt.from(-1);
11
13 - var fraction = value
14 - .modPow(BigInt.one, BigInt.parse(multiplier))
15 - .toString()
16 - .padLeft(decimals, "0");
12 + var fraction =
13 + value.modPow(BigInt.one, BigInt.parse(multiplier)).toString().padLeft(decimals, "0");
14
15 if (fractionalDigits < 0) fractionalDigits = 0;
16 if (fractionalDigits > decimals) fractionalDigits = decimals;
cw_core/lib/get_height_by_date.dart
+2 -1
@@ -6,7 +6,8 @@ import 'dart:convert';
6
7 // FIXME: Hardcoded values; Works only for monero
8
9 -int getMoneroHeigthByDate({required DateTime date}) => MoneroHeight.getBlockHeightByTime(date..subtract(Duration(days: 1)));
9 +int getMoneroHeigthByDate({required DateTime date}) =>
10 + MoneroHeight.getBlockHeightByTime(date..subtract(Duration(days: 1)));
11
12 const havenDates = {
13 "2023-05": 1352995,
cw_core/lib/get_height_by_date_xmr.dart
-1
@@ -1,4 +1,3 @@
1 -
1 class MoneroHeight {
2 // for i in $(seq 1 364); do echo "_Checkpoint(_t($(curl https://xmrchain.net/block/${i}0000 | grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}' | xargs | sed 's/ /\n/g' | head -5 | tail -1 | tr '()' ' ' | sed 's/ /\n/g' | head -2 | xargs)), ${i}0000),"; done > points.txt
3 static final List<_Checkpoint> _points = [
cw_core/lib/hive_type_ids.dart
+24 -24
@@ -1,24 +1,24 @@
1 -const CONTACT_TYPE_ID = 0;
2 -const NODE_TYPE_ID = 1;
3 -const TRANSACTION_TYPE_ID = 2;
4 -const TRADE_TYPE_ID = 3;
5 -const WALLET_INFO_TYPE_ID = 4;
6 -const WALLET_TYPE_TYPE_ID = 5;
7 -const TEMPLATE_TYPE_ID = 6;
8 -const EXCHANGE_TEMPLATE_TYPE_ID = 7;
9 -const ORDER_TYPE_ID = 8;
10 -const UNSPENT_COINS_INFO_TYPE_ID = 9;
11 -const ANONPAY_INVOICE_INFO_TYPE_ID = 10;
12 -const ADDRESS_INFO_TYPE_ID = 11;
13 -const ERC20_TOKEN_TYPE_ID = 12;
14 -const NANO_ACCOUNT_TYPE_ID = 13;
15 -const POW_NODE_TYPE_ID = 14;
16 -const DERIVATION_TYPE_TYPE_ID = 15;
17 -const SPL_TOKEN_TYPE_ID = 16;
18 -const DERIVATION_INFO_TYPE_ID = 17;
19 -const TRON_TOKEN_TYPE_ID = 18;
20 -const HARDWARE_WALLET_TYPE_TYPE_ID = 19;
21 -const MWEB_UTXO_TYPE_ID = 20;
22 -const HAVEN_SEED_STORE_TYPE_ID = 21;
23 -const ZANO_ASSET_TYPE_ID = 22;
24 -const PAYJOIN_SESSION_TYPE_ID = 23;
\ No newline at end of file
1 +const CONTACT_TYPE_ID = 0;
2 +const NODE_TYPE_ID = 1;
3 +const TRANSACTION_TYPE_ID = 2;
4 +const TRADE_TYPE_ID = 3;
5 +const WALLET_INFO_TYPE_ID = 4;
6 +const WALLET_TYPE_TYPE_ID = 5;
7 +const TEMPLATE_TYPE_ID = 6;
8 +const EXCHANGE_TEMPLATE_TYPE_ID = 7;
9 +const ORDER_TYPE_ID = 8;
10 +const UNSPENT_COINS_INFO_TYPE_ID = 9;
11 +const ANONPAY_INVOICE_INFO_TYPE_ID = 10;
12 +const ADDRESS_INFO_TYPE_ID = 11;
13 +const ERC20_TOKEN_TYPE_ID = 12;
14 +const NANO_ACCOUNT_TYPE_ID = 13;
15 +const POW_NODE_TYPE_ID = 14;
16 +const DERIVATION_TYPE_TYPE_ID = 15;
17 +const SPL_TOKEN_TYPE_ID = 16;
18 +const DERIVATION_INFO_TYPE_ID = 17;
19 +const TRON_TOKEN_TYPE_ID = 18;
20 +const HARDWARE_WALLET_TYPE_TYPE_ID = 19;
21 +const MWEB_UTXO_TYPE_ID = 20;
22 +const HAVEN_SEED_STORE_TYPE_ID = 21;
23 +const ZANO_ASSET_TYPE_ID = 22;
24 +const PAYJOIN_SESSION_TYPE_ID = 23;
cw_core/lib/key.dart
+2 -1
@@ -16,7 +16,8 @@ List<String> extractKeys(String key) {
16 return [_key, iv];
17 }
18
19 -Future<String> encode({required encrypt.Key key, required encrypt.IV iv, required String data}) async {
19 +Future<String> encode(
20 + {required encrypt.Key key, required encrypt.IV iv, required String data}) async {
21 final encrypter = encrypt.Encrypter(encrypt.Salsa20(key));
22 final encrypted = encrypter.encrypt(data, iv: iv);
23
cw_core/lib/keyable.dart
+1 -1
@@ -1,3 +1,3 @@
1 mixin Keyable {
2 dynamic keyIndex;
3 -}
\ No newline at end of file
3 +}
cw_core/lib/lnurl.dart
+6 -9
@@ -12,12 +12,11 @@ bool isBolt11ZeroInvoice(String invoice) {
12 try {
13 final request = Bech32Codec().decode(invoice.replaceFirst("lightning:", ""), invoice.length);
14
15 -
16 - final prefix = _BOLT_PREFIXES
17 - .firstWhere((prefix) => request.hrp.startsWith(prefix), orElse: () => "");
15 + final prefix =
16 + _BOLT_PREFIXES.firstWhere((prefix) => request.hrp.startsWith(prefix), orElse: () => "");
17
18 return request.hrp.length == prefix.length;
20 - } catch(e) {
19 + } catch (e) {
20 return false;
21 }
22 }
@@ -27,7 +26,7 @@ int? _getAmountBolt11Msat(String invoice) {
26 final request = Bech32Codec().decode(invoice.replaceFirst("lightning:", ""), invoice.length);
27
28 final prefix = _BOLT_PREFIXES.firstWhere(
30 - (prefix) => request.hrp.startsWith(prefix),
29 + (prefix) => request.hrp.startsWith(prefix),
30 orElse: () => throw FormatException('Invalid BOLT11 invoice: unknown HRP prefix.'),
31 );
32
@@ -86,8 +85,7 @@ class LNURL {
85 final maxSendable = body["maxSendable"] as int?;
86
87 // if minSendable and maxSendable are the same we assume a specific payment request
89 - if (msat != maxSendable)
90 - return null;
88 + if (msat != maxSendable) return null;
89
90 if (msat == null || msat % 1000 != 0) return null;
91 return Money.fromInt(msat ~/ 1000, CryptoCurrency.btcln);
@@ -136,8 +134,7 @@ class LNURL {
134 String _findLnUrl(String input) {
135 final res = RegExp(r',*?((lnurl)([0-9]+[a-z0-9]+))').allMatches(input.toLowerCase());
136
139 - if (res.length != 1)
140 - throw ArgumentError('Not a valid lnurl string');
137 + if (res.length != 1) throw ArgumentError('Not a valid lnurl string');
138 return res.first.group(0)!;
139 }
140
cw_core/lib/monero_wallet_keys.dart
+6 -6
@@ -1,11 +1,11 @@
1 class MoneroWalletKeys {
2 const MoneroWalletKeys(
3 {required this.primaryAddress,
4 - required this.privateSpendKey,
5 - required this.privateViewKey,
6 - required this.publicSpendKey,
7 - required this.publicViewKey,
8 - required this.passphrase});
4 + required this.privateSpendKey,
5 + required this.privateViewKey,
6 + required this.publicSpendKey,
7 + required this.publicViewKey,
8 + required this.passphrase});
9
10 final String primaryAddress;
11 final String publicViewKey;
@@ -13,4 +13,4 @@ class MoneroWalletKeys {
13 final String publicSpendKey;
14 final String privateSpendKey;
15 final String passphrase;
16 -}
\ No newline at end of file
16 +}
cw_core/lib/mweb_utxo.part.dart
+1 -3
@@ -50,7 +50,5 @@ class MwebUtxoAdapter extends TypeAdapter<MwebUtxo> {
50 @override
51 bool operator ==(Object other) =>
52 identical(this, other) ||
53 - other is MwebUtxoAdapter &&
54 - runtimeType == other.runtimeType &&
55 - typeId == other.typeId;
53 + other is MwebUtxoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
54 }
cw_core/lib/nano_account.part.dart
+1 -3
@@ -44,7 +44,5 @@ class NanoAccountAdapter extends TypeAdapter<NanoAccount> {
44 @override
45 bool operator ==(Object other) =>
46 identical(this, other) ||
47 - other is NanoAccountAdapter &&
48 - runtimeType == other.runtimeType &&
49 - typeId == other.typeId;
47 + other is NanoAccountAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
48 }
cw_core/lib/node.dart
+30 -34
@@ -25,11 +25,9 @@ Future<void> validateBuiltinNodes() async {
25 for (final listNode in builtinFromList) {
26 // preserve proxy settings from user
27 try {
28 - final matchedDbNode = builtinFromDb.firstWhere(
29 - (dbNode) => dbNode.uri == listNode.uri
30 - );
28 + final matchedDbNode = builtinFromDb.firstWhere((dbNode) => dbNode.uri == listNode.uri);
29 listNode.socksProxyAddress = matchedDbNode.socksProxyAddress;
32 - } catch(e) {}
30 + } catch (e) {}
31 }
32
33 final dbSet = builtinFromDb.toSet();
@@ -121,7 +119,7 @@ class Node {
119 "label": label,
120 'password': password,
121 "isPow": isPow ? 1 : 0,
124 - 'useSSL': (useSSL??false) ? 1 : 0,
122 + 'useSSL': (useSSL ?? false) ? 1 : 0,
123 "typeRaw": typeRaw,
124 'trusted': trusted ? 1 : 0,
125 'socksProxyAddress': socksProxyAddress,
@@ -165,7 +163,6 @@ class Node {
163 }
164
165 Future<int> save() async {
168 -
166 final json = toMap();
167 if (json[selfIdColumn] == 0) {
168 json[selfIdColumn] = null;
@@ -174,9 +171,9 @@ class Node {
171 return id;
172 }
173
177 -
178 - static Future<List<Node>> selectList(String where, List<dynamic> whereArgs, {String? orderBy}) async {
179 - if(orderBy == null) {
174 + static Future<List<Node>> selectList(String where, List<dynamic> whereArgs,
175 + {String? orderBy}) async {
176 + if (orderBy == null) {
177 orderBy = selfIdColumn;
178 }
179 final list = await db!.query(
@@ -189,7 +186,7 @@ class Node {
186 }
187
188 static Future<Node?> select(String where, List<dynamic> whereArgs, {String? orderBy}) async {
192 - if(orderBy == null) {
189 + if (orderBy == null) {
190 orderBy = selfIdColumn;
191 }
192 final list = await db!.query(
@@ -201,7 +198,6 @@ class Node {
198 return list.isEmpty ? null : Node.fromMap(list.first);
199 }
200
204 -
201 static Future<List<Node>> getAll() async {
202 return selectList("isPow = ?", [0]);
203 }
@@ -219,11 +215,15 @@ class Node {
215 }
216
217 static Future<Node?> getDefaultForWalletType(WalletType type) async {
222 - return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 0, 1])).firstOrNull;
218 + return (await selectList(
219 + "typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 0, 1]))
220 + .firstOrNull;
221 }
222
223 static Future<Node?> getDefaultPowForWalletType(WalletType type) async {
226 - return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 1, 1])).firstOrNull;
224 + return (await selectList(
225 + "typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 1, 1]))
226 + .firstOrNull;
227 }
228
229 static Future<List<Node>> getAllForWalletTypePow(WalletType type) async {
@@ -238,7 +238,6 @@ class Node {
238 return select("${selfIdColumn} = ?", [id]);
239 }
240
241 -
241 int id;
242 late String uriRaw;
243 String? login;
@@ -262,7 +261,6 @@ class Node {
261 static String get tableName => "Node";
262 static String get selfIdColumn => "${tableName}Id";
263
265 -
264 bool get isSSL => useSSL ?? false;
265
266 bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
@@ -333,7 +331,6 @@ class Node {
331 socksProxyAddress.hashCode ^
332 path.hashCode;
333
336 -
334 WalletType get type => deserializeFromInt(typeRaw);
335
336 set type(WalletType type) => typeRaw = serializeToInt(type);
@@ -387,7 +384,6 @@ class Node {
384 body: jsonBody,
385 );
386
390 -
387 final resBody = json.decode(response.body) as Map<String, dynamic>;
388
389 return resBody['result']['height'] != null;
@@ -407,15 +403,13 @@ class Node {
403 final body = {'jsonrpc': '2.0', 'id': '0', 'method': methodName};
404
405 try {
410 -
406 final jsonBody = json.encode(body);
407
408 final response = await ProxyWrapper().post(
414 - clearnetUri: rpcUri,
415 - headers: {'Content-Type': 'application/json'},
416 - body: jsonBody,
417 - allowMitmMoneroBypassSSLCheck: true
418 - );
409 + clearnetUri: rpcUri,
410 + headers: {'Content-Type': 'application/json'},
411 + body: jsonBody,
412 + allowMitmMoneroBypassSSLCheck: true);
413 // Check if we received a 401 Unauthorized response
414 if (response.statusCode == 401) {
415 final daemonRpc = DaemonRpc(
@@ -494,7 +488,6 @@ class Node {
488 final ProxySocket socket;
489 socket = await ProxyWrapper().getSocksSocket(useSSL ?? false, uri.host, uri.port);
490
497 -
491 socket.destroy();
492 return true;
493 } catch (_) {
@@ -531,9 +524,12 @@ class Node {
524
525 Future<bool> requestEthereumServer() async {
526 try {
534 - final req = await ProxyWrapper().getHttpClient()
535 - .getUrl(uri,)
536 - .timeout(Duration(seconds: 15));
527 + final req = await ProxyWrapper()
528 + .getHttpClient()
529 + .getUrl(
530 + uri,
531 + )
532 + .timeout(Duration(seconds: 15));
533 final response = await req.close();
534
535 return response.statusCode >= 200 && response.statusCode < 300;
@@ -544,13 +540,13 @@ class Node {
540 }
541
542 Future<bool> requestDecredNode() async {
547 - if (uri.host == "default-spv-nodes") {
548 - // Just show default port as ok. The wallet will connect to a list of known
549 - // nodes automatically.
550 - return true;
551 - }
552 - try {
553 - final socket = await Socket.connect(uri.host, uri.port, timeout: Duration(seconds: 5));
543 + if (uri.host == "default-spv-nodes") {
544 + // Just show default port as ok. The wallet will connect to a list of known
545 + // nodes automatically.
546 + return true;
547 + }
548 + try {
549 + final socket = await Socket.connect(uri.host, uri.port, timeout: Duration(seconds: 5));
550 socket.destroy();
551 return true;
552 } catch (_) {
cw_core/lib/node_legacy.dart
+18 -28
@@ -19,17 +19,15 @@ import 'node.dart' as node_new;
19 part 'node_legacy.part.dart';
20
21 Future<void> performNodeHiveMigration() async {
22 - if(!CakeHive.isAdapterRegistered(Node.typeId)) {
22 + if (!CakeHive.isAdapterRegistered(Node.typeId)) {
23 CakeHive.registerAdapter(NodeAdapter());
24 }
25
26 final nodeBox = await CakeHive.openBox<Node>(Node.boxName);
27 - final powNodeBox = await CakeHive.openBox<Node>(Node.boxName+"pow");
27 + final powNodeBox = await CakeHive.openBox<Node>(Node.boxName + "pow");
28 final builtinNodes = await loadAllDefaultNodes();
29 final builtinPowNodes = await loadDefaultNanoPowNodes();
30 await Node.migrateAllToSqlite(nodeBox, powNodeBox, builtinNodes, builtinPowNodes);
31 -
32 -
31 }
32
33 Uri createUriFromElectrumAddress(String address, String path) =>
@@ -62,31 +60,26 @@ class Node extends HiveObject with Keyable {
60 final list = nodeBox.values.toList();
61 final powList = powNodeBox.values.toList();
62 for (final node in list) {
65 - if(defaultNodes.any((item)=>item.uri == node.uri)) {
63 + if (defaultNodes.any((item) => item.uri == node.uri)) {
64 // default nodes will be added by validateBuiltinNodes(), no need to migrate them.
65 await node.delete();
66 continue;
67 }
70 - await node.migrateToSqlite(
71 - isPow: false,
72 - isBuiltin: false,
73 - isOfficial: false);
68 + await node.migrateToSqlite(isPow: false, isBuiltin: false, isOfficial: false);
69 await node.delete();
70 }
71 for (final node in powList) {
77 - if(defaultPowNodes.any((item)=>item.uri == node.uri)) {
72 + if (defaultPowNodes.any((item) => item.uri == node.uri)) {
73 await node.delete();
74 continue;
75 }
81 - await node.migrateToSqlite(
82 - isPow: true,
83 - isBuiltin: false,
84 - isOfficial: false);
76 + await node.migrateToSqlite(isPow: true, isBuiltin: false, isOfficial: false);
77 await node.delete();
78 }
79 }
80
89 - Future<void> migrateToSqlite({required bool isPow, required bool isBuiltin, required bool isOfficial}) async {
81 + Future<void> migrateToSqlite(
82 + {required bool isPow, required bool isBuiltin, required bool isOfficial}) async {
83 final newNode = node_new.Node(
84 id: key as int,
85 login: login,
@@ -106,7 +99,6 @@ class Node extends HiveObject with Keyable {
99 await newNode.save();
100 }
101
109 -
102 Node.fromMap(Map<String, Object?> map)
103 : uriRaw = map['uri'] as String? ?? '',
104 path = map['path'] as String? ?? '',
@@ -208,15 +200,15 @@ class Node extends HiveObject with Keyable {
200 @override
201 bool operator ==(other) =>
202 other is Node &&
211 - (other.uriRaw == uriRaw &&
212 - other.login == login &&
213 - other.label == label &&
214 - other.password == password &&
215 - other.typeRaw == typeRaw &&
216 - other.useSSL == useSSL &&
217 - other.trusted == trusted &&
218 - other.socksProxyAddress == socksProxyAddress &&
219 - other.path == path);
203 + (other.uriRaw == uriRaw &&
204 + other.login == login &&
205 + other.label == label &&
206 + other.password == password &&
207 + other.typeRaw == typeRaw &&
208 + other.useSSL == useSSL &&
209 + other.trusted == trusted &&
210 + other.socksProxyAddress == socksProxyAddress &&
211 + other.path == path);
212
213 @override
214 int get hashCode =>
@@ -241,6 +233,4 @@ class Node extends HiveObject with Keyable {
233 set type(WalletType type) => typeRaw = serializeToInt(type);
234
235 dynamic _keyIndex;
244 -
245 -
246 -}
\ No newline at end of file
236 +}
cw_core/lib/node_legacy.part.dart
+2 -5
@@ -24,8 +24,7 @@ class NodeAdapter extends TypeAdapter<Node> {
24 trusted: fields[5] == null ? false : fields[5] as bool,
25 socksProxyAddress: fields[6] as String?,
26 path: fields[7] == null ? '' : fields[7] as String?,
27 - isEnabledForAutoSwitching:
28 - fields[11] == null ? false : fields[11] as bool,
27 + isEnabledForAutoSwitching: fields[11] == null ? false : fields[11] as bool,
28 )
29 ..uriRaw = fields[0] == null ? '' : fields[0] as String
30 ..typeRaw = fields[3] == null ? 0 : fields[3] as int
@@ -72,7 +71,5 @@ class NodeAdapter extends TypeAdapter<Node> {
71 @override
72 bool operator ==(Object other) =>
73 identical(this, other) ||
75 - other is NodeAdapter &&
76 - runtimeType == other.runtimeType &&
77 - typeId == other.typeId;
74 + other is NodeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
75 }
cw_core/lib/node_list.dart
+8 -13
@@ -18,7 +18,7 @@ Future<List<Node>> loadDefaultNodes(WalletType type) async {
18 case WalletType.haven:
19 path = 'assets/haven_node_list.yml';
20 break;
21 - // TODO: (refactoring) each wallet would have its path, so `wallet.nodePath` would be decided based on chain id in Evm wallet
21 + // TODO: (refactoring) each wallet would have its path, so `wallet.nodePath` would be decided based on chain id in Evm wallet
22 case WalletType.ethereum:
23 path = 'assets/ethereum_server_list.yml';
24 break;
@@ -147,7 +147,6 @@ Future<List<Node>> loadAllDefaultNodes() async {
147 }
148
149 Future<void> resetToDefault() async {
150 -
150 final nodes = await loadAllDefaultNodes();
151
152 final currentNodes = await Node.getAll();
@@ -157,15 +156,14 @@ Future<void> resetToDefault() async {
156 for (final node in nodes) {
157 try {
158 final curr = currentNodes.firstWhere(
160 - (item) => item.uri == node.uri && item.typeRaw == node.typeRaw,
159 + (item) => item.uri == node.uri && item.typeRaw == node.typeRaw,
160 );
162 - node.id = curr.id;
163 - } catch(e) {}
164 -
161 + node.id = curr.id;
162 + } catch (e) {}
163 }
164
165 await Node.deleteAll();
168 - for(final node in nodes) {
166 + for (final node in nodes) {
167 await node.save();
168 }
169 }
@@ -173,7 +171,7 @@ Future<void> resetToDefault() async {
171 Future<void> resetPowToDefault() async {
172 final nanoPowNodes = await loadDefaultNanoPowNodes();
173 await Node.deleteAllPow();
176 - for(final node in nanoPowNodes) {
174 + for (final node in nanoPowNodes) {
175 node.save();
176 }
177 }
@@ -181,12 +179,9 @@ Future<void> resetPowToDefault() async {
179 Future<Node> getDefaultNodeFromFiles(WalletType type, {bool isPow = false}) async {
180 final nodes = isPow ? await loadDefaultNanoPowNodes() : await loadDefaultNodes(type);
181 try {
184 - return nodes.firstWhere((item)=>item.isDefault);
185 - } catch(e) {
182 + return nodes.firstWhere((item) => item.isDefault);
183 + } catch (e) {
184 // ideally the yamls would always have a default, but this is better than nothing
185 return nodes.first;
186 }
187 }
190 -
191 -
192 -
cw_core/lib/parseBoolFromString.dart
+1 -1
@@ -1,3 +1,3 @@
1 bool parseBoolFromString(String string) {
2 return string.toString() == 'true';
3 -}
\ No newline at end of file
3 +}
cw_core/lib/parse_fixed.dart
+2 -1
@@ -52,7 +52,8 @@ BigInt parseFixed(String value, int decimals) {
52 var fraction = (comps.length == 2 ? comps[1] : "0").padRight(decimals, "0");
53
54 if (fraction.length > multiplier.length - 1) {
55 - throw FormatException("fractional component(${fraction.length}) exceeds decimals(${decimals}), underflow, parseFixed");
55 + throw FormatException(
56 + "fractional component(${fraction.length}) exceeds decimals(${decimals}), underflow, parseFixed");
57 }
58
59 final wholeValue = BigInt.parse(whole);
cw_core/lib/pathForWallet.dart
+1 -2
@@ -28,8 +28,7 @@ Future<String> pathForWalletDir({required String name, required WalletType type}
28 }
29
30 Future<String> pathForWallet({required String name, required WalletType type}) async =>
31 - await pathForWalletDir(name: name, type: type)
32 - .then((path) => path + '/$name');
31 + await pathForWalletDir(name: name, type: type).then((path) => path + '/$name');
32
33 Future<String> outdatedAndroidPathForWalletDir({required String name}) async {
34 final directory = await getAppDir();
cw_core/lib/payjoin_session.dart
-1
@@ -56,7 +56,6 @@ class PayjoinSession extends HiveObject {
56
57 BigInt get amount => BigInt.parse(rawAmount ?? "0");
58 set amount(BigInt amount) => rawAmount = amount.toString();
59 -
59 }
60
61 enum PayjoinSessionStatus {
cw_core/lib/payjoin_session.part.dart
+1 -3
@@ -59,7 +59,5 @@ class PayjoinSessionAdapter extends TypeAdapter<PayjoinSession> {
59 @override
60 bool operator ==(Object other) =>
61 identical(this, other) ||
62 - other is PayjoinSessionAdapter &&
63 - runtimeType == other.runtimeType &&
64 - typeId == other.typeId;
62 + other is PayjoinSessionAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
63 }
cw_core/lib/payment_uris.dart
+3 -4
@@ -408,14 +408,14 @@ class ERC681URI extends PaymentURI {
408
409 static int _getChainID(String path) {
410 return int.parse(RegExp(
411 - r'@\d*',
412 - ).firstMatch(path)?.group(0)?.replaceAll("@", "") ??
411 + r'@\d*',
412 + ).firstMatch(path)?.group(0)?.replaceAll("@", "") ??
413 "1");
414 }
415
416 static (bool, String) _getTargetAddress(String path) {
417 final targetAddress =
418 - RegExp(r'^(0x)?[0-9a-f]{40}', caseSensitive: false).firstMatch(path)!.group(0)!;
418 + RegExp(r'^(0x)?[0-9a-f]{40}', caseSensitive: false).firstMatch(path)!.group(0)!;
419 return (path.contains("/"), targetAddress);
420 }
421
@@ -508,4 +508,3 @@ class LightningPaymentRequest extends PaymentURI {
508 @override
509 String toString() => bolt11Invoice ?? "lightning:$lnURL";
510 }
511 -
cw_core/lib/root_dir.dart
+16 -12
@@ -23,12 +23,11 @@ bool get isNonAmnesticTails {
23
24 bool showNotice = true;
25
26 -void setRootDirFromEnv() =>
27 - _rootDirPath = Platform.environment['CAKE_WALLET_DIR'];
26 +void setRootDirFromEnv() => _rootDirPath = Platform.environment['CAKE_WALLET_DIR'];
27
28 void copyDirectory(Directory source, Directory destination) {
29 source.listSync(recursive: false).forEach((var entity) {
31 - if (entity is Directory) {
30 + if (entity is Directory) {
31 var newDirectory = Directory(p.join(destination.absolute.path, p.basename(entity.path)));
32 newDirectory.createSync(recursive: true);
33 copyDirectory(entity.absolute, newDirectory);
@@ -41,7 +40,8 @@ void copyDirectory(Directory source, Directory destination) {
40
41 Future<void> linuxSymlinkSharedPreferences() async {
42 if (!Platform.isLinux) return; // nuh-uh
44 - final dataHome = Platform.environment["XDG_DATA_HOME"] ?? p.join(Platform.environment["HOME"] ?? "", ".local", "share");
43 + final dataHome = Platform.environment["XDG_DATA_HOME"] ??
44 + p.join(Platform.environment["HOME"] ?? "", ".local", "share");
45 var cakeNames = ['com.example.cake_wallet', 'cake_wallet'];
46 for (String name in cakeNames) {
47 final oldPath = p.join(dataHome, name);
@@ -53,8 +53,8 @@ Future<void> linuxSymlinkSharedPreferences() async {
53 if (oldLink.existsSync()) {
54 printV("not creating, link exists");
55 } else {
56 - if (newDir.existsSync()) {
57 - newDir.renameSync("${newPath}_${DateTime.now().millisecondsSinceEpoch~/1000}");
56 + if (newDir.existsSync()) {
57 + newDir.renameSync("${newPath}_${DateTime.now().millisecondsSinceEpoch ~/ 1000}");
58 }
59 copyDirectory(oldDir, newDir);
60 oldDir.deleteSync(recursive: true);
@@ -94,14 +94,16 @@ Future<Directory> getAppDir() async {
94 // for storing things that users in general back-up
95 var linuxAppPath = [
96 if (appDirPath != null) appDirPath, // old preferred
97 - p.join('/home', Platform.environment['USER']??"null", appName), // old fallback
98 - if (Platform.environment['HOME'] != null) p.join(Platform.environment['HOME']!, ".$appName"), // old fallback but using HOME
99 - if (Platform.environment['HOME'] != null) p.join(Platform.environment['HOME']!, '.config', appName), // old fallback but using HOME
97 + p.join('/home', Platform.environment['USER'] ?? "null", appName), // old fallback
98 + if (Platform.environment['HOME'] != null)
99 + p.join(Platform.environment['HOME']!, ".$appName"), // old fallback but using HOME
100 + if (Platform.environment['HOME'] != null)
101 + p.join(Platform.environment['HOME']!, '.config', appName), // old fallback but using HOME
102 if (isNonAmnesticTails) p.join(_tailsData, ".$appName") // tails (if persistance is enabled)
103 ];
104
105 String preferredPath = linuxAppPath.last;
104 -
106 +
107 preferredLoop:
108 for (String notSoPreferredPath in linuxAppPath) {
109 if (notSoPreferredPath == linuxAppPath.last) continue;
@@ -109,8 +111,10 @@ Future<Directory> getAppDir() async {
111 if (useThisOne) {
112 if (showNotice) {
113 showNotice = false;
112 - printV("Not using $preferredPath because $notSoPreferredPath exists, falling back for backwards compatibility");
113 - printV("Can't see your wallet? Check\n - ${linuxAppPath.join("\n - ")}\n and move directory that to $preferredPath");
114 + printV(
115 + "Not using $preferredPath because $notSoPreferredPath exists, falling back for backwards compatibility");
116 + printV(
117 + "Can't see your wallet? Check\n - ${linuxAppPath.join("\n - ")}\n and move directory that to $preferredPath");
118 printV("Or use CAKE_WALLET_DIR=/path/to/app/ ${Platform.executable}");
119 }
120 preferredPath = notSoPreferredPath;
cw_core/lib/sec_random_native.dart
+2 -1
@@ -14,7 +14,8 @@ Future<Uint8List> secRandom(int count) async {
14 final rng = Random.secure();
15 return Uint8List.fromList(List<int>.generate(count, (_) => rng.nextInt(byteSize)));
16 }
17 - return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}) ?? Uint8List.fromList([]);
17 + return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}) ??
18 + Uint8List.fromList([]);
19 } on PlatformException catch (_) {
20 return Uint8List.fromList([]);
21 }
cw_core/lib/solana_rpc_http_service.dart
+2 -4
@@ -4,14 +4,12 @@ import 'package:on_chain/solana/solana.dart';
4
5 class SolanaRPCHTTPService implements SolanaJSONRPCService {
6 SolanaRPCHTTPService(
7 - {required this.url,
8 - this.defaultRequestTimeout = const Duration(seconds: 30)});
7 + {required this.url, this.defaultRequestTimeout = const Duration(seconds: 30)});
8 @override
9 final String url;
10 final Duration defaultRequestTimeout;
11
13 - Future<Map<String, dynamic>> call(SolanaRequestDetails params,
14 - [Duration? timeout]) async {
12 + Future<Map<String, dynamic>> call(SolanaRequestDetails params, [Duration? timeout]) async {
13 final response = await ProxyWrapper().post(
14 clearnetUri: Uri.parse(url),
15 body: params.toRequestBody(),
cw_core/lib/spl_token.part.dart
+1 -3
@@ -58,7 +58,5 @@ class SPLTokenAdapter extends TypeAdapter<SPLToken> {
58 @override
59 bool operator ==(Object other) =>
60 identical(this, other) ||
61 - other is SPLTokenAdapter &&
62 - runtimeType == other.runtimeType &&
63 - typeId == other.typeId;
61 + other is SPLTokenAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
62 }
cw_core/lib/transaction_direction.dart
+5 -3
@@ -7,7 +7,8 @@ TransactionDirection parseTransactionDirectionFromInt(int raw) {
7 case 1:
8 return TransactionDirection.outgoing;
9 default:
10 - throw Exception('Unexpected token: raw for TransactionDirection parseTransactionDirectionFromInt');
10 + throw Exception(
11 + 'Unexpected token: raw for TransactionDirection parseTransactionDirectionFromInt');
12 }
13 }
14
@@ -18,6 +19,7 @@ TransactionDirection parseTransactionDirectionFromNumber(String raw) {
19 case "1":
20 return TransactionDirection.outgoing;
21 default:
21 - throw Exception('Unexpected token: raw for TransactionDirection parseTransactionDirectionFromNumber');
22 + throw Exception(
23 + 'Unexpected token: raw for TransactionDirection parseTransactionDirectionFromNumber');
24 }
23 -}
\ No newline at end of file
25 +}
cw_core/lib/transaction_history.dart
+1 -2
@@ -2,8 +2,7 @@ import 'package:mobx/mobx.dart';
2 import 'package:cw_core/transaction_info.dart';
3
4 abstract class TransactionHistoryBase<TransactionType extends TransactionInfo> {
5 - TransactionHistoryBase()
6 - : transactions = ObservableMap<String, TransactionType>();
5 + TransactionHistoryBase() : transactions = ObservableMap<String, TransactionType>();
6
7 @observable
8 ObservableMap<String, TransactionType> transactions;
cw_core/lib/transaction_priority.dart
+3 -3
@@ -1,9 +1,9 @@
1 import 'package:cw_core/enumerable_item.dart';
2
3 -abstract class TransactionPriority extends EnumerableItem<int>
4 - with Serializable<int> {
3 +abstract class TransactionPriority extends EnumerableItem<int> with Serializable<int> {
4 final String? description;
5 final String? hint;
6
8 - const TransactionPriority({required String title, required int raw, this.description, this.hint}) : super(title: title, raw: raw);
7 + const TransactionPriority({required String title, required int raw, this.description, this.hint})
8 + : super(title: title, raw: raw);
9 }
cw_core/lib/tron_token.part.dart
+1 -3
@@ -55,7 +55,5 @@ class TronTokenAdapter extends TypeAdapter<TronToken> {
55 @override
56 bool operator ==(Object other) =>
57 identical(this, other) ||
58 - other is TronTokenAdapter &&
59 - runtimeType == other.runtimeType &&
60 - typeId == other.typeId;
58 + other is TronTokenAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
59 }
cw_core/lib/utils/file.dart
+1 -3
@@ -6,9 +6,7 @@ Future<void> write({required String path, required String password, required Str
6 writeData(path: path, password: password, data: data);
7
8 Future<void> writeData(
9 - {required String path,
10 - required String password,
11 - required String data}) async {
9 + {required String path, required String password, required String data}) async {
10 final keys = extractKeys(password);
11 final key = encrypt.Key.fromBase64(keys.first);
12 final iv = encrypt.IV.fromBase64(keys.last);
cw_core/lib/utils/proxy_logger/abstract.dart
+3 -3
@@ -11,7 +11,7 @@ enum RequestMethod {
11 post,
12 put,
13 delete,
14 -
14 +
15 newHttpClient,
16 newHttpIOClient,
17 newProxySocket,
@@ -23,7 +23,7 @@ abstract class ProxyLogger {
23 required RequestMethod method,
24 required Uint8List body,
25 required very_insecure_http_do_not_use.Response? response,
26 - required RequestNetwork network,
26 + required RequestNetwork network,
27 required String? error,
28 });
29 -}
\ No newline at end of file
29 +}
cw_core/lib/utils/proxy_logger/memory_proxy_logger.dart
+12 -10
@@ -46,18 +46,20 @@ class MemoryProxyLogger implements ProxyLogger {
46 required RequestMethod method,
47 required Uint8List body,
48 required very_insecure_http_do_not_use.Response? response,
49 - required RequestNetwork network,
49 + required RequestNetwork network,
50 required String? error,
51 }) {
52 final trace = StackTrace.current;
53 - logs.add(MemoryProxyLoggerEntry(
54 - method: method,
55 - trace: trace,
56 - uri: uri,
57 - body: body,
58 - network: network,
59 - response: response,
60 - error: error,),
53 + logs.add(
54 + MemoryProxyLoggerEntry(
55 + method: method,
56 + trace: trace,
57 + uri: uri,
58 + body: body,
59 + network: network,
60 + response: response,
61 + error: error,
62 + ),
63 );
64 }
63 -}
\ No newline at end of file
65 +}
cw_core/lib/utils/proxy_logger/silent_logger.dart
+2 -2
@@ -11,7 +11,7 @@ class SilentProxyLogger implements ProxyLogger {
11 required RequestMethod method,
12 required Uint8List body,
13 required very_insecure_http_do_not_use.Response? response,
14 - required RequestNetwork network,
14 + required RequestNetwork network,
15 required String? error,
16 }) {}
17 -}
\ No newline at end of file
17 +}
cw_core/lib/utils/proxy_socket/abstract.dart
+10 -7
@@ -16,19 +16,21 @@ class ProxyAddress {
16 }
17
18 abstract class ProxySocket {
19 - static Future<ProxySocket> connect(bool sslEnabled, ProxyAddress address, {Duration? connectionTimeout}) async {
19 + static Future<ProxySocket> connect(bool sslEnabled, ProxyAddress address,
20 + {Duration? connectionTimeout}) async {
21 if (CakeTor.instance!.started) {
22 var socksSocket = await SOCKSSocket.create(
22 - proxyHost: InternetAddress.loopbackIPv4.address,
23 - proxyPort: CakeTor.instance!.port,
24 - sslEnabled: sslEnabled,
23 + proxyHost: InternetAddress.loopbackIPv4.address,
24 + proxyPort: CakeTor.instance!.port,
25 + sslEnabled: sslEnabled,
26 );
27 await socksSocket.connect();
28 await socksSocket.connectTo(address.host, address.port);
29 return ProxySocketSocks(socksSocket);
30 }
31 if (sslEnabled == false) {
31 - return ProxySocketInsecure(await Socket.connect(address.host, address.port, timeout: connectionTimeout));
32 + return ProxySocketInsecure(
33 + await Socket.connect(address.host, address.port, timeout: connectionTimeout));
34 } else {
35 return ProxySocketSecure(await SecureSocket.connect(
36 address.host,
@@ -43,6 +45,7 @@ abstract class ProxySocket {
45 void destroy();
46 void write(String data);
47 bool get isClosed;
46 - StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function (Object error)? onError, Function ()? onDone, bool cancelOnError = true});
48 + StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
49 + {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true});
50 ProxyAddress get address;
48 -}
\ No newline at end of file
51 +}
cw_core/lib/utils/proxy_socket/insecure.dart
+11 -10
@@ -1,4 +1,3 @@
1 -
1 import 'package:cw_core/utils/print_verbose.dart';
2 import 'package:cw_core/utils/proxy_socket/abstract.dart';
3 import 'dart:async';
@@ -9,15 +8,16 @@ class ProxySocketInsecure implements ProxySocket {
8 final Socket socket;
9
10 ProxySocketInsecure(this.socket);
12 -
11 +
12 bool isClosed = false;
13
15 - ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
16 -
14 + ProxyAddress get address =>
15 + ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
16 +
17 @override
18 Future<void> close() async {
19 try {
20 - if (isClosed) return;
20 + if (isClosed) return;
21 isClosed = true;
22 return socket.close();
23 } catch (e) {
@@ -25,7 +25,7 @@ class ProxySocketInsecure implements ProxySocket {
25 return;
26 }
27 }
28 -
28 +
29 @override
30 void destroy() async {
31 try {
@@ -37,7 +37,7 @@ class ProxySocketInsecure implements ProxySocket {
37 return;
38 }
39 }
40 -
40 +
41 @override
42 void write(String data) {
43 try {
@@ -51,9 +51,10 @@ class ProxySocketInsecure implements ProxySocket {
51 return;
52 }
53 }
54 -
54 +
55 @override
56 - StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
56 + StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
57 + {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
58 return socket.listen(
59 (data) {
60 onData(Uint8List.fromList(data));
@@ -63,4 +64,4 @@ class ProxySocketInsecure implements ProxySocket {
64 cancelOnError: cancelOnError,
65 );
66 }
66 -}
\ No newline at end of file
67 +}
cw_core/lib/utils/proxy_socket/secure.dart
+10 -8
@@ -11,9 +11,10 @@ class ProxySocketSecure implements ProxySocket {
11 bool isClosed = false;
12
13 ProxySocketSecure(this.socket);
14 -
15 - ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
16 -
14 +
15 + ProxyAddress get address =>
16 + ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
17 +
18 @override
19 Future<void> close() async {
20 try {
@@ -25,11 +26,11 @@ class ProxySocketSecure implements ProxySocket {
26 return;
27 }
28 }
28 -
29 +
30 @override
31 void destroy() async {
32 try {
32 - if (isClosed) return;
33 + if (isClosed) return;
34 isClosed = true;
35 socket.destroy();
36 } catch (e) {
@@ -37,7 +38,7 @@ class ProxySocketSecure implements ProxySocket {
38 return;
39 }
40 }
40 -
41 +
42 @override
43 void write(String data) {
44 runZonedGuarded(() {
@@ -57,9 +58,10 @@ class ProxySocketSecure implements ProxySocket {
58 printV("ProxySocketSecure: write (async error): $e");
59 });
60 }
60 -
61 +
62 @override
62 - StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
63 + StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
64 + {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
65 return socket.listen(
66 (data) {
67 onData(Uint8List.fromList(data));
cw_core/lib/utils/proxy_socket/socks.dart
+6 -6
@@ -9,10 +9,10 @@ class ProxySocketSocks implements ProxySocket {
9 final SOCKSSocket socket;
10 bool isClosed = false;
11 ProxySocketSocks(this.socket);
12 -
12 +
13 @override
14 ProxyAddress get address => ProxyAddress(host: socket.proxyHost, port: socket.proxyPort);
15 -
15 +
16 @override
17 Future<void> close() async {
18 try {
@@ -24,10 +24,10 @@ class ProxySocketSocks implements ProxySocket {
24 return;
25 }
26 }
27 -
27 +
28 @override
29 void destroy() => close();
30 -
30 +
31 @override
32 void write(String data) {
33 try {
@@ -43,7 +43,8 @@ class ProxySocketSocks implements ProxySocket {
43 }
44
45 @override
46 - StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
46 + StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
47 + {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
48 return socket.listen(
49 (data) {
50 onData(Uint8List.fromList(data));
@@ -54,4 +55,3 @@ class ProxySocketSocks implements ProxySocket {
55 );
56 }
57 }
57 -
cw_core/lib/utils/proxy_wrapper.dart
+23 -27
@@ -16,22 +16,23 @@ class ProxyWrapper {
16 factory ProxyWrapper() {
17 return _proxyWrapper;
18 }
19 -
19 +
20 ProxyWrapper._internal();
21 - Future<ProxySocket> getSocksSocket(bool sslEnabled, String host, int port, {Duration? connectionTimeout}) async {
21 + Future<ProxySocket> getSocksSocket(bool sslEnabled, String host, int port,
22 + {Duration? connectionTimeout}) async {
23 logger?.log(
23 - uri: Uri(
24 - scheme: sslEnabled ? "https" : "http",
25 - host: host,
26 - port: port,
27 - ),
28 - method: RequestMethod.newProxySocket,
29 - body: Uint8List(0),
30 - response: null,
31 - network: requestNetwork(),
32 - error: null
33 - );
34 - return ProxySocket.connect(sslEnabled, ProxyAddress(host: host, port: port), connectionTimeout: connectionTimeout);
24 + uri: Uri(
25 + scheme: sslEnabled ? "https" : "http",
26 + host: host,
27 + port: port,
28 + ),
29 + method: RequestMethod.newProxySocket,
30 + body: Uint8List(0),
31 + response: null,
32 + network: requestNetwork(),
33 + error: null);
34 + return ProxySocket.connect(sslEnabled, ProxyAddress(host: host, port: port),
35 + connectionTimeout: connectionTimeout);
36 }
37
38 RequestNetwork requestNetwork() {
@@ -56,17 +57,17 @@ class ProxyWrapper {
57
58 int getPort() => CakeTor.instance!.port;
59
59 - @Deprecated('Use ProxyWrapper().get/post/put methods instead, and provide proper clearnet and onion uri.')
60 + @Deprecated(
61 + 'Use ProxyWrapper().get/post/put methods instead, and provide proper clearnet and onion uri.')
62 HttpClient getHttpClient({int? portOverride, bool internal = false}) {
63 if (!internal) {
64 logger?.log(
63 - uri: null,
64 - method: RequestMethod.newProxySocket,
65 - body: Uint8List(0),
66 - response: null,
67 - network: requestNetwork(),
68 - error: null
69 - );
65 + uri: null,
66 + method: RequestMethod.newProxySocket,
67 + body: Uint8List(0),
68 + response: null,
69 + network: requestNetwork(),
70 + error: null);
71 }
72 if (CakeTor.instance!.started) {
73 // Assign connection factory.
@@ -84,8 +85,6 @@ class ProxyWrapper {
85 }
86 }
87
87 -
88 -
88 Future<Response> _make({
89 required RequestMethod method,
90 required ioc.IOClient client,
@@ -216,7 +215,6 @@ class ProxyWrapper {
215
216 throw Exception("Unable to connect to server");
217 }
219 -
218
219 Future<Response> post({
220 Map<String, String>? headers,
@@ -235,7 +233,6 @@ class ProxyWrapper {
233
234 ioc.IOClient clearnetClient = ioc.IOClient(cleatnetHttpClient);
235
238 -
236 bool torEnabled = CakeTor.instance!.started;
237
238 if (torEnabled) {
@@ -439,7 +436,6 @@ class ProxyWrapper {
436 }
437 }
438
442 -
439 class CakeTor {
440 static CakeTorInstance? instance;
441 }
cw_core/lib/utils/tor/abstract.dart
+1 -1
@@ -65,4 +65,4 @@ CakeTorInstance(
65 )
66 """;
67 }
68 -}
\ No newline at end of file
68 +}
cw_core/lib/utils/tor/disabled.dart
+1 -1
@@ -30,4 +30,4 @@ CakeTorDisabled(
30 )
31 """;
32 }
33 -}
\ No newline at end of file
33 +}
cw_core/lib/utils/tor/socks.dart
+1 -1
@@ -31,4 +31,4 @@ CakeTorSocks(
31 )
32 """;
33 }
34 -}
\ No newline at end of file
34 +}
cw_core/lib/utils/tor/torch.dart
+1 -1
@@ -88,4 +88,4 @@ CakeTorTorch(
88 )
89 """;
90 }
91 -}
\ No newline at end of file
91 +}
cw_core/lib/utils/zpub.dart
+11 -11
@@ -1,4 +1,3 @@
1 -
1 import 'dart:typed_data';
2
3 import 'package:blockchain_utils/blockchain_utils.dart';
@@ -15,31 +14,32 @@ String convertAnyToXpub(String any) {
14 String convertZpubToXpub(String zpub) {
15 try {
16 final decoded = Base58Decoder.checkDecode(zpub);
18 -
17 +
18 if (decoded.length < 4) {
19 throw ArgumentError('Invalid extended public key length');
20 }
22 -
21 +
22 final versionBytes = decoded.sublist(0, 4);
23 final zpubVersionBytes = [0x04, 0xb2, 0x47, 0x46]; // zpub mainnet version
24 final zpubTestnetVersionBytes = [0x04, 0x5f, 0x1c, 0xf6]; // vpub testnet version
26 -
25 +
26 bool isZpub = listEquals(versionBytes, zpubVersionBytes);
27 bool isVpub = listEquals(versionBytes, zpubTestnetVersionBytes);
29 -
28 +
29 if (!isZpub && !isVpub) {
30 return zpub;
31 }
33 -
34 - final xpubVersionBytes = isZpub ?
35 - [0x04, 0x88, 0xb2, 0x1e] : // xpub mainnet
36 - [0x04, 0x35, 0x87, 0xcf]; // tpub testnet
37 -
32 +
33 + final xpubVersionBytes = isZpub
34 + ? [0x04, 0x88, 0xb2, 0x1e]
35 + : // xpub mainnet
36 + [0x04, 0x35, 0x87, 0xcf]; // tpub testnet
37 +
38 final newExtendedKey = Uint8List.fromList([
39 ...xpubVersionBytes,
40 ...decoded.sublist(4),
41 ]);
42 -
42 +
43 return Base58Encoder.checkEncode(newExtendedKey);
44 } catch (e) {
45 throw ArgumentError('Failed to convert zpub to xpub: $e');
cw_core/lib/wallet_info.dart
+120 -122
@@ -327,79 +327,77 @@ class DerivationInfo {
327
328 class WalletInfo {
329 WalletInfo(
330 - this.internalId,
331 - this.id,
332 - this.name,
333 - this.type,
334 - this.isRecovery,
335 - this.restoreHeight,
336 - this.timestamp,
337 - this.dirPath,
338 - this.path,
339 - this.address,
340 - this.yatEid,
341 - this.yatLastUsedAddressRaw,
342 - this.showIntroCakePayCard,
343 - this.derivationInfoId,
344 - this.hardwareWalletType,
345 - this.parentAddress,
346 - this.hashedWalletIdentifier,
347 - this.isNonSeedWallet,
348 - this.sortOrder,
349 - this.addressPageType,
350 - this.receiveInfoboxDismissed,
351 - this.showCombinedBalance,
352 - this.favoriteTokenAddress
353 - ) : _yatLastUsedAddressController = StreamController<String>.broadcast();
354 -
355 - factory WalletInfo.external({
356 - required String id,
357 - required String name,
358 - required WalletType type,
359 - required bool isRecovery,
360 - required int restoreHeight,
361 - required DateTime date,
362 - required String dirPath,
363 - required String path,
364 - required String address,
365 - bool? showIntroCakePayCard,
366 - String yatEid = '',
367 - String yatLastUsedAddressRaw = '',
368 - int? derivationInfoId,
369 - HardwareWalletType? hardwareWalletType,
370 - String? parentAddress,
371 - String? hashedWalletIdentifier,
372 - bool? isNonSeedWallet,
373 - int? sortOrder,
374 - bool? receiveInfoboxDismissed,
375 - bool? showCombinedBalance,
376 - String? favoriteTokenAddress
377 - }) {
330 + this.internalId,
331 + this.id,
332 + this.name,
333 + this.type,
334 + this.isRecovery,
335 + this.restoreHeight,
336 + this.timestamp,
337 + this.dirPath,
338 + this.path,
339 + this.address,
340 + this.yatEid,
341 + this.yatLastUsedAddressRaw,
342 + this.showIntroCakePayCard,
343 + this.derivationInfoId,
344 + this.hardwareWalletType,
345 + this.parentAddress,
346 + this.hashedWalletIdentifier,
347 + this.isNonSeedWallet,
348 + this.sortOrder,
349 + this.addressPageType,
350 + this.receiveInfoboxDismissed,
351 + this.showCombinedBalance,
352 + this.favoriteTokenAddress)
353 + : _yatLastUsedAddressController = StreamController<String>.broadcast();
354 +
355 + factory WalletInfo.external(
356 + {required String id,
357 + required String name,
358 + required WalletType type,
359 + required bool isRecovery,
360 + required int restoreHeight,
361 + required DateTime date,
362 + required String dirPath,
363 + required String path,
364 + required String address,
365 + bool? showIntroCakePayCard,
366 + String yatEid = '',
367 + String yatLastUsedAddressRaw = '',
368 + int? derivationInfoId,
369 + HardwareWalletType? hardwareWalletType,
370 + String? parentAddress,
371 + String? hashedWalletIdentifier,
372 + bool? isNonSeedWallet,
373 + int? sortOrder,
374 + bool? receiveInfoboxDismissed,
375 + bool? showCombinedBalance,
376 + String? favoriteTokenAddress}) {
377 return WalletInfo(
379 - 0,
380 - id,
381 - name,
382 - type,
383 - isRecovery,
384 - restoreHeight,
385 - date.millisecondsSinceEpoch,
386 - dirPath,
387 - path,
388 - address,
389 - yatEid,
390 - yatLastUsedAddressRaw,
391 - showIntroCakePayCard,
392 - derivationInfoId ?? -1,
393 - hardwareWalletType,
394 - parentAddress,
395 - hashedWalletIdentifier,
396 - isNonSeedWallet ?? false,
397 - sortOrder ?? 0,
398 - null,
399 - receiveInfoboxDismissed ?? false,
400 - showCombinedBalance ?? true,
401 - favoriteTokenAddress
402 - );
378 + 0,
379 + id,
380 + name,
381 + type,
382 + isRecovery,
383 + restoreHeight,
384 + date.millisecondsSinceEpoch,
385 + dirPath,
386 + path,
387 + address,
388 + yatEid,
389 + yatLastUsedAddressRaw,
390 + showIntroCakePayCard,
391 + derivationInfoId ?? -1,
392 + hardwareWalletType,
393 + parentAddress,
394 + hashedWalletIdentifier,
395 + isNonSeedWallet ?? false,
396 + sortOrder ?? 0,
397 + null,
398 + receiveInfoboxDismissed ?? false,
399 + showCombinedBalance ?? true,
400 + favoriteTokenAddress);
401 }
402
403 static String get tableName => 'walletInfo';
@@ -565,59 +563,59 @@ class WalletInfo {
563 StreamController<String> _yatLastUsedAddressController;
564
565 Map<String, dynamic> toJson() => {
568 - selfIdColumn: internalId,
569 - "id": id,
570 - "name": name,
571 - "type": type.index,
572 - "isRecovery": isRecovery ? 1 : 0,
573 - "restoreHeight": restoreHeight,
574 - "timestamp": timestamp,
575 - "dirPath": dirPath,
576 - "path": path,
577 - "address": address,
578 - "yatEid": yatEid,
579 - "yatLastUsedAddressRaw": yatLastUsedAddressRaw,
580 - "showIntroCakePayCard": showIntroCakePayCard == true ? 1 : 0, // SQL regression: null -> false
581 - "walletInfoDerivationInfoId": derivationInfoId,
582 - "hardwareWalletType": hardwareWalletType?.index,
583 - "parentAddress": parentAddress,
584 - "hashedWalletIdentifier": hashedWalletIdentifier,
585 - "isNonSeedWallet": isNonSeedWallet ? 1 : 0,
586 - "sortOrder": sortOrder,
587 - "addressPageType": addressPageType,
588 - "receiveInfoboxDismissed": receiveInfoboxDismissed ? 1 : 0,
589 - "showCombinedBalance": showCombinedBalance ? 1 : 0,
590 - "favoriteTokenAddress": favoriteTokenAddress
591 - };
566 + selfIdColumn: internalId,
567 + "id": id,
568 + "name": name,
569 + "type": type.index,
570 + "isRecovery": isRecovery ? 1 : 0,
571 + "restoreHeight": restoreHeight,
572 + "timestamp": timestamp,
573 + "dirPath": dirPath,
574 + "path": path,
575 + "address": address,
576 + "yatEid": yatEid,
577 + "yatLastUsedAddressRaw": yatLastUsedAddressRaw,
578 + "showIntroCakePayCard":
579 + showIntroCakePayCard == true ? 1 : 0, // SQL regression: null -> false
580 + "walletInfoDerivationInfoId": derivationInfoId,
581 + "hardwareWalletType": hardwareWalletType?.index,
582 + "parentAddress": parentAddress,
583 + "hashedWalletIdentifier": hashedWalletIdentifier,
584 + "isNonSeedWallet": isNonSeedWallet ? 1 : 0,
585 + "sortOrder": sortOrder,
586 + "addressPageType": addressPageType,
587 + "receiveInfoboxDismissed": receiveInfoboxDismissed ? 1 : 0,
588 + "showCombinedBalance": showCombinedBalance ? 1 : 0,
589 + "favoriteTokenAddress": favoriteTokenAddress
590 + };
591
592 factory WalletInfo.fromJson(Map<String, dynamic> json) {
593 return WalletInfo(
595 - json[selfIdColumn] as int,
596 - json['id'] as String,
597 - json['name'] as String,
598 - WalletType.values[json['type'] as int],
599 - (json['isRecovery'] as int) == 1,
600 - json['restoreHeight'] as int,
601 - json['timestamp'] as int,
602 - json['dirPath'] as String,
603 - json['path'] as String,
604 - json['address'] as String,
605 - json['yatEid'] as String?,
606 - json['yatLastUsedAddressRaw'] as String?,
607 - (json['showIntroCakePayCard'] as int) == 1,
608 - json['walletInfoDerivationInfoId'] as int,
609 - json['hardwareWalletType'] == null
610 - ? null
611 - : HardwareWalletType.values[json['hardwareWalletType'] as int],
612 - json['parentAddress'] as String?,
613 - json['hashedWalletIdentifier'] as String?,
614 - (json['isNonSeedWallet'] as int) == 1,
615 - json['sortOrder'] as int? ?? 0,
616 - json['addressPageType'] as String? ?? null,
617 - json['receiveInfoboxDismissed'] != 0,
618 - json["showCombinedBalance"] != 0,
619 - json["favoriteTokenAddress"] as String? ?? null
620 - );
594 + json[selfIdColumn] as int,
595 + json['id'] as String,
596 + json['name'] as String,
597 + WalletType.values[json['type'] as int],
598 + (json['isRecovery'] as int) == 1,
599 + json['restoreHeight'] as int,
600 + json['timestamp'] as int,
601 + json['dirPath'] as String,
602 + json['path'] as String,
603 + json['address'] as String,
604 + json['yatEid'] as String?,
605 + json['yatLastUsedAddressRaw'] as String?,
606 + (json['showIntroCakePayCard'] as int) == 1,
607 + json['walletInfoDerivationInfoId'] as int,
608 + json['hardwareWalletType'] == null
609 + ? null
610 + : HardwareWalletType.values[json['hardwareWalletType'] as int],
611 + json['parentAddress'] as String?,
612 + json['hashedWalletIdentifier'] as String?,
613 + (json['isNonSeedWallet'] as int) == 1,
614 + json['sortOrder'] as int? ?? 0,
615 + json['addressPageType'] as String? ?? null,
616 + json['receiveInfoboxDismissed'] != 0,
617 + json["showCombinedBalance"] != 0,
618 + json["favoriteTokenAddress"] as String? ?? null);
619 }
620
621 Future<int> save() async {
cw_core/lib/wallet_info_legacy.dart
+1 -1
@@ -201,7 +201,7 @@ class WalletInfo extends HiveObject {
201
202 // @HiveField(22)
203 String? parentAddress;
204 -
204 +
205 // @HiveField(23)
206 List<String>? hiddenAddresses;
207
cw_core/lib/wallet_info_legacy.part.dart
+5 -11
@@ -53,9 +53,7 @@ class DerivationInfoAdapter extends TypeAdapter<DerivationInfo> {
53 @override
54 bool operator ==(Object other) =>
55 identical(this, other) ||
56 - other is DerivationInfoAdapter &&
57 - runtimeType == other.runtimeType &&
58 - typeId == other.typeId;
56 + other is DerivationInfoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
57 }
58
59 class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
@@ -88,8 +86,8 @@ class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
86 fields[26] == null ? false : fields[26] as bool,
87 )
88 ..addresses = (fields[10] as Map?)?.cast<String, String>()
91 - ..addressInfos = (fields[14] as Map?)?.map((dynamic k, dynamic v) =>
92 - MapEntry(k as int, (v as List).cast<AddressInfo>()))
89 + ..addressInfos = (fields[14] as Map?)
90 + ?.map((dynamic k, dynamic v) => MapEntry(k as int, (v as List).cast<AddressInfo>()))
91 ..usedAddresses = (fields[15] as List?)?.cast<String>()
92 ..derivationType = fields[16] as newWi.DerivationType?
93 ..derivationPath = fields[17] as String?
@@ -163,9 +161,7 @@ class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
161 @override
162 bool operator ==(Object other) =>
163 identical(this, other) ||
166 - other is WalletInfoAdapter &&
167 - runtimeType == other.runtimeType &&
168 - typeId == other.typeId;
164 + other is WalletInfoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
165 }
166
167 class DerivationTypeAdapter extends TypeAdapter<newWi.DerivationType> {
@@ -217,9 +213,7 @@ class DerivationTypeAdapter extends TypeAdapter<newWi.DerivationType> {
213 @override
214 bool operator ==(Object other) =>
215 identical(this, other) ||
220 - other is DerivationTypeAdapter &&
221 - runtimeType == other.runtimeType &&
222 - typeId == other.typeId;
216 + other is DerivationTypeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
217 }
218
219 class HardwareWalletTypeAdapter extends TypeAdapter<newWi.HardwareWalletType> {
cw_core/lib/wallet_keys_file.dart
+8 -1
@@ -101,7 +101,14 @@ class WalletKeysData {
101 final String? scanSecret;
102 final String? spendPubkey;
103
104 - WalletKeysData({this.privateKey, this.mnemonic, this.altMnemonic, this.passphrase, this.xPub, this.scanSecret, this.spendPubkey});
104 + WalletKeysData(
105 + {this.privateKey,
106 + this.mnemonic,
107 + this.altMnemonic,
108 + this.passphrase,
109 + this.xPub,
110 + this.scanSecret,
111 + this.spendPubkey});
112
113 String toJSON() => jsonEncode({
114 "privateKey": privateKey,
cw_core/lib/wallet_type.dart
+13 -12
@@ -334,17 +334,18 @@ WalletType? _cryptoCurrencyToWalletType(CryptoCurrency type) {
334
335 WalletType? cryptoCurrencyOrTokenToWalletType(CryptoCurrency type) {
336 try {
337 - if(type.tag == CryptoCurrency.bnb.tag) {
338 - return _cryptoCurrencyToWalletType(CryptoCurrency.bnb);
339 - }
340 -
341 - if(type.tag != null && ![CryptoCurrency.btcln.tag, CryptoCurrency.bnb.tag].contains(type.tag)) {
342 - return _cryptoCurrencyToWalletType(CryptoCurrency.fromString(type.tag!));
343 - } else {
344 - return _cryptoCurrencyToWalletType(type);
337 + if (type.tag == CryptoCurrency.bnb.tag) {
338 + return _cryptoCurrencyToWalletType(CryptoCurrency.bnb);
339 + }
340 +
341 + if (type.tag != null &&
342 + ![CryptoCurrency.btcln.tag, CryptoCurrency.bnb.tag].contains(type.tag)) {
343 + return _cryptoCurrencyToWalletType(CryptoCurrency.fromString(type.tag!));
344 + } else {
345 + return _cryptoCurrencyToWalletType(type);
346 + }
347 + } catch (e) {
348 + printV(e);
349 + return null;
350 }
346 -} catch (e) {
347 - printV(e);
348 - return null;
349 -}
351 }
cw_core/lib/wallet_type.part.dart
+1 -3
@@ -130,7 +130,5 @@ class WalletTypeAdapter extends TypeAdapter<WalletType> {
130 @override
131 bool operator ==(Object other) =>
132 identical(this, other) ||
133 - other is WalletTypeAdapter &&
134 - runtimeType == other.runtimeType &&
135 - typeId == other.typeId;
133 + other is WalletTypeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
134 }
cw_core/lib/wownero_amount_format.dart
+1 -1
@@ -15,4 +15,4 @@ double wowneroAmountToDouble({required int amount}) =>
15 cryptoAmountToDouble(amount: amount, divider: wowneroAmountDivider);
16
17 int wowneroParseAmount({required String amount}) =>
18 - (double.parse(amount) * wowneroAmountDivider).round();
\ No newline at end of file
18 + (double.parse(amount) * wowneroAmountDivider).round();
cw_core/lib/zano_asset.part.dart
+1 -3
@@ -70,7 +70,5 @@ class ZanoAssetAdapter extends TypeAdapter<ZanoAsset> {
70 @override
71 bool operator ==(Object other) =>
72 identical(this, other) ||
73 - other is ZanoAssetAdapter &&
74 - runtimeType == other.runtimeType &&
75 - typeId == other.typeId;
73 + other is ZanoAssetAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
74 }
cw_core/test/amount/amount_sanitizer_test.dart
+5 -5
@@ -3,27 +3,27 @@ import 'package:flutter_test/flutter_test.dart';
3
4 void main() {
5 group('smartAmountSanitizer', () {
6 - test('sanitize decimal dot', (){
6 + test('sanitize decimal dot', () {
7 final amount = "1,000.00".sanitized();
8 expect(amount, "1000.00");
9 });
10
11 - test('sanitize decimal comma', (){
11 + test('sanitize decimal comma', () {
12 final amount = "1.000,00".sanitized();
13 expect(amount, "1000.00");
14 });
15
16 - test('general case', (){
16 + test('general case', () {
17 final amount = "1000.00".sanitized();
18 expect(amount, "1000.00");
19 });
20
21 - test('no decimals', (){
21 + test('no decimals', () {
22 final amount = "1,000".sanitized();
23 expect(amount, "1.000");
24 });
25
26 - test('no decimals', (){
26 + test('no decimals', () {
27 final amount = "1.000".sanitized();
28 expect(amount, "1.000");
29 });
cw_core/test/amount/money_test.dart
+2 -2
@@ -316,7 +316,7 @@ void main() {
316 });
317 });
318
319 - group("toStringWithPrecision", (){
319 + group("toStringWithPrecision", () {
320 test("with fractionalDigits and padded with zeros", () {
321 final money = Money.parse("1", CryptoCurrency.btc);
322 expect(money.amount, equals(BigInt.parse("100000000")));
@@ -332,7 +332,7 @@ void main() {
332 });
333 });
334
335 - group("toStringWithSymbol", (){
335 + group("toStringWithSymbol", () {
336 test("with fractionalDigits and padded with zeros", () {
337 final money = Money.parse("1", CryptoCurrency.btc);
338 expect(money.amount, equals(BigInt.parse("100000000")));
cw_core/test/crypto_amount_format.dart
+3 -3
@@ -35,7 +35,7 @@ void main() {
35 group('String.withLocalSeperator', () {
36 group('Locale en_US', () {
37 const locale = 'en_US';
38 -
38 +
39 test('should not have a grouping separator', () {
40 final input = '123.45';
41 final result = input.withLocalSeperator(locale);
@@ -57,10 +57,10 @@ void main() {
57 expect(result, equals('1,000,000.4567'));
58 });
59 });
60 -
60 +
61 group('Locale de_DE', () {
62 const locale = 'de_DE';
63 -
63 +
64 test('should not have a grouping separator', () {
65 final input = '123.45';
66 final result = input.withLocalSeperator(locale);
cw_core/test/format_fixed_test.dart
+4 -8
@@ -14,14 +14,12 @@ void main() {
14 group('formatFixed, different fractional digits and trimming zeros', () {
15 test(
16 'should format 1000001 into 1',
17 - () => expect(
18 - formatFixed(BigInt.parse("1000001"), 6, fractionalDigits: 5), '1'),
17 + () => expect(formatFixed(BigInt.parse("1000001"), 6, fractionalDigits: 5), '1'),
18 );
19
20 test(
21 'should format 1000000 into 1, fractionalDigits > decimals',
23 - () => expect(
24 - formatFixed(BigInt.parse("1000000"), 6, fractionalDigits: 12), '1'),
22 + () => expect(formatFixed(BigInt.parse("1000000"), 6, fractionalDigits: 12), '1'),
23 );
24
25 test(
@@ -45,8 +43,7 @@ void main() {
43 test(
44 'should format 1000001 into 1.00000',
45 () => expect(
48 - formatFixed(BigInt.parse("1000001"), 6,
49 - fractionalDigits: 5, trimZeros: false),
46 + formatFixed(BigInt.parse("1000001"), 6, fractionalDigits: 5, trimZeros: false),
47 '1.00000',
48 ),
49 );
@@ -54,8 +51,7 @@ void main() {
51 test(
52 'should format 1000000 into 1.000000',
53 () => expect(
57 - formatFixed(BigInt.parse("1000000"), 6,
58 - fractionalDigits: 12, trimZeros: false),
54 + formatFixed(BigInt.parse("1000000"), 6, fractionalDigits: 12, trimZeros: false),
55 '1.000000',
56 ),
57 );
cw_core/test/lnurl_test.dart
+18 -9
@@ -39,49 +39,58 @@ void main() {
39
40 group("isBolt11ZeroInvoice", () {
41 test("should identify a zero amount invoice", () {
42 - final invoice = "lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
42 + final invoice =
43 + "lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
44 expect(isBolt11ZeroInvoice(invoice), true);
45 });
46
47 test("should identify a non zero amount invoice", () {
47 - final invoice = "lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
48 + final invoice =
49 + "lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
50 expect(isBolt11ZeroInvoice(invoice), false);
51 });
52
53 test("should identify a zero amount prefixed invoice", () {
52 - final invoice = "lightning:lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
54 + final invoice =
55 + "lightning:lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
56 expect(isBolt11ZeroInvoice(invoice), true);
57 });
58
59 test("should identify a non zero amount prefixed invoice", () {
57 - final invoice = "lightning:lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
60 + final invoice =
61 + "lightning:lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
62 expect(isBolt11ZeroInvoice(invoice), false);
63 });
64 });
65
66 group("getBolt11Amount", () {
67 test("should identify a zero amount invoice", () {
64 - final invoice = "lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
68 + final invoice =
69 + "lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
70 expect(getBolt11Amount(invoice), null);
71 });
72
73 test("should get the amount 1 BTC encoded as bitcoin", () {
69 - final invoice = "lnbc11p5exaxspp5u6e6lx90rw2vqr2e5axt8ur3v98qnmqfsmh8r0l0mcm7ry70vyvsdqqcqzzsxqrrsssp5eqydmrufk39dwhuxzajwx4xyffn0mlcu3qa8vjwry6qev5gsepkq9qxpqysgqt0zldve9uxt3txjt8wp0gev52lquljgugy26nneue85pjwk5yak4hs2d8533tus07pq5ka6zrnd0ruaeepwres8p7ws5mx63xlwff5sqlxcy8a";
74 + final invoice =
75 + "lnbc11p5exaxspp5u6e6lx90rw2vqr2e5axt8ur3v98qnmqfsmh8r0l0mcm7ry70vyvsdqqcqzzsxqrrsssp5eqydmrufk39dwhuxzajwx4xyffn0mlcu3qa8vjwry6qev5gsepkq9qxpqysgqt0zldve9uxt3txjt8wp0gev52lquljgugy26nneue85pjwk5yak4hs2d8533tus07pq5ka6zrnd0ruaeepwres8p7ws5mx63xlwff5sqlxcy8a";
76 expect(getBolt11Amount(invoice), Money.fromInt(100000000, CryptoCurrency.btcln));
77 });
78
79 test("should get the amount 0,1 BTC encoded as millibitcoin", () {
74 - final invoice = "lnbc100m1p5exagmpp5n4c5tml3h8h7k4gthc9papkyeymceqqvcldkng4nvxwzj7nu9jnsdqqcqzzsxqrrsssp58kgzrh7y3pevantduc4yg33aa6r79ed6xgmhr0dy40zc8pxrz5ms9qxpqysgqcq27km3v3wcz6pntmsfnz259zy6tff0uwjz9kamdrvmxmdv09gp44mh0ygn7gweqf4zdev4x8e67p5kcvahethchdkkjexhtk7emuqcpasz0lp";
80 + final invoice =
81 + "lnbc100m1p5exagmpp5n4c5tml3h8h7k4gthc9papkyeymceqqvcldkng4nvxwzj7nu9jnsdqqcqzzsxqrrsssp58kgzrh7y3pevantduc4yg33aa6r79ed6xgmhr0dy40zc8pxrz5ms9qxpqysgqcq27km3v3wcz6pntmsfnz259zy6tff0uwjz9kamdrvmxmdv09gp44mh0ygn7gweqf4zdev4x8e67p5kcvahethchdkkjexhtk7emuqcpasz0lp";
82 expect(getBolt11Amount(invoice), Money.fromInt(10000000, CryptoCurrency.btcln));
83 });
84
85 test("should get the amount 1000 SATS encoded as microbitcoin", () {
79 - final invoice = "lnbc10u1p5exfgvpp5n3s9dsw9ddax5c3h8437ya7y4g582uyufyna626yr9vqdfjrhwzqdqqcqzzsxqrrsssp5mmkyp5h35fpaxm4063f3kc7d4nmgd4gd8fv8086wxd784m76kmpq9qxpqysgqye9r0vahpjy9l2je6vakxzk3cjnsyx76r29c4amkz4cmapq5tqt5l7rl0emkd003jjvz2d8jqrw6wc4cduvapuyeseh7a855l82wutcpeq30kg";
86 + final invoice =
87 + "lnbc10u1p5exfgvpp5n3s9dsw9ddax5c3h8437ya7y4g582uyufyna626yr9vqdfjrhwzqdqqcqzzsxqrrsssp5mmkyp5h35fpaxm4063f3kc7d4nmgd4gd8fv8086wxd784m76kmpq9qxpqysgqye9r0vahpjy9l2je6vakxzk3cjnsyx76r29c4amkz4cmapq5tqt5l7rl0emkd003jjvz2d8jqrw6wc4cduvapuyeseh7a855l82wutcpeq30kg";
88 expect(getBolt11Amount(invoice), Money.fromInt(1000, CryptoCurrency.btcln));
89 });
90
91 test("should get the amount 1 SAT encoded as nanobitcoin", () {
84 - final invoice = "lnbc10n1p5exazppp5szh273r6nzvwydzsdlg0ws0vhxwnc6nqtqt4sjt0vu6x6l8t5csqdqqcqzzsxqrrsssp5nkup6uht7xlfqaj8lxpe5kx0ejum9p4pvv3nlnndr9ykzge3393s9qxpqysgqufh05a7qs0ezeckvmh7tjkr9ngng96nq274twg20z45ysp7afpdrttm2ky73cpjwpjqsmtzzd79w6lyvszgmkanwn8mj0jcfunrwv3qprg3z3j";
92 + final invoice =
93 + "lnbc10n1p5exazppp5szh273r6nzvwydzsdlg0ws0vhxwnc6nqtqt4sjt0vu6x6l8t5csqdqqcqzzsxqrrsssp5nkup6uht7xlfqaj8lxpe5kx0ejum9p4pvv3nlnndr9ykzge3393s9qxpqysgqufh05a7qs0ezeckvmh7tjkr9ngng96nq274twg20z45ysp7afpdrttm2ky73cpjwpjqsmtzzd79w6lyvszgmkanwn8mj0jcfunrwv3qprg3z3j";
94 expect(getBolt11Amount(invoice), Money.fromInt(1, CryptoCurrency.btcln));
95 });
96 });
cw_custom_lints/lib/http_force_proxy/http_force_proxy_rule.dart
+1 -2
@@ -51,8 +51,7 @@ class _Visitor extends SimpleAstVisitor<void> {
51
52 if (uriString.startsWith("package:http")) {
53 final prefixNode = node.prefix;
54 - if (prefixNode != null &&
55 - prefixNode.name == "very_insecure_http_do_not_use") {
54 + if (prefixNode != null && prefixNode.name == "very_insecure_http_do_not_use") {
55 return;
56 }
57
cw_custom_lints/lib/print_verbose/print_verbose_fix.dart
+1 -2
@@ -17,8 +17,7 @@ class ReplaceWithPrintV extends ResolvedCorrectionProducer {
17 );
18
19 @override
20 - CorrectionApplicability get applicability =>
21 - CorrectionApplicability.singleLocation;
20 + CorrectionApplicability get applicability => CorrectionApplicability.singleLocation;
21
22 @override
23 FixKind get fixKind => _fixKind;
cw_dogecoin/lib/cw_dogecoin.dart
-1
@@ -3,4 +3,3 @@ export 'src/dogecoin_wallet_addresses.dart';
3 export 'src/dogecoin_wallet_creation_credentials.dart';
4 export 'src/dogecoin_wallet_service.dart';
5 export 'src/dogecoin_transaction_priority.dart';
6 -
cw_dogecoin/lib/src/dogecoin_transaction_priority.dart
+3 -4
@@ -7,11 +7,11 @@ class DogecoinTransactionPriority extends BitcoinTransactionPriority {
7
8 static const List<DogecoinTransactionPriority> all = [fast, medium, slow];
9 static const DogecoinTransactionPriority slow =
10 - DogecoinTransactionPriority(title: 'Slow', raw: 0);
10 + DogecoinTransactionPriority(title: 'Slow', raw: 0);
11 static const DogecoinTransactionPriority medium =
12 - DogecoinTransactionPriority(title: 'Medium', raw: 1);
12 + DogecoinTransactionPriority(title: 'Medium', raw: 1);
13 static const DogecoinTransactionPriority fast =
14 - DogecoinTransactionPriority(title: 'Fast', raw: 2);
14 + DogecoinTransactionPriority(title: 'Fast', raw: 2);
15
16 static DogecoinTransactionPriority deserialize({required int raw}) {
17 switch (raw) {
@@ -53,4 +53,3 @@ class DogecoinTransactionPriority extends BitcoinTransactionPriority {
53 return label;
54 }
55 }
56 -
cw_dogecoin/lib/src/dogecoin_wallet.dart
+1 -2
@@ -75,14 +75,13 @@ abstract class DogeCoinWalletBase extends ElectrumWallet with Store {
75
76 @override
77 int feeAmountForPriority(TransactionPriority priority, int inputsCount, int outputsCount,
78 - {int? size}) =>
78 + {int? size}) =>
79 feeRate(priority) * (size ?? estimatedDogeCoinTransactionSize(inputsCount, outputsCount));
80
81 @override
82 int feeAmountWithFeeRate(int feeRate, int inputsCount, int outputsCount, {int? size}) =>
83 feeRate * (size ?? estimatedDogeCoinTransactionSize(inputsCount, outputsCount));
84
85 -
85 static Future<DogeCoinWallet> create(
86 {required String mnemonic,
87 required String password,
cw_dogecoin/lib/src/dogecoin_wallet_addresses.dart
+3 -6
@@ -8,11 +8,9 @@ import 'package:mobx/mobx.dart';
8
9 part 'dogecoin_wallet_addresses.g.dart';
10
11 -class DogeCoinWalletAddresses = DogeCoinWalletAddressesBase
12 - with _$DogeCoinWalletAddresses;
11 +class DogeCoinWalletAddresses = DogeCoinWalletAddressesBase with _$DogeCoinWalletAddresses;
12
14 -abstract class DogeCoinWalletAddressesBase extends ElectrumWalletAddresses
15 - with Store {
13 +abstract class DogeCoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
14 DogeCoinWalletAddressesBase(
15 WalletInfo walletInfo, {
16 required super.mainHdByType,
@@ -36,6 +34,5 @@ abstract class DogeCoinWalletAddressesBase extends ElectrumWalletAddresses
34 generateP2PKHAddress(hd: hd, index: index, network: network);
35
36 @override
39 - PaymentURI getPaymentUri(String amount) =>
40 - DogeURI(address: address, amount: amount);
37 + PaymentURI getPaymentUri(String amount) => DogeURI(address: address, amount: amount);
38 }
cw_dogecoin/test/cw_dogecoin_test.dart
+1 -2
@@ -3,6 +3,5 @@ import 'package:flutter_test/flutter_test.dart';
3 import 'package:cw_dogecoin/cw_dogecoin.dart';
4
5 void main() {
6 - test('adds one to input values', () {
7 - });
6 + test('adds one to input values', () {});
7 }
cw_evm/lib/clients/arbitrum_client.dart
-1
@@ -43,4 +43,3 @@ class ArbitrumClient extends EVMChainClient {
43 @override
44 int get chainId => 42161;
45 }
46 -
cw_evm/lib/clients/base_client.dart
-1
@@ -43,4 +43,3 @@ class BaseClient extends EVMChainClient {
43 @override
44 int get chainId => 8453;
45 }
46 -
cw_evm/lib/clients/bsc_client.dart
-1
@@ -44,4 +44,3 @@ class BSCClient extends EVMChainClient {
44 @override
45 int get chainId => 56;
46 }
47 -
cw_evm/lib/clients/ethereum_client.dart
-1
@@ -10,4 +10,3 @@ class EthereumClient extends EVMChainClient {
10 Uint8List prepareSignedTransactionForSending(Uint8List signedTransaction) =>
11 prependTransactionType(0x02, signedTransaction);
12 }
13 -
cw_evm/lib/clients/evm_chain_client.dart
+9 -6
@@ -145,7 +145,9 @@ class EVMChainClient {
145
146 final jsonResponse = json.decode(response.body) as Map<String, dynamic>;
147
148 - if (response.statusCode >= 200 && response.statusCode < 300 && jsonResponse['status'] != 0 &&
148 + if (response.statusCode >= 200 &&
149 + response.statusCode < 300 &&
150 + jsonResponse['status'] != 0 &&
151 jsonResponse['result'] is List) {
152 final symbol = EVMChainUtils.getFeeCurrency(chainId);
153
@@ -520,9 +522,11 @@ class EVMChainClient {
522 */
523 }
524
523 - Future<EVMChainERC20Balance> fetchERC20Balances(EthereumAddress userAddress, Erc20Token token) async {
525 + Future<EVMChainERC20Balance> fetchERC20Balances(
526 + EthereumAddress userAddress, Erc20Token token) async {
527 try {
525 - final erc20 = ERC20(address: EthereumAddress.fromHex(token.contractAddress), client: _client!);
528 + final erc20 =
529 + ERC20(address: EthereumAddress.fromHex(token.contractAddress), client: _client!);
530 final balance = await erc20.balanceOf(userAddress);
531
532 return EVMChainERC20Balance(Money(balance, token));
@@ -659,9 +663,8 @@ class EVMChainClient {
663 final tokenData = item;
664
665 final nativeRaw = tokenData['native_token'];
662 - final nativeToken = nativeRaw is bool
663 - ? nativeRaw
664 - : (nativeRaw?.toString().toLowerCase() == 'true');
666 + final nativeToken =
667 + nativeRaw is bool ? nativeRaw : (nativeRaw?.toString().toLowerCase() == 'true');
668 if (nativeToken) continue;
669
670 final balanceStr = tokenData['balance'] as String? ?? '0';
cw_evm/lib/clients/polygon_client.dart
-1
@@ -43,4 +43,3 @@ class PolygonClient extends EVMChainClient {
43 @override
44 int get chainId => 137;
45 }
46 -
cw_evm/lib/contract/erc20.dart
+22 -25
@@ -21,10 +21,10 @@ class ERC20 extends web3.GeneratedContract {
21 /// set, the function will be evaluated in the specified block. By default, the
22 /// latest on-chain block will be used.
23 Future<BigInt> allowance(
24 - web3.EthereumAddress owner,
25 - web3.EthereumAddress spender, {
26 - web3.BlockNum? atBlock,
27 - }) async {
24 + web3.EthereumAddress owner,
25 + web3.EthereumAddress spender, {
26 + web3.BlockNum? atBlock,
27 + }) async {
28 final function = self.abi.functions[0];
29 assert(checkSignature(function, 'dd62ed3e'));
30 final params = [owner, spender];
@@ -38,11 +38,11 @@ class ERC20 extends web3.GeneratedContract {
38 /// like the gas price, nonce and max gas. The `data` and `to` fields will be
39 /// set by the contract.
40 Future<Uint8List> approve(
41 - web3.EthereumAddress spender,
42 - BigInt amount, {
43 - required web3.Credentials credentials,
44 - web3.Transaction? transaction,
45 - }) async {
41 + web3.EthereumAddress spender,
42 + BigInt amount, {
43 + required web3.Credentials credentials,
44 + web3.Transaction? transaction,
45 + }) async {
46 final function = self.abi.functions[1];
47 assert(checkSignature(function, '095ea7b3'));
48 final params = [spender, amount];
@@ -55,9 +55,9 @@ class ERC20 extends web3.GeneratedContract {
55 /// set, the function will be evaluated in the specified block. By default, the
56 /// latest on-chain block will be used.
57 Future<BigInt> balanceOf(
58 - web3.EthereumAddress account, {
59 - web3.BlockNum? atBlock,
60 - }) async {
58 + web3.EthereumAddress account, {
59 + web3.BlockNum? atBlock,
60 + }) async {
61 final function = self.abi.functions[2];
62 assert(checkSignature(function, '70a08231'));
63 final params = [account];
@@ -123,11 +123,11 @@ class ERC20 extends web3.GeneratedContract {
123 /// like the gas price, nonce and max gas. The `data` and `to` fields will be
124 /// set by the contract.
125 Future<Uint8List> transfer(
126 - web3.EthereumAddress recipient,
127 - BigInt amount, {
128 - required web3.Credentials credentials,
129 - web3.Transaction? transaction,
130 - }) async {
126 + web3.EthereumAddress recipient,
127 + BigInt amount, {
128 + required web3.Credentials credentials,
129 + web3.Transaction? transaction,
130 + }) async {
131 final function = self.abi.functions[7];
132 assert(checkSignature(function, 'a9059cbb'));
133 final params = [recipient, amount];
@@ -139,10 +139,9 @@ class ERC20 extends web3.GeneratedContract {
139 /// The optional [transaction] parameter can be used to override parameters
140 /// like the gas price, nonce and max gas. The `data` and `to` fields will be
141 /// set by the contract.
142 - Future<Uint8List> transferFrom(web3.EthereumAddress sender,
143 - web3.EthereumAddress recipient, BigInt amount,
144 - {required web3.Credentials credentials,
145 - web3.Transaction? transaction}) async {
142 + Future<Uint8List> transferFrom(
143 + web3.EthereumAddress sender, web3.EthereumAddress recipient, BigInt amount,
144 + {required web3.Credentials credentials, web3.Transaction? transaction}) async {
145 final function = self.abi.functions[8];
146 assert(checkSignature(function, '23b872dd'));
147 final params = [sender, recipient, amount];
@@ -150,8 +149,7 @@ class ERC20 extends web3.GeneratedContract {
149 }
150
151 /// Returns a live stream of all Approval events emitted by this contract.
153 - Stream<Approval> approvalEvents(
154 - {web3.BlockNum? fromBlock, web3.BlockNum? toBlock}) {
152 + Stream<Approval> approvalEvents({web3.BlockNum? fromBlock, web3.BlockNum? toBlock}) {
153 final event = self.event('Approval');
154 final filter = web3.FilterOptions.events(
155 contract: self, event: event, fromBlock: fromBlock, toBlock: toBlock);
@@ -162,8 +160,7 @@ class ERC20 extends web3.GeneratedContract {
160 }
161
162 /// Returns a live stream of all Transfer events emitted by this contract.
165 - Stream<Transfer> transferEvents(
166 - {web3.BlockNum? fromBlock, web3.BlockNum? toBlock}) {
163 + Stream<Transfer> transferEvents({web3.BlockNum? fromBlock, web3.BlockNum? toBlock}) {
164 final event = self.event('Transfer');
165 final filter = web3.FilterOptions.events(
166 contract: self, event: event, fromBlock: fromBlock, toBlock: toBlock);
cw_evm/lib/deuro/deuro_savings.dart
+10 -7
@@ -169,7 +169,8 @@ class DEuro {
169 contractAddress: savings.self.address.hexEip55,
170 receivingAddressHex: savings.self.address.hexEip55,
171 priority: priority,
172 - data: savings.self.abi.functions[24].encodeCall([_address, amount, hexToBytes(frontendCode)]),
172 + data:
173 + savings.self.abi.functions[24].encodeCall([_address, amount, hexToBytes(frontendCode)]),
174 );
175
176 sendTransaction() => _wallet.getWeb3Client()!.sendRawTransaction(signedTransaction);
@@ -193,7 +194,8 @@ class DEuro {
194 try {
195 await _checkEthBalanceForGasFees(priority);
196
196 - final signedTransaction = await _savings.refreshBalance((owner: _address),
197 + final signedTransaction = await _savings.refreshBalance(
198 + (owner: _address),
199 credentials: _wallet.evmChainPrivateKey,
200 );
201
@@ -228,10 +230,12 @@ class DEuro {
230 await _checkEthBalanceForGasFees(priority);
231
232 return (await _wallet.createApprovalTransaction(
231 - Money(BigInt.parse(
232 - 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
233 - radix: 16,
234 - ), CryptoCurrency.deuro),
233 + Money(
234 + BigInt.parse(
235 + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
236 + radix: 16,
237 + ),
238 + CryptoCurrency.deuro),
239 _savings.self.address.hexEip55,
240 priority,
241 )) as PendingEVMChainTransaction;
@@ -244,4 +248,3 @@ class DEuro {
248 }
249 }
250 }
247 -
cw_evm/lib/deuro/deuro_savings_contract.dart
+3 -3
@@ -352,9 +352,9 @@ class Savings extends _i1.GeneratedContract {
352 /// set, the function will be evaluated in the specified block. By default, the
353 /// latest on-chain block will be used.
354 Future<SavingsData> savings({
355 - required _i1.EthereumAddress accountOwner,
356 - _i1.BlockNum? atBlock,
357 - }) async {
355 + required _i1.EthereumAddress accountOwner,
356 + _i1.BlockNum? atBlock,
357 + }) async {
358 final function = self.abi.functions[21];
359 assert(checkSignature(function, '1f7cdd5f'));
360 final params = [accountOwner];
cw_evm/lib/deuro/deuro_savings_gateway_contract.dart
+51 -59
@@ -15,13 +15,13 @@ class SavingsGateway extends _i1.GeneratedContract {
15 required _i1.Web3Client client,
16 int? chainId,
17 }) : super(
18 - _i1.DeployedContract(
19 - _contractAbi,
20 - address,
21 - ),
22 - client,
23 - chainId,
24 - );
18 + _i1.DeployedContract(
19 + _contractAbi,
20 + address,
21 + ),
22 + client,
23 + chainId,
24 + );
25
26 /// The optional [atBlock] parameter can be used to view historical data. When
27 /// set, the function will be evaluated in the specified block. By default, the
@@ -42,9 +42,9 @@ class SavingsGateway extends _i1.GeneratedContract {
42 /// set, the function will be evaluated in the specified block. By default, the
43 /// latest on-chain block will be used.
44 Future<BigInt> accruedInterest({
45 - required _i1.EthereumAddress accountOwner,
46 - _i1.BlockNum? atBlock,
47 - }) async {
45 + required _i1.EthereumAddress accountOwner,
46 + _i1.BlockNum? atBlock,
47 + }) async {
48 final function = self.abi.functions[2];
49 assert(checkSignature(function, '77267ec3'));
50 final params = [accountOwner];
@@ -60,9 +60,9 @@ class SavingsGateway extends _i1.GeneratedContract {
60 /// set, the function will be evaluated in the specified block. By default, the
61 /// latest on-chain block will be used.
62 Future<BigInt> accruedInterest$2(
63 - ({_i1.EthereumAddress accountOwner, BigInt timestamp}) args, {
64 - _i1.BlockNum? atBlock,
65 - }) async {
63 + ({_i1.EthereumAddress accountOwner, BigInt timestamp}) args, {
64 + _i1.BlockNum? atBlock,
65 + }) async {
66 final function = self.abi.functions[3];
67 assert(checkSignature(function, 'a696399d'));
68 final params = [
@@ -81,10 +81,10 @@ class SavingsGateway extends _i1.GeneratedContract {
81 /// like the gas price, nonce and max gas. The `data` and `to` fields will be
82 /// set by the contract.
83 Future<String> adjust(
84 - ({BigInt targetAmount, _i2.Uint8List frontendCode}) args, {
85 - required _i1.Credentials credentials,
86 - _i1.Transaction? transaction,
87 - }) async {
84 + ({BigInt targetAmount, _i2.Uint8List frontendCode}) args, {
85 + required _i1.Credentials credentials,
86 + _i1.Transaction? transaction,
87 + }) async {
88 final function = self.abi.functions[4];
89 assert(checkSignature(function, '753ef93c'));
90 final params = [
@@ -103,9 +103,9 @@ class SavingsGateway extends _i1.GeneratedContract {
103 /// set, the function will be evaluated in the specified block. By default, the
104 /// latest on-chain block will be used.
105 Future<BigInt> calculateInterest(
106 - ({dynamic account, BigInt ticks}) args, {
107 - _i1.BlockNum? atBlock,
108 - }) async {
106 + ({dynamic account, BigInt ticks}) args, {
107 + _i1.BlockNum? atBlock,
108 + }) async {
109 final function = self.abi.functions[7];
110 assert(checkSignature(function, '7915ce20'));
111 final params = [
@@ -214,10 +214,10 @@ class SavingsGateway extends _i1.GeneratedContract {
214 /// like the gas price, nonce and max gas. The `data` and `to` fields will be
215 /// set by the contract.
216 Future<_i2.Uint8List> refreshBalance(
217 - ({_i1.EthereumAddress owner}) args, {
218 - required _i1.Credentials credentials,
219 - _i1.Transaction? transaction,
220 - }) async {
217 + ({_i1.EthereumAddress owner}) args, {
218 + required _i1.Credentials credentials,
219 + _i1.Transaction? transaction,
220 + }) async {
221 final function = self.abi.functions[15];
222 assert(checkSignature(function, 'b77cd1c7'));
223 final params = [args.owner];
@@ -251,10 +251,10 @@ class SavingsGateway extends _i1.GeneratedContract {
251 /// like the gas price, nonce and max gas. The `data` and `to` fields will be
252 /// set by the contract.
253 Future<_i2.Uint8List> save(
254 - ({BigInt amount, _i2.Uint8List frontendCode}) args, {
255 - required _i1.Credentials credentials,
256 - _i1.Transaction? transaction,
257 - }) async {
254 + ({BigInt amount, _i2.Uint8List frontendCode}) args, {
255 + required _i1.Credentials credentials,
256 + _i1.Transaction? transaction,
257 + }) async {
258 final function = self.abi.functions[17];
259 assert(checkSignature(function, '9e2363dc'));
260 final params = [
@@ -273,14 +273,10 @@ class SavingsGateway extends _i1.GeneratedContract {
273 /// like the gas price, nonce and max gas. The `data` and `to` fields will be
274 /// set by the contract.
275 Future<_i2.Uint8List> saveTo(
276 - ({
277 - _i1.EthereumAddress owner,
278 - BigInt amount,
279 - _i2.Uint8List frontendCode
280 - }) args, {
281 - required _i1.Credentials credentials,
282 - _i1.Transaction? transaction,
283 - }) async {
276 + ({_i1.EthereumAddress owner, BigInt amount, _i2.Uint8List frontendCode}) args, {
277 + required _i1.Credentials credentials,
278 + _i1.Transaction? transaction,
279 + }) async {
280 final function = self.abi.functions[19];
281 assert(checkSignature(function, 'cbcf9676'));
282 final params = [
@@ -300,9 +296,9 @@ class SavingsGateway extends _i1.GeneratedContract {
296 /// set, the function will be evaluated in the specified block. By default, the
297 /// latest on-chain block will be used.
298 Future<Savings> savings({
303 - required _i1.EthereumAddress accountOwner,
304 - _i1.BlockNum? atBlock,
305 - }) async {
299 + required _i1.EthereumAddress accountOwner,
300 + _i1.BlockNum? atBlock,
301 + }) async {
302 final function = self.abi.functions[21];
303 assert(checkSignature(function, '1f7cdd5f'));
304 final params = [accountOwner];
@@ -318,11 +314,7 @@ class SavingsGateway extends _i1.GeneratedContract {
314 /// like the gas price, nonce and max gas. The `data` and `to` fields will be
315 /// set by the contract.
316 Future<_i2.Uint8List> withdraw(
321 - ({
322 - _i1.EthereumAddress target,
323 - BigInt amount,
324 - _i2.Uint8List frontendCode
325 - }) args, {
317 + ({_i1.EthereumAddress target, BigInt amount, _i2.Uint8List frontendCode}) args, {
318 required _i1.Credentials credentials,
319 _i1.Transaction? transaction,
320 }) async {
@@ -474,9 +466,9 @@ class Savings {
466
467 class InterestCollected {
468 InterestCollected(
477 - List<dynamic> response,
478 - this.event,
479 - ) : account = (response[0] as _i1.EthereumAddress),
469 + List<dynamic> response,
470 + this.event,
471 + ) : account = (response[0] as _i1.EthereumAddress),
472 interest = (response[1] as BigInt);
473
474 final _i1.EthereumAddress account;
@@ -488,9 +480,9 @@ class InterestCollected {
480
481 class RateChanged {
482 RateChanged(
491 - List<dynamic> response,
492 - this.event,
493 - ) : newRate = (response[0] as BigInt);
483 + List<dynamic> response,
484 + this.event,
485 + ) : newRate = (response[0] as BigInt);
486
487 final BigInt newRate;
488
@@ -499,9 +491,9 @@ class RateChanged {
491
492 class RateProposed {
493 RateProposed(
502 - List<dynamic> response,
503 - this.event,
504 - ) : who = (response[0] as _i1.EthereumAddress),
494 + List<dynamic> response,
495 + this.event,
496 + ) : who = (response[0] as _i1.EthereumAddress),
497 nextRate = (response[1] as BigInt),
498 nextChange = (response[2] as BigInt);
499
@@ -516,9 +508,9 @@ class RateProposed {
508
509 class Saved {
510 Saved(
519 - List<dynamic> response,
520 - this.event,
521 - ) : account = (response[0] as _i1.EthereumAddress),
511 + List<dynamic> response,
512 + this.event,
513 + ) : account = (response[0] as _i1.EthereumAddress),
514 amount = (response[1] as BigInt);
515
516 final _i1.EthereumAddress account;
@@ -530,9 +522,9 @@ class Saved {
522
523 class Withdrawn {
524 Withdrawn(
533 - List<dynamic> response,
534 - this.event,
535 - ) : account = (response[0] as _i1.EthereumAddress),
525 + List<dynamic> response,
526 + this.event,
527 + ) : account = (response[0] as _i1.EthereumAddress),
528 amount = (response[1] as BigInt);
529
530 final _i1.EthereumAddress account;
cw_evm/lib/evm_chain_exceptions.dart
+6 -7
@@ -12,15 +12,14 @@ class EVMChainTransactionCreationException implements Exception {
12 String toString() => exceptionMessage;
13 }
14
15 -
15 class EVMChainTransactionFeesException implements Exception {
16 final String exceptionMessage;
17
19 - EVMChainTransactionFeesException(String message)
20 - : exceptionMessage = message;
18 + EVMChainTransactionFeesException(String message) : exceptionMessage = message;
19
20 EVMChainTransactionFeesException.fromCurrency(String currency)
23 - : exceptionMessage = 'Transaction failed due to insufficient $currency balance to cover the fees.';
21 + : exceptionMessage =
22 + 'Transaction failed due to insufficient $currency balance to cover the fees.';
23
24 @override
25 String toString() => exceptionMessage;
@@ -39,15 +38,15 @@ class InsufficientGasFeeException implements Exception {
38 static String _buildMessage(BigInt? requiredGasFee, BigInt? currentBalance) {
39 const baseMessage = 'Insufficient ETH for gas fees.';
40 const addEthMessage = ' Please add ETH to your wallet to cover transaction fees.';
42 -
41 +
42 if (requiredGasFee != null) {
43 final requiredEth = (requiredGasFee / BigInt.from(10).pow(18)).toStringAsFixed(8);
45 - final balanceInfo = currentBalance != null
44 + final balanceInfo = currentBalance != null
45 ? ', Available: ${(currentBalance / BigInt.from(10).pow(18)).toStringAsFixed(8)} ETH'
46 : '';
47 return '$baseMessage Required: ~$requiredEth ETH$balanceInfo.$addEthMessage';
48 }
50 -
49 +
50 return '$baseMessage$addEthMessage';
51 }
52
cw_evm/lib/evm_chain_registry.dart
+1 -2
@@ -233,6 +233,5 @@ class EvmChainRegistry {
233
234 List<ChainConfig> getAllChains() => _chains.values.toList();
235
236 - List<WalletType> getRegisteredWalletTypes() =>
237 - _walletTypeToChainId.keys.toList();
236 + List<WalletType> getRegisteredWalletTypes() => _walletTypeToChainId.keys.toList();
237 }
cw_evm/lib/evm_chain_transaction_model.dart
+2 -1
@@ -35,7 +35,8 @@ class EVMChainTransactionModel {
35 this.evmSignatureName,
36 });
37
38 - factory EVMChainTransactionModel.fromJson(Map<String, dynamic> json, String defaultSymbol, int chainId) =>
38 + factory EVMChainTransactionModel.fromJson(
39 + Map<String, dynamic> json, String defaultSymbol, int chainId) =>
40 EVMChainTransactionModel(
41 date: DateTime.fromMillisecondsSinceEpoch(int.parse(json["timeStamp"]) * 1000),
42 hash: json["hash"] ?? "",
cw_evm/lib/evm_chain_wallet.dart
+4 -11
@@ -561,8 +561,7 @@ abstract class EVMChainWalletBase
561 'distribution',
562 ];
563
564 - static final _suspiciousWordPattern =
565 - RegExp(r'\b(bot|claim|reward)\b', caseSensitive: false);
564 + static final _suspiciousWordPattern = RegExp(r'\b(bot|claim|reward)\b', caseSensitive: false);
565
566 static const _knownNonEvmNativeSymbols = {
567 'ICP',
@@ -630,8 +629,7 @@ abstract class EVMChainWalletBase
629 final prefs = await sharedPrefs.future;
630 if (prefs.getBool(_scamCheckDoneKey) == true) return;
631
633 - final whitelistLower =
634 - getDefaultTokenContractAddresses.map((a) => a.toLowerCase()).toSet();
632 + final whitelistLower = getDefaultTokenContractAddresses.map((a) => a.toLowerCase()).toSet();
633 final defaultSymbolsUpper =
634 EVMChainDefaultTokens.getDefaultTokenSymbols(selectedChainId).toSet();
635
@@ -1316,16 +1314,12 @@ abstract class EVMChainWalletBase
1314 } else if (newTxInfo.direction == TransactionDirection.incoming &&
1315 existingTxInfo.direction == TransactionDirection.outgoing) {
1316 result[transactionModel.hash] = newTxInfo;
1319 - }
1320 -
1321 - else if (newTxInfo.direction == TransactionDirection.outgoing &&
1317 + } else if (newTxInfo.direction == TransactionDirection.outgoing &&
1318 existingTxInfo.direction == TransactionDirection.outgoing &&
1319 _hasEvmTokenContractAddress(newTxInfo) &&
1320 !_hasEvmTokenContractAddress(existingTxInfo)) {
1321 result[transactionModel.hash] = newTxInfo;
1326 - }
1327 -
1328 - else if (existingTxInfo.isPending) {
1322 + } else if (existingTxInfo.isPending) {
1323 result[transactionModel.hash] = newTxInfo;
1324 }
1325 }
@@ -1333,7 +1327,6 @@ abstract class EVMChainWalletBase
1327 return result;
1328 }
1329
1336 -
1330 bool _hasEvmTokenContractAddress(EVMChainTransactionInfo info) {
1331 final c = info.contractAddress;
1332 return c != null && c.isNotEmpty;
cw_evm/lib/evm_chain_wallet_addresses.dart
-1
@@ -23,7 +23,6 @@ abstract class EVMChainWalletAddressesBase extends WalletAddresses with Store {
23
24 final int _selectedChainId;
25
26 -
26 @override
27 Future<void> init() async {
28 address = walletInfo.address;
cw_evm/lib/evm_erc20_balance.dart
+1 -1
@@ -7,7 +7,7 @@ import "package:cw_core/currency.dart";
7 class EVMChainERC20Balance extends Balance {
8 EVMChainERC20Balance(Money balance) : super(balance, Money.zero(balance.currency));
9
10 - String toJSON() => json.encode({ "balanceInWei": available.amount.toString() });
10 + String toJSON() => json.encode({"balanceInWei": available.amount.toString()});
11
12 static EVMChainERC20Balance? fromJSON(String? jsonSource, Currency currency) {
13 if (jsonSource == null) return null;
cw_evm/lib/hardware/evm_chain_bitbox_service.dart
+2 -3
@@ -11,9 +11,8 @@ class EVMChainBitboxService extends HardwareWalletService {
11 final int chainId;
12
13 @override
14 - Future<List<HardwareAccountData>> getAvailableAccounts(
15 - {int index = 0, int limit = 5}) async {
16 - final accounts = <HardwareAccountData>[];
14 + Future<List<HardwareAccountData>> getAvailableAccounts({int index = 0, int limit = 5}) async {
15 + final accounts = <HardwareAccountData>[];
16 final indexRange = List.generate(limit, (i) => i + index);
17
18 for (final i in indexRange) {
cw_evm/lib/hardware/evm_chain_ledger_credentials.dart
+11 -17
@@ -1,8 +1,7 @@
1 import 'dart:async';
2 import 'dart:typed_data';
3
4 -import 'package:cw_core/hardware/device_not_connected_exception.dart'
5 - as exception;
4 +import 'package:cw_core/hardware/device_not_connected_exception.dart' as exception;
5 import 'package:cw_core/utils/print_verbose.dart';
6 import 'package:ledger_ethereum/ledger_ethereum.dart';
7 import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
@@ -19,15 +18,13 @@ class EvmLedgerCredentials extends CredentialsWithKnownAddress {
18 @override
19 EthereumAddress get address => EthereumAddress.fromHex(_address);
20
22 - Future<void> setLedgerConnection(LedgerConnection connection,
23 - [String? derivationPath]) async {
24 - ethereumLedgerApp = EthereumLedgerApp(connection,
25 - derivationPath: derivationPath ?? "m/44'/60'/0'/0/0");
21 + Future<void> setLedgerConnection(LedgerConnection connection, [String? derivationPath]) async {
22 + ethereumLedgerApp =
23 + EthereumLedgerApp(connection, derivationPath: derivationPath ?? "m/44'/60'/0'/0/0");
24 }
25
26 @override
29 - MsgSignature signToEcSignature(Uint8List payload,
30 - {int? chainId, bool isEIP1559 = false}) =>
27 + MsgSignature signToEcSignature(Uint8List payload, {int? chainId, bool isEIP1559 = false}) =>
28 throw UnimplementedError("EvmLedgerCredentials.signToEcSignature");
29
30 @override
@@ -65,13 +62,11 @@ class EvmLedgerCredentials extends CredentialsWithKnownAddress {
62 chainIdV = chainId != null ? (parity + (chainId * 2 + 35)) : parity;
63 }
64
68 - return MsgSignature(
69 - BigInt.parse(r, radix: 16), BigInt.parse(s, radix: 16), chainIdV);
65 + return MsgSignature(BigInt.parse(r, radix: 16), BigInt.parse(s, radix: 16), chainIdV);
66 }
67
68 @override
73 - Future<Uint8List> signPersonalMessage(Uint8List payload,
74 - {int? chainId}) async {
69 + Future<Uint8List> signPersonalMessage(Uint8List payload, {int? chainId}) async {
70 if (isNotConnected) throw exception.DeviceNotConnectedException();
71
72 final sig = await ethereumLedgerApp!.signMessage(payload);
@@ -88,11 +83,9 @@ class EvmLedgerCredentials extends CredentialsWithKnownAddress {
83
84 @override
85 Uint8List signPersonalMessageToUint8List(Uint8List payload, {int? chainId}) =>
91 - throw UnimplementedError(
92 - "EvmLedgerCredentials.signPersonalMessageToUint8List");
86 + throw UnimplementedError("EvmLedgerCredentials.signPersonalMessageToUint8List");
87
94 - Future<void> provideERC20Info(
95 - String erc20ContractAddress, int chainId) async {
88 + Future<void> provideERC20Info(String erc20ContractAddress, int chainId) async {
89 if (isNotConnected) throw exception.DeviceNotConnectedException();
90
91 try {
@@ -105,5 +98,6 @@ class EvmLedgerCredentials extends CredentialsWithKnownAddress {
98 }
99 }
100
108 - bool get isNotConnected => ethereumLedgerApp == null || ethereumLedgerApp!.connection.isDisconnected;
101 + bool get isNotConnected =>
102 + ethereumLedgerApp == null || ethereumLedgerApp!.connection.isDisconnected;
103 }
cw_evm/lib/hardware/evm_chain_ledger_service.dart
+2 -4
@@ -11,8 +11,7 @@ class EVMChainLedgerService extends HardwareWalletService {
11 final LedgerConnection ledgerConnection;
12
13 @override
14 - Future<List<HardwareAccountData>> getAvailableAccounts(
15 - {int index = 0, int limit = 5}) async {
14 + Future<List<HardwareAccountData>> getAvailableAccounts({int index = 0, int limit = 5}) async {
15 final ethereumLedgerApp = EthereumLedgerApp(ledgerConnection);
16
17 await ethereumLedgerApp.getVersion();
@@ -22,8 +21,7 @@ class EVMChainLedgerService extends HardwareWalletService {
21
22 for (final i in indexRange) {
23 final derivationPath = "m/44'/60'/$i'/0/0";
25 - final address = await ethereumLedgerApp.getAccounts(
26 - accountsDerivationPath: derivationPath);
24 + final address = await ethereumLedgerApp.getAccounts(accountsDerivationPath: derivationPath);
25
26 accounts.add(HardwareAccountData(
27 address: address.first,
cw_evm/lib/tokens/base_tokens.dart
+1 -3
@@ -61,8 +61,7 @@ class BaseTokens {
61 if (token.iconPath?.isEmpty ?? true) {
62 try {
63 iconPath = CryptoCurrency.all
64 - .firstWhere((element) =>
65 - element.title.toUpperCase() == token.symbol.toUpperCase())
64 + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase())
65 .iconPath;
66 } catch (_) {}
67 } else {
@@ -73,4 +72,3 @@ class BaseTokens {
72 }).toList();
73 }
74 }
76 -
cw_evm/lib/tokens/polygon_tokens.dart
+1 -3
@@ -75,8 +75,7 @@ class PolygonTokens {
75 if (token.iconPath?.isEmpty ?? true) {
76 try {
77 iconPath = CryptoCurrency.all
78 - .firstWhere((element) =>
79 - element.title.toUpperCase() == token.symbol.toUpperCase())
78 + .firstWhere((element) => element.title.toUpperCase() == token.symbol.toUpperCase())
79 .iconPath;
80 } catch (_) {}
81 } else {
@@ -87,4 +86,3 @@ class PolygonTokens {
86 }).toList();
87 }
88 }
90 -
cw_evm/lib/usdt0/usdt0_config.dart
+7 -13
@@ -1,15 +1,13 @@
1 import 'package:cw_core/erc20_token.dart';
2
3 -/// USDT0 (Omnichain USDT) config.
3 +/// USDT0 (Omnichain USDT) config.
4 /// Addresses and EIDs from https://docs.usdt0.to/technical-documentation/deployments
5 class USDT0Config {
6 USDT0Config._();
7
8 - static const String ethereumOftAdapter =
9 - '0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee';
8 + static const String ethereumOftAdapter = '0x6C96dE32CEa08842dcc4058c14d3aaAD7Fa41dee';
9
11 - static const String ethereumNativeUsdt =
12 - '0xdac17f958d2ee523a2206206994597c13d831ec7';
10 + static const String ethereumNativeUsdt = '0xdac17f958d2ee523a2206206994597c13d831ec7';
11
12 static const Map<int, String> usdt0TokenAddressByChainId = {
13 1: ethereumNativeUsdt,
@@ -31,24 +29,20 @@ class USDT0Config {
29
30 static const int ethereumChainId = 1;
31
34 - static List<int> get supportedChainIds =>
35 - usdt0TokenAddressByChainId.keys.toList(growable: false);
32 + static List<int> get supportedChainIds => usdt0TokenAddressByChainId.keys.toList(growable: false);
33
34 static String? getOftAdapterAddress(int chainId) {
35 if (chainId == ethereumChainId) return ethereumOftAdapter;
36 return null;
37 }
38
42 - static String? getUsdt0TokenAddress(int chainId) =>
43 - usdt0TokenAddressByChainId[chainId];
39 + static String? getUsdt0TokenAddress(int chainId) => usdt0TokenAddressByChainId[chainId];
40
45 - static String? getOftContractAddress(int chainId) =>
46 - oftContractAddressByChainId[chainId];
41 + static String? getOftContractAddress(int chainId) => oftContractAddressByChainId[chainId];
42
43 static int? getEndpointId(int chainId) => endpointIdByChainId[chainId];
44
50 - static bool isChainSupported(int chainId) =>
51 - usdt0TokenAddressByChainId.containsKey(chainId);
45 + static bool isChainSupported(int chainId) => usdt0TokenAddressByChainId.containsKey(chainId);
46
47 static bool isUSDT0Token(Erc20Token token, int chainId) {
48 final address = getUsdt0TokenAddress(chainId);
cw_evm/lib/usdt0/usdt0_service.dart
+1 -1
@@ -81,7 +81,7 @@ class USDT0Service {
81 );
82
83 final pendingApproval = await wallet.createApprovalTransaction(
84 - Money(maxUint,token),
84 + Money(maxUint, token),
85 adapter,
86 priority,
87 useBlinkProtection: useBlinkProtection,
cw_evm/lib/utils/network_chain_utils.dart
-1
@@ -60,4 +60,3 @@ class FeeModel {
60 this.maxPriorityFee,
61 });
62 }
63 -
cw_monero/lib/api/account_list.dart
+1 -1
@@ -39,7 +39,7 @@ void refreshAccounts() {
39 }
40 }
41
42 - List<Wallet2SubaddressAccountRow> getAllAccount() {
42 +List<Wallet2SubaddressAccountRow> getAllAccount() {
43 // final size = monero.Wallet_numSubaddressAccounts(wptr!);
44 refreshAccounts();
45 int size = subaddressAccount!.getAll_size();
cw_monero/lib/api/exceptions/creation_transaction_exception.dart
+2 -2
@@ -1,8 +1,8 @@
1 class CreationTransactionException implements Exception {
2 CreationTransactionException({required this.message});
3 -
3 +
4 final String message;
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_monero/lib/api/exceptions/setup_wallet_exception.dart
+2 -2
@@ -1,8 +1,8 @@
1 class SetupWalletException implements Exception {
2 SetupWalletException({required this.message});
3 -
3 +
4 final String message;
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_monero/lib/api/exceptions/wallet_creation_exception.dart
+1 -1
@@ -5,4 +5,4 @@ class WalletCreationException implements Exception {
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_monero/lib/api/exceptions/wallet_opening_exception.dart
+1 -1
@@ -5,4 +5,4 @@ class WalletOpeningException implements Exception {
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_monero/lib/api/exceptions/wallet_restore_from_keys_exception.dart
+2 -2
@@ -1,8 +1,8 @@
1 class WalletRestoreFromKeysException implements Exception {
2 WalletRestoreFromKeysException({required this.message});
3 -
3 +
4 final String message;
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_monero/lib/api/exceptions/wallet_restore_from_seed_exception.dart
+2 -2
@@ -1,8 +1,8 @@
1 class WalletRestoreFromSeedException implements Exception {
2 WalletRestoreFromSeedException({required this.message});
3 -
3 +
4 final String message;
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_monero/lib/api/monero_output.dart
+1 -1
@@ -3,4 +3,4 @@ class MoneroOutput {
3
4 final String address;
5 final String amount;
6 -}
\ No newline at end of file
6 +}
cw_monero/lib/api/structs/pending_transaction.dart
+7 -8
@@ -1,15 +1,14 @@
1 -
1 class PendingTransactionDescription {
3 - PendingTransactionDescription({
4 - required this.amount,
5 - required this.fee,
6 - required this.hash,
7 - required this.hex,
8 - required this.pointerAddress});
2 + PendingTransactionDescription(
3 + {required this.amount,
4 + required this.fee,
5 + required this.hash,
6 + required this.hex,
7 + required this.pointerAddress});
8
9 final int amount;
10 final int fee;
11 final String hash;
12 final String hex;
13 final int pointerAddress;
15 -}
\ No newline at end of file
14 +}
cw_monero/lib/api/subaddress_list.dart
+18 -14
@@ -1,4 +1,3 @@
1 -
1 import 'package:cw_monero/api/account_list.dart';
2 import 'package:cw_monero/api/transaction_history.dart';
3 import 'package:cw_monero/api/wallet.dart';
@@ -16,7 +15,9 @@ class SubaddressInfoMetadata {
15 SubaddressInfoMetadata? subaddress = null;
16
17 String getRawLabel({required int accountIndex, required int addressIndex}) {
19 - return currentWallet?.getSubaddressLabel(accountIndex: accountIndex, addressIndex: addressIndex)??"";
18 + return currentWallet?.getSubaddressLabel(
19 + accountIndex: accountIndex, addressIndex: addressIndex) ??
20 + "";
21 }
22
23 void refreshSubaddresses({required int accountIndex}) {
@@ -46,8 +47,11 @@ class Subaddress {
47 final int received;
48 final int txCount;
49 String get label {
49 - final localLabel = currentWallet?.getSubaddressLabel(accountIndex: accountIndex, addressIndex: addressIndex) ?? "";
50 - if (localLabel.startsWith("#$addressIndex")) return localLabel; // don't duplicate the ID if it was user-providen
50 + final localLabel =
51 + currentWallet?.getSubaddressLabel(accountIndex: accountIndex, addressIndex: addressIndex) ??
52 + "";
53 + if (localLabel.startsWith("#$addressIndex"))
54 + return localLabel; // don't duplicate the ID if it was user-providen
55 return "#$addressIndex ${localLabel}".trim();
56 }
57 }
@@ -97,7 +101,7 @@ Future<List<Subaddress>> getAllSubaddresses() async {
101 final list = List.generate(size, (index) {
102 final ttDetailsLocal = ttDetails.where((element) {
103 final address = getAddress(
100 - accountIndex: subaddress!.accountIndex,
104 + accountIndex: subaddress!.accountIndex,
105 addressIndex: index,
106 );
107 if (element.address.contains(address)) return true;
@@ -115,13 +119,12 @@ Future<List<Subaddress>> getAllSubaddresses() async {
119 );
120 }).reversed.toList();
121 if (list.length == 0) {
118 - list.add(
119 - Subaddress(
120 - addressIndex: subaddress!.accountIndex,
121 - accountIndex: 0,
122 - received: 0,
123 - txCount: 0,
124 - ));
122 + list.add(Subaddress(
123 + addressIndex: subaddress!.accountIndex,
124 + accountIndex: 0,
125 + received: 0,
126 + txCount: 0,
127 + ));
128 }
129 return list;
130 }
@@ -138,6 +141,7 @@ Future<void> addSubaddress({required int accountIndex, required String label}) a
141
142 Future<void> setLabelForSubaddress(
143 {required int accountIndex, required int addressIndex, required String label}) async {
141 - currentWallet?.setSubaddressLabel(accountIndex: accountIndex, addressIndex: addressIndex, label: label);
144 + currentWallet?.setSubaddressLabel(
145 + accountIndex: accountIndex, addressIndex: addressIndex, label: label);
146 await store();
143 -}
\ No newline at end of file
147 +}
cw_monero/lib/api/transaction_history.dart
+60 -60
@@ -16,7 +16,6 @@ import 'package:monero/src/wallet2.dart';
16 import 'package:monero/src/generated_bindings_monero.g.dart' as monero_gen;
17 import 'package:mutex/mutex.dart';
18
19 -
19 String _formatTransactionError(String error) {
20 final message = error.replaceAll(
21 RegExp(
@@ -68,7 +67,7 @@ int countOfTransactions() => txhistory!.count();
67
68 Future<List<Transaction>> getAllTransactions() async {
69 List<Transaction> dummyTxs = [];
71 -
70 +
71 await txHistoryMutex.acquire();
72 txhistory ??= currentWallet!.history();
73 final startAddress = txhistory!.ffiAddress() * currentWallet!.ffiAddress();
@@ -91,29 +90,29 @@ Future<List<Transaction>> getAllTransactions() async {
90 }
91 txHistoryMutex.release();
92 final accts = currentWallet!.numSubaddressAccounts();
94 - for (var i = 0; i < accts; i++) {
93 + for (var i = 0; i < accts; i++) {
94 final fullBalance = currentWallet!.balance(accountIndex: i);
95 final availBalance = currentWallet!.unlockedBalance(accountIndex: i);
96 if (fullBalance > availBalance) {
98 - if (list.where((element) => element.accountIndex == i && element.isConfirmed == false).isEmpty) {
99 - dummyTxs.add(
100 - Transaction.dummy(
101 - displayLabel: "",
102 - description: "",
103 - fee: 0,
104 - confirmations: 0,
105 - blockheight: 0,
106 - accountIndex: i,
107 - addressIndex: 0,
108 - addressIndexList: [0],
109 - paymentId: "",
110 - amount: fullBalance - availBalance,
111 - isSpend: false,
112 - hash: "pending",
113 - key: "",
114 - txInfo: DummyTransaction(),
115 - )..timeStamp = DateTime.now()
116 - );
97 + if (list
98 + .where((element) => element.accountIndex == i && element.isConfirmed == false)
99 + .isEmpty) {
100 + dummyTxs.add(Transaction.dummy(
101 + displayLabel: "",
102 + description: "",
103 + fee: 0,
104 + confirmations: 0,
105 + blockheight: 0,
106 + accountIndex: i,
107 + addressIndex: 0,
108 + addressIndexList: [0],
109 + paymentId: "",
110 + amount: fullBalance - availBalance,
111 + isSpend: false,
112 + hash: "pending",
113 + key: "",
114 + txInfo: DummyTransaction(),
115 + )..timeStamp = DateTime.now());
116 }
117 }
118 }
@@ -128,7 +127,8 @@ class DummyTransaction implements Wallet2TransactionInfo {
127
128 Map<int, Map<String, Transaction>> txCache = {};
129 Future<Transaction> getTransaction(String txId) async {
131 - if (txCache[currentWallet!.ffiAddress()] != null && txCache[currentWallet!.ffiAddress()]![txId] != null) {
130 + if (txCache[currentWallet!.ffiAddress()] != null &&
131 + txCache[currentWallet!.ffiAddress()]![txId] != null) {
132 return txCache[currentWallet!.ffiAddress()]![txId]!;
133 }
134 await txHistoryMutex.acquire();
@@ -147,7 +147,6 @@ Future<PendingTransactionDescription> createTransactionSync(
147 String? amount,
148 int accountIndex = 0,
149 List<String> preferredInputs = const []}) async {
150 -
150 final amt = amount == null ? 0 : currentWallet!.amountFromString(amount);
151
152 final waddr = currentWallet!.ffiAddress();
@@ -158,10 +157,11 @@ Future<PendingTransactionDescription> createTransactionSync(
157 monero.Wallet_synchronized(Pointer.fromAddress(waddr));
158 });
159
161 - final address_ = address.toNativeUtf8();
160 + final address_ = address.toNativeUtf8();
161 final paymentId_ = paymentId.toNativeUtf8();
162 if (preferredInputs.isEmpty) {
164 - throw MoneroTransactionCreationException("No inputs provided, transaction cannot be constructed");
163 + throw MoneroTransactionCreationException(
164 + "No inputs provided, transaction cannot be constructed");
165 }
166
167 final preferredInputs_ = preferredInputs.join(monero.defaultSeparatorStr).toNativeUtf8();
@@ -171,7 +171,8 @@ Future<PendingTransactionDescription> createTransactionSync(
171 final preferredInputsAddr = preferredInputs_.address;
172 final spaddr = monero.defaultSeparator.address;
173 final pendingTxPtr = Pointer<Void>.fromAddress(await Isolate.run(() {
174 - final tx = monero_gen.MoneroC(DynamicLibrary.open(monero.libPath)).MONERO_Wallet_createTransaction(
174 + final tx =
175 + monero_gen.MoneroC(DynamicLibrary.open(monero.libPath)).MONERO_Wallet_createTransaction(
176 Pointer.fromAddress(waddr),
177 Pointer.fromAddress(addraddr).cast(),
178 Pointer.fromAddress(paymentIdAddr).cast(),
@@ -206,12 +207,12 @@ Future<PendingTransactionDescription> createTransactionSync(
207 final rHex = pendingTx.hex('');
208
209 return PendingTransactionDescription(
209 - amount: rAmt,
210 - fee: rFee,
211 - hash: rHash,
212 - hex: rHex,
213 - pointerAddress: pendingTx.ffiAddress(),
214 - );
210 + amount: rAmt,
211 + fee: rFee,
212 + hash: rHash,
213 + hex: rHex,
214 + pointerAddress: pendingTx.ffiAddress(),
215 + );
216 }
217
218 Future<PendingTransactionDescription> createTransactionMultDest(
@@ -220,7 +221,6 @@ Future<PendingTransactionDescription> createTransactionMultDest(
221 required int priorityRaw,
222 int accountIndex = 0,
223 List<String> preferredInputs = const []}) async {
223 -
224 final dstAddrs = outputs.map((e) => e.address).toList();
225 final amounts = outputs.map((e) => currentWallet!.amountFromString(e.amount)).toList();
226
@@ -261,7 +261,8 @@ Future<PendingTransactionDescription> createTransactionMultDest(
261 Future<String?> commitTransactionFromPointerAddress({required int address, required bool useUR}) =>
262 commitTransaction(tx: MoneroPendingTransaction(Pointer.fromAddress(address)), useUR: useUR);
263
264 -Future<String?> commitTransaction({required Wallet2PendingTransaction tx, required bool useUR}) async {
264 +Future<String?> commitTransaction(
265 + {required Wallet2PendingTransaction tx, required bool useUR}) async {
266 final txCommit = useUR
267 ? tx.commitUR(120)
268 : await Isolate.run(() {
@@ -288,7 +289,6 @@ Future<String?> commitTransaction({required Wallet2PendingTransaction tx, requir
289 }
290 return currentWallet!.errorString();
291 })();
291 -
292 }
293 if (error != null && error != "no tx keys found for this txid") {
294 throw CreationTransactionException(message: _formatTransactionError(error));
@@ -311,11 +311,12 @@ class Transaction {
311 accountIndex: accountIndex,
312 addressIndex: addressIndex,
313 );
314 - late final List<String> addressList = List.generate(addressIndexList.length, (index) =>
315 - getAddress(
316 - accountIndex: accountIndex,
317 - addressIndex: addressIndexList[index],
318 - ));
314 + late final List<String> addressList = List.generate(
315 + addressIndexList.length,
316 + (index) => getAddress(
317 + accountIndex: accountIndex,
318 + addressIndex: addressIndexList[index],
319 + ));
320 final String description;
321 final int fee;
322 final int confirmations;
@@ -364,33 +365,32 @@ class Transaction {
365 timeStamp = DateTime.fromMillisecondsSinceEpoch(
366 txInfo.timestamp() * 1000,
367 ),
367 - isSpend = txInfo.direction() ==
368 - monero.TransactionInfo_Direction.Out.index,
368 + isSpend = txInfo.direction() == monero.TransactionInfo_Direction.Out.index,
369 amount = txInfo.amount(),
370 paymentId = txInfo.paymentId(),
371 accountIndex = txInfo.subaddrAccount(),
372 addressIndex = int.tryParse(txInfo.subaddrIndex().split(", ")[0]) ?? 0,
373 - addressIndexList = txInfo.subaddrIndex().split(", ").map((e) => int.tryParse(e) ?? 0).toList(),
373 + addressIndexList =
374 + txInfo.subaddrIndex().split(", ").map((e) => int.tryParse(e) ?? 0).toList(),
375 blockheight = txInfo.blockHeight(),
376 confirmations = txInfo.confirmations(),
377 fee = txInfo.fee(),
378 description = txInfo.description(),
379 key = getTxKey(txInfo.hash());
380
380 - Transaction.dummy({
381 - required this.displayLabel,
382 - required this.description,
383 - required this.fee,
384 - required this.confirmations,
385 - required this.blockheight,
386 - required this.accountIndex,
387 - required this.addressIndexList,
388 - required this.addressIndex,
389 - required this.paymentId,
390 - required this.amount,
391 - required this.isSpend,
392 - required this.hash,
393 - required this.key,
394 - required this.txInfo
395 - });
381 + Transaction.dummy(
382 + {required this.displayLabel,
383 + required this.description,
384 + required this.fee,
385 + required this.confirmations,
386 + required this.blockheight,
387 + required this.accountIndex,
388 + required this.addressIndexList,
389 + required this.addressIndex,
390 + required this.paymentId,
391 + required this.amount,
392 + required this.isSpend,
393 + required this.hash,
394 + required this.key,
395 + required this.txInfo});
396 }
cw_monero/lib/api/wallet.dart
+31 -28
@@ -44,8 +44,7 @@ String getFilename() => currentWallet!.filename();
44
45 String getSeed() {
46 // monero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.seed", value: seed);
47 - final cakepolyseed =
48 - currentWallet!.getCacheAttribute(key: "cakewallet.seed");
47 + final cakepolyseed = currentWallet!.getCacheAttribute(key: "cakewallet.seed");
48 final cakepassphrase = getPassphrase();
49
50 final weirdPolyseed = currentWallet!.getPolyseed(passphrase: cakepassphrase);
@@ -69,7 +68,7 @@ String getSeed() {
68
69 final bip39 = currentWallet!.getCacheAttribute(key: "cakewallet.seed.bip39");
70
72 - if(bip39.isNotEmpty) return bip39;
71 + if (bip39.isNotEmpty) return bip39;
72
73 final legacy = getSeedLegacy(null);
74 return legacy;
@@ -77,11 +76,21 @@ String getSeed() {
76
77 String? getSeedLanguage(String? language) {
78 switch (language) {
80 - case "Chinese (Traditional)": language = "Chinese (simplified)"; break;
81 - case "Chinese (Simplified)": language = "Chinese (simplified)"; break;
82 - case "Korean": language = "English"; break;
83 - case "Czech": language = "English"; break;
84 - case "Japanese": language = "English"; break;
79 + case "Chinese (Traditional)":
80 + language = "Chinese (simplified)";
81 + break;
82 + case "Chinese (Simplified)":
83 + language = "Chinese (simplified)";
84 + break;
85 + case "Korean":
86 + language = "English";
87 + break;
88 + case "Czech":
89 + language = "English";
90 + break;
91 + case "Japanese":
92 + language = "English";
93 + break;
94 }
95 return language;
96 }
@@ -132,7 +141,7 @@ String getAddress({int accountIndex = 0, int addressIndex = 0}) {
141
142 // printV("getaddress: ${accountIndex}/${addressIndex}: ${monero.Wallet_numSubaddresses(wptr!, accountIndex: accountIndex)}: ${monero.Wallet_address(wptr!, accountIndex: accountIndex, addressIndex: addressIndex)}");
143 // this could be a while loop, but I'm in favor of making it if to not cause freezes
135 - if (currentWallet!.numSubaddresses(accountIndex: accountIndex)-1 < addressIndex) {
144 + if (currentWallet!.numSubaddresses(accountIndex: accountIndex) - 1 < addressIndex) {
145 if (currentWallet!.numSubaddressAccounts() < accountIndex) {
146 currentWallet!.addSubaddressAccount();
147 } else {
@@ -141,8 +150,8 @@ String getAddress({int accountIndex = 0, int addressIndex = 0}) {
150 }
151 addressCache[currentWallet!.ffiAddress()] ??= {};
152 addressCache[currentWallet!.ffiAddress()]![accountIndex] ??= {};
144 - addressCache[currentWallet!.ffiAddress()]![accountIndex]![addressIndex] ??= currentWallet!.address(
145 - accountIndex: accountIndex, addressIndex: addressIndex);
153 + addressCache[currentWallet!.ffiAddress()]![accountIndex]![addressIndex] ??=
154 + currentWallet!.address(accountIndex: accountIndex, addressIndex: addressIndex);
155 return addressCache[currentWallet!.ffiAddress()]![accountIndex]![addressIndex]!;
156 }
157
@@ -154,7 +163,6 @@ Money getUnlockedBalance({int accountIndex = 0}) => Money.fromInt(
163
164 int getCurrentHeight() => currentWallet?.blockChainHeight() ?? 0;
165
157 -
166 int cachedNodeHeight = 0;
167 bool isHeightRefreshing = false;
168 int getNodeHeightSync() {
@@ -238,10 +246,8 @@ void startRefreshSync() {
246 currentWallet!.startRefresh();
247 }
248
241 -
249 void setRefreshFromBlockHeight({required int height}) {
243 - currentWallet!.setRefreshFromBlockHeight(
244 - refresh_from_block_height: height);
250 + currentWallet!.setRefreshFromBlockHeight(refresh_from_block_height: height);
251 }
252
253 void setRecoveringFromSeed({required bool isRecovery}) {
@@ -251,7 +257,6 @@ void setRecoveringFromSeed({required bool isRecovery}) {
257
258 final storeMutex = Mutex();
259
254 -
260 int lastStorePointer = 0;
261 int lastStoreHeight = 0;
262 void storeSync({bool force = false}) async {
@@ -261,7 +266,7 @@ void storeSync({bool force = false}) async {
266 });
267 if (lastStorePointer == addr &&
268 lastStoreHeight + 75000 > currentWallet!.blockChainHeight() &&
264 - !synchronized &&
269 + !synchronized &&
270 !force) {
271 return;
272 }
@@ -300,8 +305,8 @@ class SyncListener {
305 : _cachedBlockchainHeight = 0,
306 _lastKnownBlockHeight = 0,
307 _initialSyncHeight = 0 {
303 - _start();
304 - }
308 + _start();
309 + }
310
311 void Function(int, int, double) onNewBlock;
312 void Function() onNewTransaction;
@@ -323,8 +328,7 @@ class SyncListener {
328 _cachedBlockchainHeight = 0;
329 _lastKnownBlockHeight = 0;
330 _initialSyncHeight = 0;
326 - _updateSyncInfoTimer ??=
327 - Timer.periodic(Duration(milliseconds: 1200), (_) async {
331 + _updateSyncInfoTimer ??= Timer.periodic(Duration(milliseconds: 1200), (_) async {
332 if (isNewTransactionExist()) {
333 onNewTransaction();
334 }
@@ -370,8 +374,8 @@ class SyncListener {
374 void stop() => _updateSyncInfoTimer?.cancel();
375 }
376
373 -SyncListener setListeners(void Function(int, int, double) onNewBlock,
374 - void Function() onNewTransaction) {
377 +SyncListener setListeners(
378 + void Function(int, int, double) onNewBlock, void Function() onNewTransaction) {
379 final listener = SyncListener(onNewBlock, onNewTransaction);
380 // setListenerNative();
381 return listener;
@@ -407,12 +411,10 @@ Future<int> getNodeHeight() async => getNodeHeightSync();
411 void rescanBlockchainAsync() => currentWallet!.rescanBlockchainAsync();
412
413 String getSubaddressLabel(int accountIndex, int addressIndex) {
410 - return currentWallet!.getSubaddressLabel(
411 - accountIndex: accountIndex, addressIndex: addressIndex);
414 + return currentWallet!.getSubaddressLabel(accountIndex: accountIndex, addressIndex: addressIndex);
415 }
416
414 -Future setTrustedDaemon(bool trusted) async =>
415 - currentWallet!.setTrustedDaemon(arg: trusted);
417 +Future setTrustedDaemon(bool trusted) async => currentWallet!.setTrustedDaemon(arg: trusted);
418
419 Future<bool> trustedDaemon() async => currentWallet!.trustedDaemon();
420
@@ -426,7 +428,8 @@ Map<String, List<int>> debugCallLength() => monero.debugCallLength;
428
429 Map<String, dynamic> getWalletCacheDebug() {
430 try {
429 - final jsonString = monero.MONERO_Wallet_serializeCacheToJson(Pointer.fromAddress(currentWallet!.ffiAddress()));
431 + final jsonString =
432 + monero.MONERO_Wallet_serializeCacheToJson(Pointer.fromAddress(currentWallet!.ffiAddress()));
433 final blob = json.decode(jsonString);
434 blob['cake:unspent'] = getAllUnspent();
435 return blob;
cw_monero/lib/api/wallet_manager.dart
+25 -33
@@ -36,17 +36,21 @@ void checkIfMoneroCIsFine() {
36 final dartCsExp = monero.wallet2_api_c_exp_sha256;
37
38 if (cppCsCpp != dartCsCpp) {
39 - throw MoneroCException("monero_c and monero.dart cpp wrapper code mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsCpp'\ndart: '$dartCsCpp'");
39 + throw MoneroCException(
40 + "monero_c and monero.dart cpp wrapper code mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsCpp'\ndart: '$dartCsCpp'");
41 }
42
43 if (cppCsH != dartCsH) {
43 - throw MoneroCException("monero_c and monero.dart cpp wrapper header mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsH'\ndart: '$dartCsH'");
44 + throw MoneroCException(
45 + "monero_c and monero.dart cpp wrapper header mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsH'\ndart: '$dartCsH'");
46 }
47
48 if (cppCsExp != dartCsExp && (Platform.isIOS || Platform.isMacOS)) {
47 - throw MoneroCException("monero_c and monero.dart wrapper export list mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsExp'\ndart: '$dartCsExp'");
49 + throw MoneroCException(
50 + "monero_c and monero.dart wrapper export list mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsExp'\ndart: '$dartCsExp'");
51 }
52 }
53 +
54 Wallet2WalletManager? _wmPtr;
55 Wallet2WalletManager wmPtr = (() {
56 try {
@@ -70,8 +74,7 @@ Wallet2WalletManager wmPtr = (() {
74 })();
75
76 Wallet2Wallet createWalletPointer() {
73 - final newWptr = wmPtr.createWallet(
74 - path: "", password: "", language: "", networkType: 0);
77 + final newWptr = wmPtr.createWallet(path: "", password: "", language: "", networkType: 0);
78 return newWptr;
79 }
80
@@ -83,8 +86,8 @@ void createWallet(
86 int nettype = 0}) {
87 txhistory = null;
88 language = getSeedLanguage(language)!;
86 - final newW = wmPtr.createWallet(
87 - path: path, password: password, language: language, networkType: 0);
89 + final newW =
90 + wmPtr.createWallet(path: path, password: password, language: language, networkType: 0);
91
92 int status = newW.status();
93 if (status != 0) {
@@ -128,7 +131,8 @@ void restoreWalletFromSeedSync(
131 final error = newW.errorString();
132 if (error.contains('word list failed verification')) {
133 throw WalletRestoreFromSeedException(
131 - message: "Seed verification failed, please make sure you entered the correct seed with the correct words order",
134 + message:
135 + "Seed verification failed, please make sure you entered the correct seed with the correct words order",
136 );
137 }
138 throw WalletRestoreFromSeedException(message: error);
@@ -177,12 +181,10 @@ void restoreWalletFromKeys(
181
182 int status = newW.status();
183 if (status != 0) {
180 - throw WalletRestoreFromKeysException(
181 - message: newW.errorString());
184 + throw WalletRestoreFromKeysException(message: newW.errorString());
185 }
186 newW.store(path: path);
187
185 -
188 // CW-712 - Try to restore deterministic wallet first, if the view key doesn't
189 // match the view key provided
190 if (spendKey != "") {
@@ -202,8 +204,7 @@ void restoreWalletFromKeys(
204 );
205 int status = newW.status();
206 if (status != 0) {
205 - throw WalletRestoreFromKeysException(
206 - message: newW.errorString());
207 + throw WalletRestoreFromKeysException(message: newW.errorString());
208 }
209 newW.store(path: path);
210
@@ -217,7 +218,6 @@ void restoreWalletFromKeys(
218 _lastOpenedWallet = path;
219 }
220
220 -
221 // English only, because normalization.
222 void restoreWalletFromPolyseedWithOffset(
223 {required String path,
@@ -226,7 +226,6 @@ void restoreWalletFromPolyseedWithOffset(
226 required String seedOffset,
227 required String language,
228 int nettype = 0}) {
229 -
229 txhistory = null;
230 final newW = wmPtr.createWalletFromPolyseed(
231 path: path,
@@ -259,7 +258,6 @@ void restoreWalletFromPolyseedWithOffset(
258 openedWalletsByPath[path] = currentWallet!;
259 }
260
262 -
261 void restoreWalletFromSpendKeySync(
262 {required String path,
263 required String password,
@@ -322,10 +320,7 @@ Future<void> restoreWalletFromHardwareWallet(
320 final wmPtr = MoneroWalletManagerFactory().getWalletManager().ffiAddress();
321 final newWptrAddr = await Isolate.run(() {
322 return monero.WalletManager_createWalletFromDevice(Pointer.fromAddress(wmPtr),
325 - path: path,
326 - password: password,
327 - restoreHeight: restoreHeight,
328 - deviceName: deviceName)
323 + path: path, password: password, restoreHeight: restoreHeight, deviceName: deviceName)
324 .address;
325 });
326 final newW = MoneroWallet(Pointer.fromAddress(newWptrAddr));
@@ -345,8 +340,7 @@ Future<void> restoreWalletFromHardwareWallet(
340
341 Map<String, Wallet2Wallet> openedWalletsByPath = {};
342
348 -Future<void> loadWallet(
349 - {required String path, required String password, int nettype = 0}) async {
343 +Future<void> loadWallet({required String path, required String password, int nettype = 0}) async {
344 if (openedWalletsByPath[path] != null) {
345 txhistory = null;
346 currentWallet = openedWalletsByPath[path]!;
@@ -368,14 +362,14 @@ Future<void> loadWallet(
362 var deviceType = 0;
363
364 if (Platform.isAndroid || Platform.isIOS) {
371 - deviceType = wmPtr.queryWalletDevice(
365 + deviceType = wmPtr.queryWalletDevice(
366 keysFileName: "$path.keys",
367 password: password,
368 kdfRounds: 1,
369 );
370 final status = wmPtr.errorString();
371 if (status != "") {
378 - printV("loadWallet:"+status);
372 + printV("loadWallet:" + status);
373 // This is most likely closeWallet call leaking error. This is fine.
374 if (status.contains("failed to save file")) {
375 printV("loadWallet: error leaked: $status");
@@ -390,7 +384,7 @@ Future<void> loadWallet(
384
385 if (deviceType == 1) {
386 if (gLedger == null) {
393 - throw Exception("Tried to open a ledger wallet with no ledger connected");
387 + throw Exception("Tried to open a ledger wallet with no ledger connected");
388 }
389 enableLedgerExchange(gLedger!);
390 }
@@ -407,7 +401,7 @@ Future<void> loadWallet(
401 int status = newW.status();
402 if (status != 0) {
403 final err = newW.errorString();
410 - printV("loadWallet:"+err);
404 + printV("loadWallet:" + err);
405 throw WalletOpeningException(message: err);
406 }
407 if (deviceType == 0) {
@@ -424,18 +418,16 @@ void setupBackgroundSync(String password, Wallet2Wallet wallet) {
418 if (isViewOnlyBySpendKey(wallet)) {
419 return;
420 }
427 - wallet.setupBackgroundSync(backgroundSyncType: 2, walletPassword: password, backgroundCachePassword: '');
421 + wallet.setupBackgroundSync(
422 + backgroundSyncType: 2, walletPassword: password, backgroundCachePassword: '');
423 if (wallet.status() != 0) {
424 // We simply ignore the error.
425 printV("setupBackgroundSync: ${wallet.errorString()}");
426 }
427 }
428
434 -
435 -Future<void> openWallet(
436 - {required String path,
437 - required String password,
438 - int nettype = 0}) async =>
429 +Future<void> openWallet({required String path, required String password, int nettype = 0}) async =>
430 loadWallet(path: path, password: password, nettype: nettype);
431
441 -bool isViewOnlyBySpendKey(Wallet2Wallet? wallet) => int.tryParse((wallet??currentWallet!).secretSpendKey()) == 0;
432 +bool isViewOnlyBySpendKey(Wallet2Wallet? wallet) =>
433 + int.tryParse((wallet ?? currentWallet!).secretSpendKey()) == 0;
cw_monero/lib/bip39_seed.dart
+5 -10
@@ -8,21 +8,17 @@ bool isBip39Seed(String mnemonic) => bip39.validateMnemonic(mnemonic);
8
9 String getBip39Seed() => bip39.generateMnemonic();
10
11 -String getLegacySeedFromBip39(String mnemonic,
12 - {int accountIndex = 0, String passphrase = ""}) {
11 +String getLegacySeedFromBip39(String mnemonic, {int accountIndex = 0, String passphrase = ""}) {
12 final seed = bip39.mnemonicToSeed(mnemonic, passphrase: passphrase);
13
15 - final bip32KeyPair =
16 - bip32.BIP32.fromSeed(seed).derivePath("m/44'/128'/$accountIndex'/0/0");
14 + final bip32KeyPair = bip32.BIP32.fromSeed(seed).derivePath("m/44'/128'/$accountIndex'/0/0");
15
16 final spendKey = _reduceECKey(bip32KeyPair.privateKey!);
17
20 - return LegacySeedLang.getByEnglishName("English")
21 - .encodePhrase(spendKey.toHexString());
18 + return LegacySeedLang.getByEnglishName("English").encodePhrase(spendKey.toHexString());
19 }
20
24 -const _ed25519CurveOrder =
25 - "1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
21 +const _ed25519CurveOrder = "1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED";
22
23 Uint8List _reduceECKey(Uint8List buffer) {
24 final curveOrder = BigInt.parse(_ed25519CurveOrder, radix: 16);
@@ -51,8 +47,7 @@ BigInt _readBytes(Uint8List bytes) {
47 return BigInt.from(result);
48 }
49 final mid = start + ((end - start) >> 1);
54 - return read(start, mid) +
55 - read(mid, end) * (BigInt.one << ((mid - start) * 8));
50 + return read(start, mid) + read(mid, end) * (BigInt.one << ((mid - start) * 8));
51 }
52
53 return read(0, bytes.length);
cw_monero/lib/exceptions/monero_transaction_creation_exception.dart
+1 -1
@@ -5,4 +5,4 @@ class MoneroTransactionCreationException implements Exception {
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_monero/lib/exceptions/monero_transaction_no_inputs_exception.dart
+2 -1
@@ -4,5 +4,6 @@ class MoneroTransactionNoInputsException implements Exception {
4 int inputsSize;
5
6 @override
7 - String toString() => 'Not enough inputs ($inputsSize) selected. Please select more under Coin Control';
7 + String toString() =>
8 + 'Not enough inputs ($inputsSize) selected. Please select more under Coin Control';
9 }
cw_monero/lib/ledger.dart
+4 -9
@@ -33,8 +33,7 @@ Future<void> enableLedgerExchange(LedgerConnection connection) async {
33
34 latestLedgerCommand = _ledgerMoneroCommands[ledgerRequest[1]];
35
36 - api.MoneroWallet.setDeviceReceivedData(
37 - result.cast<UnsignedChar>(), response.length);
36 + api.MoneroWallet.setDeviceReceivedData(result.cast<UnsignedChar>(), response.length);
37 malloc.free(result);
38 // api.MoneroFree().free(result.cast());
39 }
@@ -59,8 +58,7 @@ class ExchangeOperation extends LedgerRawOperation<Uint8List> {
58 ExchangeOperation(this.inputData);
59
60 @override
62 - Future<Uint8List> read(ByteDataReader reader) async =>
63 - reader.read(reader.remainingLength);
61 + Future<Uint8List> read(ByteDataReader reader) async => reader.read(reader.remainingLength);
62
63 @override
64 Future<List<Uint8List>> write(ByteDataWriter writer) async => [inputData];
@@ -109,14 +107,12 @@ const _ledgerMoneroCommands = {
107 };
108
109 void _logLedgerCommand(Uint8List command, [bool isResponse = true]) {
112 - String toHexString(Uint8List data) =>
113 - data.map((e) => e.toRadixString(16).padLeft(2, '0')).join();
110 + String toHexString(Uint8List data) => data.map((e) => e.toRadixString(16).padLeft(2, '0')).join();
111
112 if (isResponse) {
113 printV("< ${toHexString(command)}");
114 } else {
118 - printV(
119 - "> ${_ledgerMoneroCommands[command[1]]} ${toHexString(command.sublist(2))}");
115 + printV("> ${_ledgerMoneroCommands[command[1]]} ${toHexString(command.sublist(2))}");
116 }
117 }
118
@@ -125,4 +121,3 @@ class MoneroLedgerService extends HardwareWalletService {
121
122 MoneroLedgerService(this.connection);
123 }
128 -
cw_monero/lib/mnemonics/chinese_simplified.dart
+1 -1
@@ -1627,4 +1627,4 @@ class ChineseSimplifiedMnemonics {
1627 "浙",
1628 "貌"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_monero/lib/mnemonics/dutch.dart
+1 -1
@@ -1627,4 +1627,4 @@ class DutchMnemonics {
1627 "zwijmel",
1628 "zworen"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_monero/lib/mnemonics/french.dart
+1629 -1629
@@ -1,1630 +1,1630 @@
1 class FrenchMnemonics {
2 - static const words = [
3 - "abandon",
4 - "abattre",
5 - "aboi",
6 - "abolir",
7 - "aborder",
8 - "abri",
9 - "absence",
10 - "absolu",
11 - "abuser",
12 - "acacia",
13 - "acajou",
14 - "accent",
15 - "accord",
16 - "accrocher",
17 - "accuser",
18 - "acerbe",
19 - "achat",
20 - "acheter",
21 - "acide",
22 - "acier",
23 - "acquis",
24 - "acte",
25 - "action",
26 - "adage",
27 - "adepte",
28 - "adieu",
29 - "admettre",
30 - "admis",
31 - "adorer",
32 - "adresser",
33 - "aduler",
34 - "affaire",
35 - "affirmer",
36 - "afin",
37 - "agacer",
38 - "agent",
39 - "agir",
40 - "agiter",
41 - "agonie",
42 - "agrafe",
43 - "agrume",
44 - "aider",
45 - "aigle",
46 - "aigre",
47 - "aile",
48 - "ailleurs",
49 - "aimant",
50 - "aimer",
51 - "ainsi",
52 - "aise",
53 - "ajouter",
54 - "alarme",
55 - "album",
56 - "alcool",
57 - "alerte",
58 - "algue",
59 - "alibi",
60 - "aller",
61 - "allumer",
62 - "alors",
63 - "amande",
64 - "amener",
65 - "amie",
66 - "amorcer",
67 - "amour",
68 - "ample",
69 - "amuser",
70 - "ananas",
71 - "ancien",
72 - "anglais",
73 - "angoisse",
74 - "animal",
75 - "anneau",
76 - "annoncer",
77 - "apercevoir",
78 - "apparence",
79 - "appel",
80 - "apporter",
81 - "apprendre",
82 - "appuyer",
83 - "arbre",
84 - "arcade",
85 - "arceau",
86 - "arche",
87 - "ardeur",
88 - "argent",
89 - "argile",
90 - "aride",
91 - "arme",
92 - "armure",
93 - "arracher",
94 - "arriver",
95 - "article",
96 - "asile",
97 - "aspect",
98 - "assaut",
99 - "assez",
100 - "assister",
101 - "assurer",
102 - "astre",
103 - "astuce",
104 - "atlas",
105 - "atroce",
106 - "attacher",
107 - "attente",
108 - "attirer",
109 - "aube",
110 - "aucun",
111 - "audace",
112 - "auparavant",
113 - "auquel",
114 - "aurore",
115 - "aussi",
116 - "autant",
117 - "auteur",
118 - "autoroute",
119 - "autre",
120 - "aval",
121 - "avant",
122 - "avec",
123 - "avenir",
124 - "averse",
125 - "aveu",
126 - "avide",
127 - "avion",
128 - "avis",
129 - "avoir",
130 - "avouer",
131 - "avril",
132 - "azote",
133 - "azur",
134 - "badge",
135 - "bagage",
136 - "bague",
137 - "bain",
138 - "baisser",
139 - "balai",
140 - "balcon",
141 - "balise",
142 - "balle",
143 - "bambou",
144 - "banane",
145 - "banc",
146 - "bandage",
147 - "banjo",
148 - "banlieue",
149 - "bannir",
150 - "banque",
151 - "baobab",
152 - "barbe",
153 - "barque",
154 - "barrer",
155 - "bassine",
156 - "bataille",
157 - "bateau",
158 - "battre",
159 - "baver",
160 - "bavoir",
161 - "bazar",
162 - "beau",
163 - "beige",
164 - "berger",
165 - "besoin",
166 - "beurre",
167 - "biais",
168 - "biceps",
169 - "bidule",
170 - "bien",
171 - "bijou",
172 - "bilan",
173 - "billet",
174 - "blanc",
175 - "blason",
176 - "bleu",
177 - "bloc",
178 - "blond",
179 - "bocal",
180 - "boire",
181 - "boiserie",
182 - "boiter",
183 - "bonbon",
184 - "bondir",
185 - "bonheur",
186 - "bordure",
187 - "borgne",
188 - "borner",
189 - "bosse",
190 - "bouche",
191 - "bouder",
192 - "bouger",
193 - "boule",
194 - "bourse",
195 - "bout",
196 - "boxe",
197 - "brader",
198 - "braise",
199 - "branche",
200 - "braquer",
201 - "bras",
202 - "brave",
203 - "brebis",
204 - "brevet",
205 - "brider",
206 - "briller",
207 - "brin",
208 - "brique",
209 - "briser",
210 - "broche",
211 - "broder",
212 - "bronze",
213 - "brosser",
214 - "brouter",
215 - "bruit",
216 - "brute",
217 - "budget",
218 - "buffet",
219 - "bulle",
220 - "bureau",
221 - "buriner",
222 - "buste",
223 - "buter",
224 - "butiner",
225 - "cabas",
226 - "cabinet",
227 - "cabri",
228 - "cacao",
229 - "cacher",
230 - "cadeau",
231 - "cadre",
232 - "cage",
233 - "caisse",
234 - "caler",
235 - "calme",
236 - "camarade",
237 - "camion",
238 - "campagne",
239 - "canal",
240 - "canif",
241 - "capable",
242 - "capot",
243 - "carat",
244 - "caresser",
245 - "carie",
246 - "carpe",
247 - "cartel",
248 - "casier",
249 - "casque",
250 - "casserole",
251 - "cause",
252 - "cavale",
253 - "cave",
254 - "ceci",
255 - "cela",
256 - "celui",
257 - "cendre",
258 - "cent",
259 - "cependant",
260 - "cercle",
261 - "cerise",
262 - "cerner",
263 - "certes",
264 - "cerveau",
265 - "cesser",
266 - "chacun",
267 - "chair",
268 - "chaleur",
269 - "chamois",
270 - "chanson",
271 - "chaque",
272 - "charge",
273 - "chasse",
274 - "chat",
275 - "chaud",
276 - "chef",
277 - "chemin",
278 - "cheveu",
279 - "chez",
280 - "chicane",
281 - "chien",
282 - "chiffre",
283 - "chiner",
284 - "chiot",
285 - "chlore",
286 - "choc",
287 - "choix",
288 - "chose",
289 - "chou",
290 - "chute",
291 - "cibler",
292 - "cidre",
293 - "ciel",
294 - "cigale",
295 - "cinq",
296 - "cintre",
297 - "cirage",
298 - "cirque",
299 - "ciseau",
300 - "citation",
301 - "citer",
302 - "citron",
303 - "civet",
304 - "clairon",
305 - "clan",
306 - "classe",
307 - "clavier",
308 - "clef",
309 - "climat",
310 - "cloche",
311 - "cloner",
312 - "clore",
313 - "clos",
314 - "clou",
315 - "club",
316 - "cobra",
317 - "cocon",
318 - "coiffer",
319 - "coin",
320 - "colline",
321 - "colon",
322 - "combat",
323 - "comme",
324 - "compte",
325 - "conclure",
326 - "conduire",
327 - "confier",
328 - "connu",
329 - "conseil",
330 - "contre",
331 - "convenir",
332 - "copier",
333 - "cordial",
334 - "cornet",
335 - "corps",
336 - "cosmos",
337 - "coton",
338 - "couche",
339 - "coude",
340 - "couler",
341 - "coupure",
342 - "cour",
343 - "couteau",
344 - "couvrir",
345 - "crabe",
346 - "crainte",
347 - "crampe",
348 - "cran",
349 - "creuser",
350 - "crever",
351 - "crier",
352 - "crime",
353 - "crin",
354 - "crise",
355 - "crochet",
356 - "croix",
357 - "cruel",
358 - "cuisine",
359 - "cuite",
360 - "culot",
361 - "culte",
362 - "cumul",
363 - "cure",
364 - "curieux",
365 - "cuve",
366 - "dame",
367 - "danger",
368 - "dans",
369 - "davantage",
370 - "debout",
371 - "dedans",
372 - "dehors",
373 - "delta",
374 - "demain",
375 - "demeurer",
376 - "demi",
377 - "dense",
378 - "dent",
379 - "depuis",
380 - "dernier",
381 - "descendre",
382 - "dessus",
383 - "destin",
384 - "dette",
385 - "deuil",
386 - "deux",
387 - "devant",
388 - "devenir",
389 - "devin",
390 - "devoir",
391 - "dicton",
392 - "dieu",
393 - "difficile",
394 - "digestion",
395 - "digue",
396 - "diluer",
397 - "dimanche",
398 - "dinde",
399 - "diode",
400 - "dire",
401 - "diriger",
402 - "discours",
403 - "disposer",
404 - "distance",
405 - "divan",
406 - "divers",
407 - "docile",
408 - "docteur",
409 - "dodu",
410 - "dogme",
411 - "doigt",
412 - "dominer",
413 - "donation",
414 - "donjon",
415 - "donner",
416 - "dopage",
417 - "dorer",
418 - "dormir",
419 - "doseur",
420 - "douane",
421 - "double",
422 - "douche",
423 - "douleur",
424 - "doute",
425 - "doux",
426 - "douzaine",
427 - "draguer",
428 - "drame",
429 - "drap",
430 - "dresser",
431 - "droit",
432 - "duel",
433 - "dune",
434 - "duper",
435 - "durant",
436 - "durcir",
437 - "durer",
438 - "eaux",
439 - "effacer",
440 - "effet",
441 - "effort",
442 - "effrayant",
443 - "elle",
444 - "embrasser",
445 - "emmener",
446 - "emparer",
447 - "empire",
448 - "employer",
449 - "emporter",
450 - "enclos",
451 - "encore",
452 - "endive",
453 - "endormir",
454 - "endroit",
455 - "enduit",
456 - "enfant",
457 - "enfermer",
458 - "enfin",
459 - "enfler",
460 - "enfoncer",
461 - "enfuir",
462 - "engager",
463 - "engin",
464 - "enjeu",
465 - "enlever",
466 - "ennemi",
467 - "ennui",
468 - "ensemble",
469 - "ensuite",
470 - "entamer",
471 - "entendre",
472 - "entier",
473 - "entourer",
474 - "entre",
475 - "envelopper",
476 - "envie",
477 - "envoyer",
478 - "erreur",
479 - "escalier",
480 - "espace",
481 - "espoir",
482 - "esprit",
483 - "essai",
484 - "essor",
485 - "essuyer",
486 - "estimer",
487 - "exact",
488 - "examiner",
489 - "excuse",
490 - "exemple",
491 - "exiger",
492 - "exil",
493 - "exister",
494 - "exode",
495 - "expliquer",
496 - "exposer",
497 - "exprimer",
498 - "extase",
499 - "fable",
500 - "facette",
501 - "facile",
502 - "fade",
503 - "faible",
504 - "faim",
505 - "faire",
506 - "fait",
507 - "falloir",
508 - "famille",
509 - "faner",
510 - "farce",
511 - "farine",
512 - "fatigue",
513 - "faucon",
514 - "faune",
515 - "faute",
516 - "faux",
517 - "faveur",
518 - "favori",
519 - "faxer",
520 - "feinter",
521 - "femme",
522 - "fendre",
523 - "fente",
524 - "ferme",
525 - "festin",
526 - "feuille",
527 - "feutre",
528 - "fiable",
529 - "fibre",
530 - "ficher",
531 - "fier",
532 - "figer",
533 - "figure",
534 - "filet",
535 - "fille",
536 - "filmer",
537 - "fils",
538 - "filtre",
539 - "final",
540 - "finesse",
541 - "finir",
542 - "fiole",
543 - "firme",
544 - "fixe",
545 - "flacon",
546 - "flair",
547 - "flamme",
548 - "flan",
549 - "flaque",
550 - "fleur",
551 - "flocon",
552 - "flore",
553 - "flot",
554 - "flou",
555 - "fluide",
556 - "fluor",
557 - "flux",
558 - "focus",
559 - "foin",
560 - "foire",
561 - "foison",
562 - "folie",
563 - "fonction",
564 - "fondre",
565 - "fonte",
566 - "force",
567 - "forer",
568 - "forger",
569 - "forme",
570 - "fort",
571 - "fosse",
572 - "fouet",
573 - "fouine",
574 - "foule",
575 - "four",
576 - "foyer",
577 - "frais",
578 - "franc",
579 - "frapper",
580 - "freiner",
581 - "frimer",
582 - "friser",
583 - "frite",
584 - "froid",
585 - "froncer",
586 - "fruit",
587 - "fugue",
588 - "fuir",
589 - "fuite",
590 - "fumer",
591 - "fureur",
592 - "furieux",
593 - "fuser",
594 - "fusil",
595 - "futile",
596 - "futur",
597 - "gagner",
598 - "gain",
599 - "gala",
600 - "galet",
601 - "galop",
602 - "gamme",
603 - "gant",
604 - "garage",
605 - "garde",
606 - "garer",
607 - "gauche",
608 - "gaufre",
609 - "gaule",
610 - "gaver",
611 - "gazon",
612 - "geler",
613 - "genou",
614 - "genre",
615 - "gens",
616 - "gercer",
617 - "germer",
618 - "geste",
619 - "gibier",
620 - "gicler",
621 - "gilet",
622 - "girafe",
623 - "givre",
624 - "glace",
625 - "glisser",
626 - "globe",
627 - "gloire",
628 - "gluant",
629 - "gober",
630 - "golf",
631 - "gommer",
632 - "gorge",
633 - "gosier",
634 - "goutte",
635 - "grain",
636 - "gramme",
637 - "grand",
638 - "gras",
639 - "grave",
640 - "gredin",
641 - "griffure",
642 - "griller",
643 - "gris",
644 - "gronder",
645 - "gros",
646 - "grotte",
647 - "groupe",
648 - "grue",
649 - "guerrier",
650 - "guetter",
651 - "guider",
652 - "guise",
653 - "habiter",
654 - "hache",
655 - "haie",
656 - "haine",
657 - "halte",
658 - "hamac",
659 - "hanche",
660 - "hangar",
661 - "hanter",
662 - "haras",
663 - "hareng",
664 - "harpe",
665 - "hasard",
666 - "hausse",
667 - "haut",
668 - "havre",
669 - "herbe",
670 - "heure",
671 - "hibou",
672 - "hier",
673 - "histoire",
674 - "hiver",
675 - "hochet",
676 - "homme",
677 - "honneur",
678 - "honte",
679 - "horde",
680 - "horizon",
681 - "hormone",
682 - "houle",
683 - "housse",
684 - "hublot",
685 - "huile",
686 - "huit",
687 - "humain",
688 - "humble",
689 - "humide",
690 - "humour",
691 - "hurler",
692 - "idole",
693 - "igloo",
694 - "ignorer",
695 - "illusion",
696 - "image",
697 - "immense",
698 - "immobile",
699 - "imposer",
700 - "impression",
701 - "incapable",
702 - "inconnu",
703 - "index",
704 - "indiquer",
705 - "infime",
706 - "injure",
707 - "inox",
708 - "inspirer",
709 - "instant",
710 - "intention",
711 - "intime",
712 - "inutile",
713 - "inventer",
714 - "inviter",
715 - "iode",
716 - "iris",
717 - "issue",
718 - "ivre",
719 - "jade",
720 - "jadis",
721 - "jamais",
722 - "jambe",
723 - "janvier",
724 - "jardin",
725 - "jauge",
726 - "jaunisse",
727 - "jeter",
728 - "jeton",
729 - "jeudi",
730 - "jeune",
731 - "joie",
732 - "joindre",
733 - "joli",
734 - "joueur",
735 - "journal",
736 - "judo",
737 - "juge",
738 - "juillet",
739 - "juin",
740 - "jument",
741 - "jungle",
742 - "jupe",
743 - "jupon",
744 - "jurer",
745 - "juron",
746 - "jury",
747 - "jusque",
748 - "juste",
749 - "kayak",
750 - "ketchup",
751 - "kilo",
752 - "kiwi",
753 - "koala",
754 - "label",
755 - "lacet",
756 - "lacune",
757 - "laine",
758 - "laisse",
759 - "lait",
760 - "lame",
761 - "lancer",
762 - "lande",
763 - "laque",
764 - "lard",
765 - "largeur",
766 - "larme",
767 - "larve",
768 - "lasso",
769 - "laver",
770 - "lendemain",
771 - "lentement",
772 - "lequel",
773 - "lettre",
774 - "leur",
775 - "lever",
776 - "levure",
777 - "liane",
778 - "libre",
779 - "lien",
780 - "lier",
781 - "lieutenant",
782 - "ligne",
783 - "ligoter",
784 - "liguer",
785 - "limace",
786 - "limer",
787 - "limite",
788 - "lingot",
789 - "lion",
790 - "lire",
791 - "lisser",
792 - "litre",
793 - "livre",
794 - "lobe",
795 - "local",
796 - "logis",
797 - "loin",
798 - "loisir",
799 - "long",
800 - "loque",
801 - "lors",
802 - "lotus",
803 - "louer",
804 - "loup",
805 - "lourd",
806 - "louve",
807 - "loyer",
808 - "lubie",
809 - "lucide",
810 - "lueur",
811 - "luge",
812 - "luire",
813 - "lundi",
814 - "lune",
815 - "lustre",
816 - "lutin",
817 - "lutte",
818 - "luxe",
819 - "machine",
820 - "madame",
821 - "magie",
822 - "magnifique",
823 - "magot",
824 - "maigre",
825 - "main",
826 - "mairie",
827 - "maison",
828 - "malade",
829 - "malheur",
830 - "malin",
831 - "manche",
832 - "manger",
833 - "manier",
834 - "manoir",
835 - "manquer",
836 - "marche",
837 - "mardi",
838 - "marge",
839 - "mariage",
840 - "marquer",
841 - "mars",
842 - "masque",
843 - "masse",
844 - "matin",
845 - "mauvais",
846 - "meilleur",
847 - "melon",
848 - "membre",
849 - "menacer",
850 - "mener",
851 - "mensonge",
852 - "mentir",
853 - "menu",
854 - "merci",
855 - "merlu",
856 - "mesure",
857 - "mettre",
858 - "meuble",
859 - "meunier",
860 - "meute",
861 - "miche",
862 - "micro",
863 - "midi",
864 - "miel",
865 - "miette",
866 - "mieux",
867 - "milieu",
868 - "mille",
869 - "mimer",
870 - "mince",
871 - "mineur",
872 - "ministre",
873 - "minute",
874 - "mirage",
875 - "miroir",
876 - "miser",
877 - "mite",
878 - "mixte",
879 - "mobile",
880 - "mode",
881 - "module",
882 - "moins",
883 - "mois",
884 - "moment",
885 - "momie",
886 - "monde",
887 - "monsieur",
888 - "monter",
889 - "moquer",
890 - "moral",
891 - "morceau",
892 - "mordre",
893 - "morose",
894 - "morse",
895 - "mortier",
896 - "morue",
897 - "motif",
898 - "motte",
899 - "moudre",
900 - "moule",
901 - "mourir",
902 - "mousse",
903 - "mouton",
904 - "mouvement",
905 - "moyen",
906 - "muer",
907 - "muette",
908 - "mugir",
909 - "muguet",
910 - "mulot",
911 - "multiple",
912 - "munir",
913 - "muret",
914 - "muse",
915 - "musique",
916 - "muter",
917 - "nacre",
918 - "nager",
919 - "nain",
920 - "naissance",
921 - "narine",
922 - "narrer",
923 - "naseau",
924 - "nasse",
925 - "nation",
926 - "nature",
927 - "naval",
928 - "navet",
929 - "naviguer",
930 - "navrer",
931 - "neige",
932 - "nerf",
933 - "nerveux",
934 - "neuf",
935 - "neutre",
936 - "neuve",
937 - "neveu",
938 - "niche",
939 - "nier",
940 - "niveau",
941 - "noble",
942 - "noce",
943 - "nocif",
944 - "noir",
945 - "nomade",
946 - "nombre",
947 - "nommer",
948 - "nord",
949 - "norme",
950 - "notaire",
951 - "notice",
952 - "notre",
953 - "nouer",
954 - "nougat",
955 - "nourrir",
956 - "nous",
957 - "nouveau",
958 - "novice",
959 - "noyade",
960 - "noyer",
961 - "nuage",
962 - "nuance",
963 - "nuire",
964 - "nuit",
965 - "nulle",
966 - "nuque",
967 - "oasis",
968 - "objet",
969 - "obliger",
970 - "obscur",
971 - "observer",
972 - "obtenir",
973 - "obus",
974 - "occasion",
975 - "occuper",
976 - "ocre",
977 - "octet",
978 - "odeur",
979 - "odorat",
980 - "offense",
981 - "officier",
982 - "offrir",
983 - "ogive",
984 - "oiseau",
985 - "olive",
986 - "ombre",
987 - "onctueux",
988 - "onduler",
989 - "ongle",
990 - "onze",
991 - "opter",
992 - "option",
993 - "orageux",
994 - "oral",
995 - "orange",
996 - "orbite",
997 - "ordinaire",
998 - "ordre",
999 - "oreille",
1000 - "organe",
1001 - "orgie",
1002 - "orgueil",
1003 - "orient",
1004 - "origan",
1005 - "orner",
1006 - "orteil",
1007 - "ortie",
1008 - "oser",
1009 - "osselet",
1010 - "otage",
1011 - "otarie",
1012 - "ouate",
1013 - "oublier",
1014 - "ouest",
1015 - "ours",
1016 - "outil",
1017 - "outre",
1018 - "ouvert",
1019 - "ouvrir",
1020 - "ovale",
1021 - "ozone",
1022 - "pacte",
1023 - "page",
1024 - "paille",
1025 - "pain",
1026 - "paire",
1027 - "paix",
1028 - "palace",
1029 - "palissade",
1030 - "palmier",
1031 - "palpiter",
1032 - "panda",
1033 - "panneau",
1034 - "papa",
1035 - "papier",
1036 - "paquet",
1037 - "parc",
1038 - "pardi",
1039 - "parfois",
1040 - "parler",
1041 - "parmi",
1042 - "parole",
1043 - "partir",
1044 - "parvenir",
1045 - "passer",
1046 - "pastel",
1047 - "patin",
1048 - "patron",
1049 - "paume",
1050 - "pause",
1051 - "pauvre",
1052 - "paver",
1053 - "pavot",
1054 - "payer",
1055 - "pays",
1056 - "peau",
1057 - "peigne",
1058 - "peinture",
1059 - "pelage",
1060 - "pelote",
1061 - "pencher",
1062 - "pendre",
1063 - "penser",
1064 - "pente",
1065 - "percer",
1066 - "perdu",
1067 - "perle",
1068 - "permettre",
1069 - "personne",
1070 - "perte",
1071 - "peser",
1072 - "pesticide",
1073 - "petit",
1074 - "peuple",
1075 - "peur",
1076 - "phase",
1077 - "photo",
1078 - "phrase",
1079 - "piano",
1080 - "pied",
1081 - "pierre",
1082 - "pieu",
1083 - "pile",
1084 - "pilier",
1085 - "pilote",
1086 - "pilule",
1087 - "piment",
1088 - "pincer",
1089 - "pinson",
1090 - "pinte",
1091 - "pion",
1092 - "piquer",
1093 - "pirate",
1094 - "pire",
1095 - "piste",
1096 - "piton",
1097 - "pitre",
1098 - "pivot",
1099 - "pizza",
1100 - "placer",
1101 - "plage",
1102 - "plaire",
1103 - "plan",
1104 - "plaque",
1105 - "plat",
1106 - "plein",
1107 - "pleurer",
1108 - "pliage",
1109 - "plier",
1110 - "plonger",
1111 - "plot",
1112 - "pluie",
1113 - "plume",
1114 - "plus",
1115 - "pneu",
1116 - "poche",
1117 - "podium",
1118 - "poids",
1119 - "poil",
1120 - "point",
1121 - "poire",
1122 - "poison",
1123 - "poitrine",
1124 - "poivre",
1125 - "police",
1126 - "pollen",
1127 - "pomme",
1128 - "pompier",
1129 - "poncer",
1130 - "pondre",
1131 - "pont",
1132 - "portion",
1133 - "poser",
1134 - "position",
1135 - "possible",
1136 - "poste",
1137 - "potage",
1138 - "potin",
1139 - "pouce",
1140 - "poudre",
1141 - "poulet",
1142 - "poumon",
1143 - "poupe",
1144 - "pour",
1145 - "pousser",
1146 - "poutre",
1147 - "pouvoir",
1148 - "prairie",
1149 - "premier",
1150 - "prendre",
1151 - "presque",
1152 - "preuve",
1153 - "prier",
1154 - "primeur",
1155 - "prince",
1156 - "prison",
1157 - "priver",
1158 - "prix",
1159 - "prochain",
1160 - "produire",
1161 - "profond",
1162 - "proie",
1163 - "projet",
1164 - "promener",
1165 - "prononcer",
1166 - "propre",
1167 - "prose",
1168 - "prouver",
1169 - "prune",
1170 - "public",
1171 - "puce",
1172 - "pudeur",
1173 - "puiser",
1174 - "pull",
1175 - "pulpe",
1176 - "puma",
1177 - "punir",
1178 - "purge",
1179 - "putois",
1180 - "quand",
1181 - "quartier",
1182 - "quasi",
1183 - "quatre",
1184 - "quel",
1185 - "question",
1186 - "queue",
1187 - "quiche",
1188 - "quille",
1189 - "quinze",
1190 - "quitter",
1191 - "quoi",
1192 - "rabais",
1193 - "raboter",
1194 - "race",
1195 - "racheter",
1196 - "racine",
1197 - "racler",
1198 - "raconter",
1199 - "radar",
1200 - "radio",
1201 - "rafale",
1202 - "rage",
1203 - "ragot",
1204 - "raideur",
1205 - "raie",
1206 - "rail",
1207 - "raison",
1208 - "ramasser",
1209 - "ramener",
1210 - "rampe",
1211 - "rance",
1212 - "rang",
1213 - "rapace",
1214 - "rapide",
1215 - "rapport",
1216 - "rarement",
1217 - "rasage",
1218 - "raser",
1219 - "rasoir",
1220 - "rassurer",
1221 - "rater",
1222 - "ratio",
1223 - "rature",
1224 - "ravage",
1225 - "ravir",
1226 - "rayer",
1227 - "rayon",
1228 - "rebond",
1229 - "recevoir",
1230 - "recherche",
1231 - "record",
1232 - "reculer",
1233 - "redevenir",
1234 - "refuser",
1235 - "regard",
1236 - "regretter",
1237 - "rein",
1238 - "rejeter",
1239 - "rejoindre",
1240 - "relation",
1241 - "relever",
1242 - "religion",
1243 - "remarquer",
1244 - "remettre",
1245 - "remise",
1246 - "remonter",
1247 - "remplir",
1248 - "remuer",
1249 - "rencontre",
1250 - "rendre",
1251 - "renier",
1252 - "renoncer",
1253 - "rentrer",
1254 - "renverser",
1255 - "repas",
1256 - "repli",
1257 - "reposer",
1258 - "reproche",
1259 - "requin",
1260 - "respect",
1261 - "ressembler",
1262 - "reste",
1263 - "retard",
1264 - "retenir",
1265 - "retirer",
1266 - "retour",
1267 - "retrouver",
1268 - "revenir",
1269 - "revoir",
1270 - "revue",
1271 - "rhume",
1272 - "ricaner",
1273 - "riche",
1274 - "rideau",
1275 - "ridicule",
1276 - "rien",
1277 - "rigide",
1278 - "rincer",
1279 - "rire",
1280 - "risquer",
1281 - "rituel",
1282 - "rivage",
1283 - "rive",
1284 - "robe",
1285 - "robot",
1286 - "robuste",
1287 - "rocade",
1288 - "roche",
1289 - "rodeur",
1290 - "rogner",
1291 - "roman",
1292 - "rompre",
1293 - "ronce",
1294 - "rondeur",
1295 - "ronger",
1296 - "roque",
1297 - "rose",
1298 - "rosir",
1299 - "rotation",
1300 - "rotule",
1301 - "roue",
1302 - "rouge",
1303 - "rouler",
1304 - "route",
1305 - "ruban",
1306 - "rubis",
1307 - "ruche",
1308 - "rude",
1309 - "ruelle",
1310 - "ruer",
1311 - "rugby",
1312 - "rugir",
1313 - "ruine",
1314 - "rumeur",
1315 - "rural",
1316 - "ruse",
1317 - "rustre",
1318 - "sable",
1319 - "sabot",
1320 - "sabre",
1321 - "sacre",
1322 - "sage",
1323 - "saint",
1324 - "saisir",
1325 - "salade",
1326 - "salive",
1327 - "salle",
1328 - "salon",
1329 - "salto",
1330 - "salut",
1331 - "salve",
1332 - "samba",
1333 - "sandale",
1334 - "sanguin",
1335 - "sapin",
1336 - "sarcasme",
1337 - "satisfaire",
1338 - "sauce",
1339 - "sauf",
1340 - "sauge",
1341 - "saule",
1342 - "sauna",
1343 - "sauter",
1344 - "sauver",
1345 - "savoir",
1346 - "science",
1347 - "scoop",
1348 - "score",
1349 - "second",
1350 - "secret",
1351 - "secte",
1352 - "seigneur",
1353 - "sein",
1354 - "seize",
1355 - "selle",
1356 - "selon",
1357 - "semaine",
1358 - "sembler",
1359 - "semer",
1360 - "semis",
1361 - "sensuel",
1362 - "sentir",
1363 - "sept",
1364 - "serpe",
1365 - "serrer",
1366 - "sertir",
1367 - "service",
1368 - "seuil",
1369 - "seulement",
1370 - "short",
1371 - "sien",
1372 - "sigle",
1373 - "signal",
1374 - "silence",
1375 - "silo",
1376 - "simple",
1377 - "singe",
1378 - "sinon",
1379 - "sinus",
1380 - "sioux",
1381 - "sirop",
1382 - "site",
1383 - "situation",
1384 - "skier",
1385 - "snob",
1386 - "sobre",
1387 - "social",
1388 - "socle",
1389 - "sodium",
1390 - "soigner",
1391 - "soir",
1392 - "soixante",
1393 - "soja",
1394 - "solaire",
1395 - "soldat",
1396 - "soleil",
1397 - "solide",
1398 - "solo",
1399 - "solvant",
1400 - "sombre",
1401 - "somme",
1402 - "somnoler",
1403 - "sondage",
1404 - "songeur",
1405 - "sonner",
1406 - "sorte",
1407 - "sosie",
1408 - "sottise",
1409 - "souci",
1410 - "soudain",
1411 - "souffrir",
1412 - "souhaiter",
1413 - "soulever",
1414 - "soumettre",
1415 - "soupe",
1416 - "sourd",
1417 - "soustraire",
1418 - "soutenir",
1419 - "souvent",
1420 - "soyeux",
1421 - "spectacle",
1422 - "sport",
1423 - "stade",
1424 - "stagiaire",
1425 - "stand",
1426 - "star",
1427 - "statue",
1428 - "stock",
1429 - "stop",
1430 - "store",
1431 - "style",
1432 - "suave",
1433 - "subir",
1434 - "sucre",
1435 - "suer",
1436 - "suffire",
1437 - "suie",
1438 - "suite",
1439 - "suivre",
1440 - "sujet",
1441 - "sulfite",
1442 - "supposer",
1443 - "surf",
1444 - "surprendre",
1445 - "surtout",
1446 - "surveiller",
1447 - "tabac",
1448 - "table",
1449 - "tabou",
1450 - "tache",
1451 - "tacler",
1452 - "tacot",
1453 - "tact",
1454 - "taie",
1455 - "taille",
1456 - "taire",
1457 - "talon",
1458 - "talus",
1459 - "tandis",
1460 - "tango",
1461 - "tanin",
1462 - "tant",
1463 - "taper",
1464 - "tapis",
1465 - "tard",
1466 - "tarif",
1467 - "tarot",
1468 - "tarte",
1469 - "tasse",
1470 - "taureau",
1471 - "taux",
1472 - "taverne",
1473 - "taxer",
1474 - "taxi",
1475 - "tellement",
1476 - "temple",
1477 - "tendre",
1478 - "tenir",
1479 - "tenter",
1480 - "tenu",
1481 - "terme",
1482 - "ternir",
1483 - "terre",
1484 - "test",
1485 - "texte",
1486 - "thym",
1487 - "tibia",
1488 - "tiers",
1489 - "tige",
1490 - "tipi",
1491 - "tique",
1492 - "tirer",
1493 - "tissu",
1494 - "titre",
1495 - "toast",
1496 - "toge",
1497 - "toile",
1498 - "toiser",
1499 - "toiture",
1500 - "tomber",
1501 - "tome",
1502 - "tonne",
1503 - "tonte",
1504 - "toque",
1505 - "torse",
1506 - "tortue",
1507 - "totem",
1508 - "toucher",
1509 - "toujours",
1510 - "tour",
1511 - "tousser",
1512 - "tout",
1513 - "toux",
1514 - "trace",
1515 - "train",
1516 - "trame",
1517 - "tranquille",
1518 - "travail",
1519 - "trembler",
1520 - "trente",
1521 - "tribu",
1522 - "trier",
1523 - "trio",
1524 - "tripe",
1525 - "triste",
1526 - "troc",
1527 - "trois",
1528 - "tromper",
1529 - "tronc",
1530 - "trop",
1531 - "trotter",
1532 - "trouer",
1533 - "truc",
1534 - "truite",
1535 - "tuba",
1536 - "tuer",
1537 - "tuile",
1538 - "turbo",
1539 - "tutu",
1540 - "tuyau",
1541 - "type",
1542 - "union",
1543 - "unique",
1544 - "unir",
1545 - "unisson",
1546 - "untel",
1547 - "urne",
1548 - "usage",
1549 - "user",
1550 - "usiner",
1551 - "usure",
1552 - "utile",
1553 - "vache",
1554 - "vague",
1555 - "vaincre",
1556 - "valeur",
1557 - "valoir",
1558 - "valser",
1559 - "valve",
1560 - "vampire",
1561 - "vaseux",
1562 - "vaste",
1563 - "veau",
1564 - "veille",
1565 - "veine",
1566 - "velours",
1567 - "velu",
1568 - "vendre",
1569 - "venir",
1570 - "vent",
1571 - "venue",
1572 - "verbe",
1573 - "verdict",
1574 - "version",
1575 - "vertige",
1576 - "verve",
1577 - "veste",
1578 - "veto",
1579 - "vexer",
1580 - "vice",
1581 - "victime",
1582 - "vide",
1583 - "vieil",
1584 - "vieux",
1585 - "vigie",
1586 - "vigne",
1587 - "ville",
1588 - "vingt",
1589 - "violent",
1590 - "virer",
1591 - "virus",
1592 - "visage",
1593 - "viser",
1594 - "visite",
1595 - "visuel",
1596 - "vitamine",
1597 - "vitrine",
1598 - "vivant",
1599 - "vivre",
1600 - "vocal",
1601 - "vodka",
1602 - "vogue",
1603 - "voici",
1604 - "voile",
1605 - "voir",
1606 - "voisin",
1607 - "voiture",
1608 - "volaille",
1609 - "volcan",
1610 - "voler",
1611 - "volt",
1612 - "votant",
1613 - "votre",
1614 - "vouer",
1615 - "vouloir",
1616 - "vous",
1617 - "voyage",
1618 - "voyou",
1619 - "vrac",
1620 - "vrai",
1621 - "yacht",
1622 - "yeti",
1623 - "yeux",
1624 - "yoga",
1625 - "zeste",
1626 - "zinc",
1627 - "zone",
1628 - "zoom"
1629 - ];
1630 -}
\ No newline at end of file
2 + static const words = [
3 + "abandon",
4 + "abattre",
5 + "aboi",
6 + "abolir",
7 + "aborder",
8 + "abri",
9 + "absence",
10 + "absolu",
11 + "abuser",
12 + "acacia",
13 + "acajou",
14 + "accent",
15 + "accord",
16 + "accrocher",
17 + "accuser",
18 + "acerbe",
19 + "achat",
20 + "acheter",
21 + "acide",
22 + "acier",
23 + "acquis",
24 + "acte",
25 + "action",
26 + "adage",
27 + "adepte",
28 + "adieu",
29 + "admettre",
30 + "admis",
31 + "adorer",
32 + "adresser",
33 + "aduler",
34 + "affaire",
35 + "affirmer",
36 + "afin",
37 + "agacer",
38 + "agent",
39 + "agir",
40 + "agiter",
41 + "agonie",
42 + "agrafe",
43 + "agrume",
44 + "aider",
45 + "aigle",
46 + "aigre",
47 + "aile",
48 + "ailleurs",
49 + "aimant",
50 + "aimer",
51 + "ainsi",
52 + "aise",
53 + "ajouter",
54 + "alarme",
55 + "album",
56 + "alcool",
57 + "alerte",
58 + "algue",
59 + "alibi",
60 + "aller",
61 + "allumer",
62 + "alors",
63 + "amande",
64 + "amener",
65 + "amie",
66 + "amorcer",
67 + "amour",
68 + "ample",
69 + "amuser",
70 + "ananas",
71 + "ancien",
72 + "anglais",
73 + "angoisse",
74 + "animal",
75 + "anneau",
76 + "annoncer",
77 + "apercevoir",
78 + "apparence",
79 + "appel",
80 + "apporter",
81 + "apprendre",
82 + "appuyer",
83 + "arbre",
84 + "arcade",
85 + "arceau",
86 + "arche",
87 + "ardeur",
88 + "argent",
89 + "argile",
90 + "aride",
91 + "arme",
92 + "armure",
93 + "arracher",
94 + "arriver",
95 + "article",
96 + "asile",
97 + "aspect",
98 + "assaut",
99 + "assez",
100 + "assister",
101 + "assurer",
102 + "astre",
103 + "astuce",
104 + "atlas",
105 + "atroce",
106 + "attacher",
107 + "attente",
108 + "attirer",
109 + "aube",
110 + "aucun",
111 + "audace",
112 + "auparavant",
113 + "auquel",
114 + "aurore",
115 + "aussi",
116 + "autant",
117 + "auteur",
118 + "autoroute",
119 + "autre",
120 + "aval",
121 + "avant",
122 + "avec",
123 + "avenir",
124 + "averse",
125 + "aveu",
126 + "avide",
127 + "avion",
128 + "avis",
129 + "avoir",
130 + "avouer",
131 + "avril",
132 + "azote",
133 + "azur",
134 + "badge",
135 + "bagage",
136 + "bague",
137 + "bain",
138 + "baisser",
139 + "balai",
140 + "balcon",
141 + "balise",
142 + "balle",
143 + "bambou",
144 + "banane",
145 + "banc",
146 + "bandage",
147 + "banjo",
148 + "banlieue",
149 + "bannir",
150 + "banque",
151 + "baobab",
152 + "barbe",
153 + "barque",
154 + "barrer",
155 + "bassine",
156 + "bataille",
157 + "bateau",
158 + "battre",
159 + "baver",
160 + "bavoir",
161 + "bazar",
162 + "beau",
163 + "beige",
164 + "berger",
165 + "besoin",
166 + "beurre",
167 + "biais",
168 + "biceps",
169 + "bidule",
170 + "bien",
171 + "bijou",
172 + "bilan",
173 + "billet",
174 + "blanc",
175 + "blason",
176 + "bleu",
177 + "bloc",
178 + "blond",
179 + "bocal",
180 + "boire",
181 + "boiserie",
182 + "boiter",
183 + "bonbon",
184 + "bondir",
185 + "bonheur",
186 + "bordure",
187 + "borgne",
188 + "borner",
189 + "bosse",
190 + "bouche",
191 + "bouder",
192 + "bouger",
193 + "boule",
194 + "bourse",
195 + "bout",
196 + "boxe",
197 + "brader",
198 + "braise",
199 + "branche",
200 + "braquer",
201 + "bras",
202 + "brave",
203 + "brebis",
204 + "brevet",
205 + "brider",
206 + "briller",
207 + "brin",
208 + "brique",
209 + "briser",
210 + "broche",
211 + "broder",
212 + "bronze",
213 + "brosser",
214 + "brouter",
215 + "bruit",
216 + "brute",
217 + "budget",
218 + "buffet",
219 + "bulle",
220 + "bureau",
221 + "buriner",
222 + "buste",
223 + "buter",
224 + "butiner",
225 + "cabas",
226 + "cabinet",
227 + "cabri",
228 + "cacao",
229 + "cacher",
230 + "cadeau",
231 + "cadre",
232 + "cage",
233 + "caisse",
234 + "caler",
235 + "calme",
236 + "camarade",
237 + "camion",
238 + "campagne",
239 + "canal",
240 + "canif",
241 + "capable",
242 + "capot",
243 + "carat",
244 + "caresser",
245 + "carie",
246 + "carpe",
247 + "cartel",
248 + "casier",
249 + "casque",
250 + "casserole",
251 + "cause",
252 + "cavale",
253 + "cave",
254 + "ceci",
255 + "cela",
256 + "celui",
257 + "cendre",
258 + "cent",
259 + "cependant",
260 + "cercle",
261 + "cerise",
262 + "cerner",
263 + "certes",
264 + "cerveau",
265 + "cesser",
266 + "chacun",
267 + "chair",
268 + "chaleur",
269 + "chamois",
270 + "chanson",
271 + "chaque",
272 + "charge",
273 + "chasse",
274 + "chat",
275 + "chaud",
276 + "chef",
277 + "chemin",
278 + "cheveu",
279 + "chez",
280 + "chicane",
281 + "chien",
282 + "chiffre",
283 + "chiner",
284 + "chiot",
285 + "chlore",
286 + "choc",
287 + "choix",
288 + "chose",
289 + "chou",
290 + "chute",
291 + "cibler",
292 + "cidre",
293 + "ciel",
294 + "cigale",
295 + "cinq",
296 + "cintre",
297 + "cirage",
298 + "cirque",
299 + "ciseau",
300 + "citation",
301 + "citer",
302 + "citron",
303 + "civet",
304 + "clairon",
305 + "clan",
306 + "classe",
307 + "clavier",
308 + "clef",
309 + "climat",
310 + "cloche",
311 + "cloner",
312 + "clore",
313 + "clos",
314 + "clou",
315 + "club",
316 + "cobra",
317 + "cocon",
318 + "coiffer",
319 + "coin",
320 + "colline",
321 + "colon",
322 + "combat",
323 + "comme",
324 + "compte",
325 + "conclure",
326 + "conduire",
327 + "confier",
328 + "connu",
329 + "conseil",
330 + "contre",
331 + "convenir",
332 + "copier",
333 + "cordial",
334 + "cornet",
335 + "corps",
336 + "cosmos",
337 + "coton",
338 + "couche",
339 + "coude",
340 + "couler",
341 + "coupure",
342 + "cour",
343 + "couteau",
344 + "couvrir",
345 + "crabe",
346 + "crainte",
347 + "crampe",
348 + "cran",
349 + "creuser",
350 + "crever",
351 + "crier",
352 + "crime",
353 + "crin",
354 + "crise",
355 + "crochet",
356 + "croix",
357 + "cruel",
358 + "cuisine",
359 + "cuite",
360 + "culot",
361 + "culte",
362 + "cumul",
363 + "cure",
364 + "curieux",
365 + "cuve",
366 + "dame",
367 + "danger",
368 + "dans",
369 + "davantage",
370 + "debout",
371 + "dedans",
372 + "dehors",
373 + "delta",
374 + "demain",
375 + "demeurer",
376 + "demi",
377 + "dense",
378 + "dent",
379 + "depuis",
380 + "dernier",
381 + "descendre",
382 + "dessus",
383 + "destin",
384 + "dette",
385 + "deuil",
386 + "deux",
387 + "devant",
388 + "devenir",
389 + "devin",
390 + "devoir",
391 + "dicton",
392 + "dieu",
393 + "difficile",
394 + "digestion",
395 + "digue",
396 + "diluer",
397 + "dimanche",
398 + "dinde",
399 + "diode",
400 + "dire",
401 + "diriger",
402 + "discours",
403 + "disposer",
404 + "distance",
405 + "divan",
406 + "divers",
407 + "docile",
408 + "docteur",
409 + "dodu",
410 + "dogme",
411 + "doigt",
412 + "dominer",
413 + "donation",
414 + "donjon",
415 + "donner",
416 + "dopage",
417 + "dorer",
418 + "dormir",
419 + "doseur",
420 + "douane",
421 + "double",
422 + "douche",
423 + "douleur",
424 + "doute",
425 + "doux",
426 + "douzaine",
427 + "draguer",
428 + "drame",
429 + "drap",
430 + "dresser",
431 + "droit",
432 + "duel",
433 + "dune",
434 + "duper",
435 + "durant",
436 + "durcir",
437 + "durer",
438 + "eaux",
439 + "effacer",
440 + "effet",
441 + "effort",
442 + "effrayant",
443 + "elle",
444 + "embrasser",
445 + "emmener",
446 + "emparer",
447 + "empire",
448 + "employer",
449 + "emporter",
450 + "enclos",
451 + "encore",
452 + "endive",
453 + "endormir",
454 + "endroit",
455 + "enduit",
456 + "enfant",
457 + "enfermer",
458 + "enfin",
459 + "enfler",
460 + "enfoncer",
461 + "enfuir",
462 + "engager",
463 + "engin",
464 + "enjeu",
465 + "enlever",
466 + "ennemi",
467 + "ennui",
468 + "ensemble",
469 + "ensuite",
470 + "entamer",
471 + "entendre",
472 + "entier",
473 + "entourer",
474 + "entre",
475 + "envelopper",
476 + "envie",
477 + "envoyer",
478 + "erreur",
479 + "escalier",
480 + "espace",
481 + "espoir",
482 + "esprit",
483 + "essai",
484 + "essor",
485 + "essuyer",
486 + "estimer",
487 + "exact",
488 + "examiner",
489 + "excuse",
490 + "exemple",
491 + "exiger",
492 + "exil",
493 + "exister",
494 + "exode",
495 + "expliquer",
496 + "exposer",
497 + "exprimer",
498 + "extase",
499 + "fable",
500 + "facette",
501 + "facile",
502 + "fade",
503 + "faible",
504 + "faim",
505 + "faire",
506 + "fait",
507 + "falloir",
508 + "famille",
509 + "faner",
510 + "farce",
511 + "farine",
512 + "fatigue",
513 + "faucon",
514 + "faune",
515 + "faute",
516 + "faux",
517 + "faveur",
518 + "favori",
519 + "faxer",
520 + "feinter",
521 + "femme",
522 + "fendre",
523 + "fente",
524 + "ferme",
525 + "festin",
526 + "feuille",
527 + "feutre",
528 + "fiable",
529 + "fibre",
530 + "ficher",
531 + "fier",
532 + "figer",
533 + "figure",
534 + "filet",
535 + "fille",
536 + "filmer",
537 + "fils",
538 + "filtre",
539 + "final",
540 + "finesse",
541 + "finir",
542 + "fiole",
543 + "firme",
544 + "fixe",
545 + "flacon",
546 + "flair",
547 + "flamme",
548 + "flan",
549 + "flaque",
550 + "fleur",
551 + "flocon",
552 + "flore",
553 + "flot",
554 + "flou",
555 + "fluide",
556 + "fluor",
557 + "flux",
558 + "focus",
559 + "foin",
560 + "foire",
561 + "foison",
562 + "folie",
563 + "fonction",
564 + "fondre",
565 + "fonte",
566 + "force",
567 + "forer",
568 + "forger",
569 + "forme",
570 + "fort",
571 + "fosse",
572 + "fouet",
573 + "fouine",
574 + "foule",
575 + "four",
576 + "foyer",
577 + "frais",
578 + "franc",
579 + "frapper",
580 + "freiner",
581 + "frimer",
582 + "friser",
583 + "frite",
584 + "froid",
585 + "froncer",
586 + "fruit",
587 + "fugue",
588 + "fuir",
589 + "fuite",
590 + "fumer",
591 + "fureur",
592 + "furieux",
593 + "fuser",
594 + "fusil",
595 + "futile",
596 + "futur",
597 + "gagner",
598 + "gain",
599 + "gala",
600 + "galet",
601 + "galop",
602 + "gamme",
603 + "gant",
604 + "garage",
605 + "garde",
606 + "garer",
607 + "gauche",
608 + "gaufre",
609 + "gaule",
610 + "gaver",
611 + "gazon",
612 + "geler",
613 + "genou",
614 + "genre",
615 + "gens",
616 + "gercer",
617 + "germer",
618 + "geste",
619 + "gibier",
620 + "gicler",
621 + "gilet",
622 + "girafe",
623 + "givre",
624 + "glace",
625 + "glisser",
626 + "globe",
627 + "gloire",
628 + "gluant",
629 + "gober",
630 + "golf",
631 + "gommer",
632 + "gorge",
633 + "gosier",
634 + "goutte",
635 + "grain",
636 + "gramme",
637 + "grand",
638 + "gras",
639 + "grave",
640 + "gredin",
641 + "griffure",
642 + "griller",
643 + "gris",
644 + "gronder",
645 + "gros",
646 + "grotte",
647 + "groupe",
648 + "grue",
649 + "guerrier",
650 + "guetter",
651 + "guider",
652 + "guise",
653 + "habiter",
654 + "hache",
655 + "haie",
656 + "haine",
657 + "halte",
658 + "hamac",
659 + "hanche",
660 + "hangar",
661 + "hanter",
662 + "haras",
663 + "hareng",
664 + "harpe",
665 + "hasard",
666 + "hausse",
667 + "haut",
668 + "havre",
669 + "herbe",
670 + "heure",
671 + "hibou",
672 + "hier",
673 + "histoire",
674 + "hiver",
675 + "hochet",
676 + "homme",
677 + "honneur",
678 + "honte",
679 + "horde",
680 + "horizon",
681 + "hormone",
682 + "houle",
683 + "housse",
684 + "hublot",
685 + "huile",
686 + "huit",
687 + "humain",
688 + "humble",
689 + "humide",
690 + "humour",
691 + "hurler",
692 + "idole",
693 + "igloo",
694 + "ignorer",
695 + "illusion",
696 + "image",
697 + "immense",
698 + "immobile",
699 + "imposer",
700 + "impression",
701 + "incapable",
702 + "inconnu",
703 + "index",
704 + "indiquer",
705 + "infime",
706 + "injure",
707 + "inox",
708 + "inspirer",
709 + "instant",
710 + "intention",
711 + "intime",
712 + "inutile",
713 + "inventer",
714 + "inviter",
715 + "iode",
716 + "iris",
717 + "issue",
718 + "ivre",
719 + "jade",
720 + "jadis",
721 + "jamais",
722 + "jambe",
723 + "janvier",
724 + "jardin",
725 + "jauge",
726 + "jaunisse",
727 + "jeter",
728 + "jeton",
729 + "jeudi",
730 + "jeune",
731 + "joie",
732 + "joindre",
733 + "joli",
734 + "joueur",
735 + "journal",
736 + "judo",
737 + "juge",
738 + "juillet",
739 + "juin",
740 + "jument",
741 + "jungle",
742 + "jupe",
743 + "jupon",
744 + "jurer",
745 + "juron",
746 + "jury",
747 + "jusque",
748 + "juste",
749 + "kayak",
750 + "ketchup",
751 + "kilo",
752 + "kiwi",
753 + "koala",
754 + "label",
755 + "lacet",
756 + "lacune",
757 + "laine",
758 + "laisse",
759 + "lait",
760 + "lame",
761 + "lancer",
762 + "lande",
763 + "laque",
764 + "lard",
765 + "largeur",
766 + "larme",
767 + "larve",
768 + "lasso",
769 + "laver",
770 + "lendemain",
771 + "lentement",
772 + "lequel",
773 + "lettre",
774 + "leur",
775 + "lever",
776 + "levure",
777 + "liane",
778 + "libre",
779 + "lien",
780 + "lier",
781 + "lieutenant",
782 + "ligne",
783 + "ligoter",
784 + "liguer",
785 + "limace",
786 + "limer",
787 + "limite",
788 + "lingot",
789 + "lion",
790 + "lire",
791 + "lisser",
792 + "litre",
793 + "livre",
794 + "lobe",
795 + "local",
796 + "logis",
797 + "loin",
798 + "loisir",
799 + "long",
800 + "loque",
801 + "lors",
802 + "lotus",
803 + "louer",
804 + "loup",
805 + "lourd",
806 + "louve",
807 + "loyer",
808 + "lubie",
809 + "lucide",
810 + "lueur",
811 + "luge",
812 + "luire",
813 + "lundi",
814 + "lune",
815 + "lustre",
816 + "lutin",
817 + "lutte",
818 + "luxe",
819 + "machine",
820 + "madame",
821 + "magie",
822 + "magnifique",
823 + "magot",
824 + "maigre",
825 + "main",
826 + "mairie",
827 + "maison",
828 + "malade",
829 + "malheur",
830 + "malin",
831 + "manche",
832 + "manger",
833 + "manier",
834 + "manoir",
835 + "manquer",
836 + "marche",
837 + "mardi",
838 + "marge",
839 + "mariage",
840 + "marquer",
841 + "mars",
842 + "masque",
843 + "masse",
844 + "matin",
845 + "mauvais",
846 + "meilleur",
847 + "melon",
848 + "membre",
849 + "menacer",
850 + "mener",
851 + "mensonge",
852 + "mentir",
853 + "menu",
854 + "merci",
855 + "merlu",
856 + "mesure",
857 + "mettre",
858 + "meuble",
859 + "meunier",
860 + "meute",
861 + "miche",
862 + "micro",
863 + "midi",
864 + "miel",
865 + "miette",
866 + "mieux",
867 + "milieu",
868 + "mille",
869 + "mimer",
870 + "mince",
871 + "mineur",
872 + "ministre",
873 + "minute",
874 + "mirage",
875 + "miroir",
876 + "miser",
877 + "mite",
878 + "mixte",
879 + "mobile",
880 + "mode",
881 + "module",
882 + "moins",
883 + "mois",
884 + "moment",
885 + "momie",
886 + "monde",
887 + "monsieur",
888 + "monter",
889 + "moquer",
890 + "moral",
891 + "morceau",
892 + "mordre",
893 + "morose",
894 + "morse",
895 + "mortier",
896 + "morue",
897 + "motif",
898 + "motte",
899 + "moudre",
900 + "moule",
901 + "mourir",
902 + "mousse",
903 + "mouton",
904 + "mouvement",
905 + "moyen",
906 + "muer",
907 + "muette",
908 + "mugir",
909 + "muguet",
910 + "mulot",
911 + "multiple",
912 + "munir",
913 + "muret",
914 + "muse",
915 + "musique",
916 + "muter",
917 + "nacre",
918 + "nager",
919 + "nain",
920 + "naissance",
921 + "narine",
922 + "narrer",
923 + "naseau",
924 + "nasse",
925 + "nation",
926 + "nature",
927 + "naval",
928 + "navet",
929 + "naviguer",
930 + "navrer",
931 + "neige",
932 + "nerf",
933 + "nerveux",
934 + "neuf",
935 + "neutre",
936 + "neuve",
937 + "neveu",
938 + "niche",
939 + "nier",
940 + "niveau",
941 + "noble",
942 + "noce",
943 + "nocif",
944 + "noir",
945 + "nomade",
946 + "nombre",
947 + "nommer",
948 + "nord",
949 + "norme",
950 + "notaire",
951 + "notice",
952 + "notre",
953 + "nouer",
954 + "nougat",
955 + "nourrir",
956 + "nous",
957 + "nouveau",
958 + "novice",
959 + "noyade",
960 + "noyer",
961 + "nuage",
962 + "nuance",
963 + "nuire",
964 + "nuit",
965 + "nulle",
966 + "nuque",
967 + "oasis",
968 + "objet",
969 + "obliger",
970 + "obscur",
971 + "observer",
972 + "obtenir",
973 + "obus",
974 + "occasion",
975 + "occuper",
976 + "ocre",
977 + "octet",
978 + "odeur",
979 + "odorat",
980 + "offense",
981 + "officier",
982 + "offrir",
983 + "ogive",
984 + "oiseau",
985 + "olive",
986 + "ombre",
987 + "onctueux",
988 + "onduler",
989 + "ongle",
990 + "onze",
991 + "opter",
992 + "option",
993 + "orageux",
994 + "oral",
995 + "orange",
996 + "orbite",
997 + "ordinaire",
998 + "ordre",
999 + "oreille",
1000 + "organe",
1001 + "orgie",
1002 + "orgueil",
1003 + "orient",
1004 + "origan",
1005 + "orner",
1006 + "orteil",
1007 + "ortie",
1008 + "oser",
1009 + "osselet",
1010 + "otage",
1011 + "otarie",
1012 + "ouate",
1013 + "oublier",
1014 + "ouest",
1015 + "ours",
1016 + "outil",
1017 + "outre",
1018 + "ouvert",
1019 + "ouvrir",
1020 + "ovale",
1021 + "ozone",
1022 + "pacte",
1023 + "page",
1024 + "paille",
1025 + "pain",
1026 + "paire",
1027 + "paix",
1028 + "palace",
1029 + "palissade",
1030 + "palmier",
1031 + "palpiter",
1032 + "panda",
1033 + "panneau",
1034 + "papa",
1035 + "papier",
1036 + "paquet",
1037 + "parc",
1038 + "pardi",
1039 + "parfois",
1040 + "parler",
1041 + "parmi",
1042 + "parole",
1043 + "partir",
1044 + "parvenir",
1045 + "passer",
1046 + "pastel",
1047 + "patin",
1048 + "patron",
1049 + "paume",
1050 + "pause",
1051 + "pauvre",
1052 + "paver",
1053 + "pavot",
1054 + "payer",
1055 + "pays",
1056 + "peau",
1057 + "peigne",
1058 + "peinture",
1059 + "pelage",
1060 + "pelote",
1061 + "pencher",
1062 + "pendre",
1063 + "penser",
1064 + "pente",
1065 + "percer",
1066 + "perdu",
1067 + "perle",
1068 + "permettre",
1069 + "personne",
1070 + "perte",
1071 + "peser",
1072 + "pesticide",
1073 + "petit",
1074 + "peuple",
1075 + "peur",
1076 + "phase",
1077 + "photo",
1078 + "phrase",
1079 + "piano",
1080 + "pied",
1081 + "pierre",
1082 + "pieu",
1083 + "pile",
1084 + "pilier",
1085 + "pilote",
1086 + "pilule",
1087 + "piment",
1088 + "pincer",
1089 + "pinson",
1090 + "pinte",
1091 + "pion",
1092 + "piquer",
1093 + "pirate",
1094 + "pire",
1095 + "piste",
1096 + "piton",
1097 + "pitre",
1098 + "pivot",
1099 + "pizza",
1100 + "placer",
1101 + "plage",
1102 + "plaire",
1103 + "plan",
1104 + "plaque",
1105 + "plat",
1106 + "plein",
1107 + "pleurer",
1108 + "pliage",
1109 + "plier",
1110 + "plonger",
1111 + "plot",
1112 + "pluie",
1113 + "plume",
1114 + "plus",
1115 + "pneu",
1116 + "poche",
1117 + "podium",
1118 + "poids",
1119 + "poil",
1120 + "point",
1121 + "poire",
1122 + "poison",
1123 + "poitrine",
1124 + "poivre",
1125 + "police",
1126 + "pollen",
1127 + "pomme",
1128 + "pompier",
1129 + "poncer",
1130 + "pondre",
1131 + "pont",
1132 + "portion",
1133 + "poser",
1134 + "position",
1135 + "possible",
1136 + "poste",
1137 + "potage",
1138 + "potin",
1139 + "pouce",
1140 + "poudre",
1141 + "poulet",
1142 + "poumon",
1143 + "poupe",
1144 + "pour",
1145 + "pousser",
1146 + "poutre",
1147 + "pouvoir",
1148 + "prairie",
1149 + "premier",
1150 + "prendre",
1151 + "presque",
1152 + "preuve",
1153 + "prier",
1154 + "primeur",
1155 + "prince",
1156 + "prison",
1157 + "priver",
1158 + "prix",
1159 + "prochain",
1160 + "produire",
1161 + "profond",
1162 + "proie",
1163 + "projet",
1164 + "promener",
1165 + "prononcer",
1166 + "propre",
1167 + "prose",
1168 + "prouver",
1169 + "prune",
1170 + "public",
1171 + "puce",
1172 + "pudeur",
1173 + "puiser",
1174 + "pull",
1175 + "pulpe",
1176 + "puma",
1177 + "punir",
1178 + "purge",
1179 + "putois",
1180 + "quand",
1181 + "quartier",
1182 + "quasi",
1183 + "quatre",
1184 + "quel",
1185 + "question",
1186 + "queue",
1187 + "quiche",
1188 + "quille",
1189 + "quinze",
1190 + "quitter",
1191 + "quoi",
1192 + "rabais",
1193 + "raboter",
1194 + "race",
1195 + "racheter",
1196 + "racine",
1197 + "racler",
1198 + "raconter",
1199 + "radar",
1200 + "radio",
1201 + "rafale",
1202 + "rage",
1203 + "ragot",
1204 + "raideur",
1205 + "raie",
1206 + "rail",
1207 + "raison",
1208 + "ramasser",
1209 + "ramener",
1210 + "rampe",
1211 + "rance",
1212 + "rang",
1213 + "rapace",
1214 + "rapide",
1215 + "rapport",
1216 + "rarement",
1217 + "rasage",
1218 + "raser",
1219 + "rasoir",
1220 + "rassurer",
1221 + "rater",
1222 + "ratio",
1223 + "rature",
1224 + "ravage",
1225 + "ravir",
1226 + "rayer",
1227 + "rayon",
1228 + "rebond",
1229 + "recevoir",
1230 + "recherche",
1231 + "record",
1232 + "reculer",
1233 + "redevenir",
1234 + "refuser",
1235 + "regard",
1236 + "regretter",
1237 + "rein",
1238 + "rejeter",
1239 + "rejoindre",
1240 + "relation",
1241 + "relever",
1242 + "religion",
1243 + "remarquer",
1244 + "remettre",
1245 + "remise",
1246 + "remonter",
1247 + "remplir",
1248 + "remuer",
1249 + "rencontre",
1250 + "rendre",
1251 + "renier",
1252 + "renoncer",
1253 + "rentrer",
1254 + "renverser",
1255 + "repas",
1256 + "repli",
1257 + "reposer",
1258 + "reproche",
1259 + "requin",
1260 + "respect",
1261 + "ressembler",
1262 + "reste",
1263 + "retard",
1264 + "retenir",
1265 + "retirer",
1266 + "retour",
1267 + "retrouver",
1268 + "revenir",
1269 + "revoir",
1270 + "revue",
1271 + "rhume",
1272 + "ricaner",
1273 + "riche",
1274 + "rideau",
1275 + "ridicule",
1276 + "rien",
1277 + "rigide",
1278 + "rincer",
1279 + "rire",
1280 + "risquer",
1281 + "rituel",
1282 + "rivage",
1283 + "rive",
1284 + "robe",
1285 + "robot",
1286 + "robuste",
1287 + "rocade",
1288 + "roche",
1289 + "rodeur",
1290 + "rogner",
1291 + "roman",
1292 + "rompre",
1293 + "ronce",
1294 + "rondeur",
1295 + "ronger",
1296 + "roque",
1297 + "rose",
1298 + "rosir",
1299 + "rotation",
1300 + "rotule",
1301 + "roue",
1302 + "rouge",
1303 + "rouler",
1304 + "route",
1305 + "ruban",
1306 + "rubis",
1307 + "ruche",
1308 + "rude",
1309 + "ruelle",
1310 + "ruer",
1311 + "rugby",
1312 + "rugir",
1313 + "ruine",
1314 + "rumeur",
1315 + "rural",
1316 + "ruse",
1317 + "rustre",
1318 + "sable",
1319 + "sabot",
1320 + "sabre",
1321 + "sacre",
1322 + "sage",
1323 + "saint",
1324 + "saisir",
1325 + "salade",
1326 + "salive",
1327 + "salle",
1328 + "salon",
1329 + "salto",
1330 + "salut",
1331 + "salve",
1332 + "samba",
1333 + "sandale",
1334 + "sanguin",
1335 + "sapin",
1336 + "sarcasme",
1337 + "satisfaire",
1338 + "sauce",
1339 + "sauf",
1340 + "sauge",
1341 + "saule",
1342 + "sauna",
1343 + "sauter",
1344 + "sauver",
1345 + "savoir",
1346 + "science",
1347 + "scoop",
1348 + "score",
1349 + "second",
1350 + "secret",
1351 + "secte",
1352 + "seigneur",
1353 + "sein",
1354 + "seize",
1355 + "selle",
1356 + "selon",
1357 + "semaine",
1358 + "sembler",
1359 + "semer",
1360 + "semis",
1361 + "sensuel",
1362 + "sentir",
1363 + "sept",
1364 + "serpe",
1365 + "serrer",
1366 + "sertir",
1367 + "service",
1368 + "seuil",
1369 + "seulement",
1370 + "short",
1371 + "sien",
1372 + "sigle",
1373 + "signal",
1374 + "silence",
1375 + "silo",
1376 + "simple",
1377 + "singe",
1378 + "sinon",
1379 + "sinus",
1380 + "sioux",
1381 + "sirop",
1382 + "site",
1383 + "situation",
1384 + "skier",
1385 + "snob",
1386 + "sobre",
1387 + "social",
1388 + "socle",
1389 + "sodium",
1390 + "soigner",
1391 + "soir",
1392 + "soixante",
1393 + "soja",
1394 + "solaire",
1395 + "soldat",
1396 + "soleil",
1397 + "solide",
1398 + "solo",
1399 + "solvant",
1400 + "sombre",
1401 + "somme",
1402 + "somnoler",
1403 + "sondage",
1404 + "songeur",
1405 + "sonner",
1406 + "sorte",
1407 + "sosie",
1408 + "sottise",
1409 + "souci",
1410 + "soudain",
1411 + "souffrir",
1412 + "souhaiter",
1413 + "soulever",
1414 + "soumettre",
1415 + "soupe",
1416 + "sourd",
1417 + "soustraire",
1418 + "soutenir",
1419 + "souvent",
1420 + "soyeux",
1421 + "spectacle",
1422 + "sport",
1423 + "stade",
1424 + "stagiaire",
1425 + "stand",
1426 + "star",
1427 + "statue",
1428 + "stock",
1429 + "stop",
1430 + "store",
1431 + "style",
1432 + "suave",
1433 + "subir",
1434 + "sucre",
1435 + "suer",
1436 + "suffire",
1437 + "suie",
1438 + "suite",
1439 + "suivre",
1440 + "sujet",
1441 + "sulfite",
1442 + "supposer",
1443 + "surf",
1444 + "surprendre",
1445 + "surtout",
1446 + "surveiller",
1447 + "tabac",
1448 + "table",
1449 + "tabou",
1450 + "tache",
1451 + "tacler",
1452 + "tacot",
1453 + "tact",
1454 + "taie",
1455 + "taille",
1456 + "taire",
1457 + "talon",
1458 + "talus",
1459 + "tandis",
1460 + "tango",
1461 + "tanin",
1462 + "tant",
1463 + "taper",
1464 + "tapis",
1465 + "tard",
1466 + "tarif",
1467 + "tarot",
1468 + "tarte",
1469 + "tasse",
1470 + "taureau",
1471 + "taux",
1472 + "taverne",
1473 + "taxer",
1474 + "taxi",
1475 + "tellement",
1476 + "temple",
1477 + "tendre",
1478 + "tenir",
1479 + "tenter",
1480 + "tenu",
1481 + "terme",
1482 + "ternir",
1483 + "terre",
1484 + "test",
1485 + "texte",
1486 + "thym",
1487 + "tibia",
1488 + "tiers",
1489 + "tige",
1490 + "tipi",
1491 + "tique",
1492 + "tirer",
1493 + "tissu",
1494 + "titre",
1495 + "toast",
1496 + "toge",
1497 + "toile",
1498 + "toiser",
1499 + "toiture",
1500 + "tomber",
1501 + "tome",
1502 + "tonne",
1503 + "tonte",
1504 + "toque",
1505 + "torse",
1506 + "tortue",
1507 + "totem",
1508 + "toucher",
1509 + "toujours",
1510 + "tour",
1511 + "tousser",
1512 + "tout",
1513 + "toux",
1514 + "trace",
1515 + "train",
1516 + "trame",
1517 + "tranquille",
1518 + "travail",
1519 + "trembler",
1520 + "trente",
1521 + "tribu",
1522 + "trier",
1523 + "trio",
1524 + "tripe",
1525 + "triste",
1526 + "troc",
1527 + "trois",
1528 + "tromper",
1529 + "tronc",
1530 + "trop",
1531 + "trotter",
1532 + "trouer",
1533 + "truc",
1534 + "truite",
1535 + "tuba",
1536 + "tuer",
1537 + "tuile",
1538 + "turbo",
1539 + "tutu",
1540 + "tuyau",
1541 + "type",
1542 + "union",
1543 + "unique",
1544 + "unir",
1545 + "unisson",
1546 + "untel",
1547 + "urne",
1548 + "usage",
1549 + "user",
1550 + "usiner",
1551 + "usure",
1552 + "utile",
1553 + "vache",
1554 + "vague",
1555 + "vaincre",
1556 + "valeur",
1557 + "valoir",
1558 + "valser",
1559 + "valve",
1560 + "vampire",
1561 + "vaseux",
1562 + "vaste",
1563 + "veau",
1564 + "veille",
1565 + "veine",
1566 + "velours",
1567 + "velu",
1568 + "vendre",
1569 + "venir",
1570 + "vent",
1571 + "venue",
1572 + "verbe",
1573 + "verdict",
1574 + "version",
1575 + "vertige",
1576 + "verve",
1577 + "veste",
1578 + "veto",
1579 + "vexer",
1580 + "vice",
1581 + "victime",
1582 + "vide",
1583 + "vieil",
1584 + "vieux",
1585 + "vigie",
1586 + "vigne",
1587 + "ville",
1588 + "vingt",
1589 + "violent",
1590 + "virer",
1591 + "virus",
1592 + "visage",
1593 + "viser",
1594 + "visite",
1595 + "visuel",
1596 + "vitamine",
1597 + "vitrine",
1598 + "vivant",
1599 + "vivre",
1600 + "vocal",
1601 + "vodka",
1602 + "vogue",
1603 + "voici",
1604 + "voile",
1605 + "voir",
1606 + "voisin",
1607 + "voiture",
1608 + "volaille",
1609 + "volcan",
1610 + "voler",
1611 + "volt",
1612 + "votant",
1613 + "votre",
1614 + "vouer",
1615 + "vouloir",
1616 + "vous",
1617 + "voyage",
1618 + "voyou",
1619 + "vrac",
1620 + "vrai",
1621 + "yacht",
1622 + "yeti",
1623 + "yeux",
1624 + "yoga",
1625 + "zeste",
1626 + "zinc",
1627 + "zone",
1628 + "zoom"
1629 + ];
1630 +}
cw_monero/lib/mnemonics/german.dart
+1 -1
@@ -1627,4 +1627,4 @@ class GermanMnemonics {
1627 "Zweck",
1628 "Zyklop"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_monero/lib/mnemonics/italian.dart
+1629 -1629
@@ -1,1630 +1,1630 @@
1 class ItalianMnemonics {
2 - static const words = [
3 - "abbinare",
4 - "abbonato",
5 - "abisso",
6 - "abitare",
7 - "abominio",
8 - "accadere",
9 - "accesso",
10 - "acciaio",
11 - "accordo",
12 - "accumulo",
13 - "acido",
14 - "acqua",
15 - "acrobata",
16 - "acustico",
17 - "adattare",
18 - "addetto",
19 - "addio",
20 - "addome",
21 - "adeguato",
22 - "aderire",
23 - "adorare",
24 - "adottare",
25 - "adozione",
26 - "adulto",
27 - "aereo",
28 - "aerobica",
29 - "affare",
30 - "affetto",
31 - "affidare",
32 - "affogato",
33 - "affronto",
34 - "africano",
35 - "afrodite",
36 - "agenzia",
37 - "aggancio",
38 - "aggeggio",
39 - "aggiunta",
40 - "agio",
41 - "agire",
42 - "agitare",
43 - "aglio",
44 - "agnello",
45 - "agosto",
46 - "aiutare",
47 - "albero",
48 - "albo",
49 - "alce",
50 - "alchimia",
51 - "alcool",
52 - "alfabeto",
53 - "algebra",
54 - "alimento",
55 - "allarme",
56 - "alleanza",
57 - "allievo",
58 - "alloggio",
59 - "alluce",
60 - "alpi",
61 - "alterare",
62 - "altro",
63 - "aluminio",
64 - "amante",
65 - "amarezza",
66 - "ambiente",
67 - "ambrosia",
68 - "america",
69 - "amico",
70 - "ammalare",
71 - "ammirare",
72 - "amnesia",
73 - "amnistia",
74 - "amore",
75 - "ampliare",
76 - "amputare",
77 - "analisi",
78 - "anamnesi",
79 - "ananas",
80 - "anarchia",
81 - "anatra",
82 - "anca",
83 - "ancorato",
84 - "andare",
85 - "androide",
86 - "aneddoto",
87 - "anello",
88 - "angelo",
89 - "angolino",
90 - "anguilla",
91 - "anidride",
92 - "anima",
93 - "annegare",
94 - "anno",
95 - "annuncio",
96 - "anomalia",
97 - "antenna",
98 - "anticipo",
99 - "aperto",
100 - "apostolo",
101 - "appalto",
102 - "appello",
103 - "appiglio",
104 - "applauso",
105 - "appoggio",
106 - "appurare",
107 - "aprile",
108 - "aquila",
109 - "arabo",
110 - "arachidi",
111 - "aragosta",
112 - "arancia",
113 - "arbitrio",
114 - "archivio",
115 - "arco",
116 - "argento",
117 - "argilla",
118 - "aria",
119 - "ariete",
120 - "arma",
121 - "armonia",
122 - "aroma",
123 - "arrivare",
124 - "arrosto",
125 - "arsenale",
126 - "arte",
127 - "artiglio",
128 - "asfalto",
129 - "asfissia",
130 - "asino",
131 - "asparagi",
132 - "aspirina",
133 - "assalire",
134 - "assegno",
135 - "assolto",
136 - "assurdo",
137 - "asta",
138 - "astratto",
139 - "atlante",
140 - "atletica",
141 - "atomo",
142 - "atropina",
143 - "attacco",
144 - "attesa",
145 - "attico",
146 - "atto",
147 - "attrarre",
148 - "auguri",
149 - "aula",
150 - "aumento",
151 - "aurora",
152 - "auspicio",
153 - "autista",
154 - "auto",
155 - "autunno",
156 - "avanzare",
157 - "avarizia",
158 - "avere",
159 - "aviatore",
160 - "avido",
161 - "avorio",
162 - "avvenire",
163 - "avviso",
164 - "avvocato",
165 - "azienda",
166 - "azione",
167 - "azzardo",
168 - "azzurro",
169 - "babbuino",
170 - "bacio",
171 - "badante",
172 - "baffi",
173 - "bagaglio",
174 - "bagliore",
175 - "bagno",
176 - "balcone",
177 - "balena",
178 - "ballare",
179 - "balordo",
180 - "balsamo",
181 - "bambola",
182 - "bancomat",
183 - "banda",
184 - "barato",
185 - "barba",
186 - "barista",
187 - "barriera",
188 - "basette",
189 - "basilico",
190 - "bassista",
191 - "bastare",
192 - "battello",
193 - "bavaglio",
194 - "beccare",
195 - "beduino",
196 - "bellezza",
197 - "bene",
198 - "benzina",
199 - "berretto",
200 - "bestia",
201 - "bevitore",
202 - "bianco",
203 - "bibbia",
204 - "biberon",
205 - "bibita",
206 - "bici",
207 - "bidone",
208 - "bilancia",
209 - "biliardo",
210 - "binario",
211 - "binocolo",
212 - "biologia",
213 - "biondina",
214 - "biopsia",
215 - "biossido",
216 - "birbante",
217 - "birra",
218 - "biscotto",
219 - "bisogno",
220 - "bistecca",
221 - "bivio",
222 - "blindare",
223 - "bloccare",
224 - "bocca",
225 - "bollire",
226 - "bombola",
227 - "bonifico",
228 - "borghese",
229 - "borsa",
230 - "bottino",
231 - "botulino",
232 - "braccio",
233 - "bradipo",
234 - "branco",
235 - "bravo",
236 - "bresaola",
237 - "bretelle",
238 - "brevetto",
239 - "briciola",
240 - "brigante",
241 - "brillare",
242 - "brindare",
243 - "brivido",
244 - "broccoli",
245 - "brontolo",
246 - "bruciare",
247 - "brufolo",
248 - "bucare",
249 - "buddista",
250 - "budino",
251 - "bufera",
252 - "buffo",
253 - "bugiardo",
254 - "buio",
255 - "buono",
256 - "burrone",
257 - "bussola",
258 - "bustina",
259 - "buttare",
260 - "cabernet",
261 - "cabina",
262 - "cacao",
263 - "cacciare",
264 - "cactus",
265 - "cadavere",
266 - "caffe",
267 - "calamari",
268 - "calcio",
269 - "caldaia",
270 - "calmare",
271 - "calunnia",
272 - "calvario",
273 - "calzone",
274 - "cambiare",
275 - "camera",
276 - "camion",
277 - "cammello",
278 - "campana",
279 - "canarino",
280 - "cancello",
281 - "candore",
282 - "cane",
283 - "canguro",
284 - "cannone",
285 - "canoa",
286 - "cantare",
287 - "canzone",
288 - "caos",
289 - "capanna",
290 - "capello",
291 - "capire",
292 - "capo",
293 - "capperi",
294 - "capra",
295 - "capsula",
296 - "caraffa",
297 - "carbone",
298 - "carciofo",
299 - "cardigan",
300 - "carenza",
301 - "caricare",
302 - "carota",
303 - "carrello",
304 - "carta",
305 - "casa",
306 - "cascare",
307 - "caserma",
308 - "cashmere",
309 - "casino",
310 - "cassetta",
311 - "castello",
312 - "catalogo",
313 - "catena",
314 - "catorcio",
315 - "cattivo",
316 - "causa",
317 - "cauzione",
318 - "cavallo",
319 - "caverna",
320 - "caviglia",
321 - "cavo",
322 - "cazzotto",
323 - "celibato",
324 - "cemento",
325 - "cenare",
326 - "centrale",
327 - "ceramica",
328 - "cercare",
329 - "ceretta",
330 - "cerniera",
331 - "certezza",
332 - "cervello",
333 - "cessione",
334 - "cestino",
335 - "cetriolo",
336 - "chiave",
337 - "chiedere",
338 - "chilo",
339 - "chimera",
340 - "chiodo",
341 - "chirurgo",
342 - "chitarra",
343 - "chiudere",
344 - "ciabatta",
345 - "ciao",
346 - "cibo",
347 - "ciccia",
348 - "cicerone",
349 - "ciclone",
350 - "cicogna",
351 - "cielo",
352 - "cifra",
353 - "cigno",
354 - "ciliegia",
355 - "cimitero",
356 - "cinema",
357 - "cinque",
358 - "cintura",
359 - "ciondolo",
360 - "ciotola",
361 - "cipolla",
362 - "cippato",
363 - "circuito",
364 - "cisterna",
365 - "citofono",
366 - "ciuccio",
367 - "civetta",
368 - "civico",
369 - "clausola",
370 - "cliente",
371 - "clima",
372 - "clinica",
373 - "cobra",
374 - "coccole",
375 - "cocktail",
376 - "cocomero",
377 - "codice",
378 - "coesione",
379 - "cogliere",
380 - "cognome",
381 - "colla",
382 - "colomba",
383 - "colpire",
384 - "coltello",
385 - "comando",
386 - "comitato",
387 - "commedia",
388 - "comodino",
389 - "compagna",
390 - "comune",
391 - "concerto",
392 - "condotto",
393 - "conforto",
394 - "congiura",
395 - "coniglio",
396 - "consegna",
397 - "conto",
398 - "convegno",
399 - "coperta",
400 - "copia",
401 - "coprire",
402 - "corazza",
403 - "corda",
404 - "corleone",
405 - "cornice",
406 - "corona",
407 - "corpo",
408 - "corrente",
409 - "corsa",
410 - "cortesia",
411 - "corvo",
412 - "coso",
413 - "costume",
414 - "cotone",
415 - "cottura",
416 - "cozza",
417 - "crampo",
418 - "cratere",
419 - "cravatta",
420 - "creare",
421 - "credere",
422 - "crema",
423 - "crescere",
424 - "crimine",
425 - "criterio",
426 - "croce",
427 - "crollare",
428 - "cronaca",
429 - "crostata",
430 - "croupier",
431 - "cubetto",
432 - "cucciolo",
433 - "cucina",
434 - "cultura",
435 - "cuoco",
436 - "cuore",
437 - "cupido",
438 - "cupola",
439 - "cura",
440 - "curva",
441 - "cuscino",
442 - "custode",
443 - "danzare",
444 - "data",
445 - "decennio",
446 - "decidere",
447 - "decollo",
448 - "dedicare",
449 - "dedurre",
450 - "definire",
451 - "delegare",
452 - "delfino",
453 - "delitto",
454 - "demone",
455 - "dentista",
456 - "denuncia",
457 - "deposito",
458 - "derivare",
459 - "deserto",
460 - "designer",
461 - "destino",
462 - "detonare",
463 - "dettagli",
464 - "diagnosi",
465 - "dialogo",
466 - "diamante",
467 - "diario",
468 - "diavolo",
469 - "dicembre",
470 - "difesa",
471 - "digerire",
472 - "digitare",
473 - "diluvio",
474 - "dinamica",
475 - "dipinto",
476 - "diploma",
477 - "diramare",
478 - "dire",
479 - "dirigere",
480 - "dirupo",
481 - "discesa",
482 - "disdetta",
483 - "disegno",
484 - "disporre",
485 - "dissenso",
486 - "distacco",
487 - "dito",
488 - "ditta",
489 - "diva",
490 - "divenire",
491 - "dividere",
492 - "divorare",
493 - "docente",
494 - "dolcetto",
495 - "dolore",
496 - "domatore",
497 - "domenica",
498 - "dominare",
499 - "donatore",
500 - "donna",
501 - "dorato",
502 - "dormire",
503 - "dorso",
504 - "dosaggio",
505 - "dottore",
506 - "dovere",
507 - "download",
508 - "dragone",
509 - "dramma",
510 - "dubbio",
511 - "dubitare",
512 - "duetto",
513 - "durata",
514 - "ebbrezza",
515 - "eccesso",
516 - "eccitare",
517 - "eclissi",
518 - "economia",
519 - "edera",
520 - "edificio",
521 - "editore",
522 - "edizione",
523 - "educare",
524 - "effetto",
525 - "egitto",
526 - "egiziano",
527 - "elastico",
528 - "elefante",
529 - "eleggere",
530 - "elemento",
531 - "elenco",
532 - "elezione",
533 - "elmetto",
534 - "elogio",
535 - "embrione",
536 - "emergere",
537 - "emettere",
538 - "eminenza",
539 - "emisfero",
540 - "emozione",
541 - "empatia",
542 - "energia",
543 - "enfasi",
544 - "enigma",
545 - "entrare",
546 - "enzima",
547 - "epidemia",
548 - "epilogo",
549 - "episodio",
550 - "epoca",
551 - "equivoco",
552 - "erba",
553 - "erede",
554 - "eroe",
555 - "erotico",
556 - "errore",
557 - "eruzione",
558 - "esaltare",
559 - "esame",
560 - "esaudire",
561 - "eseguire",
562 - "esempio",
563 - "esigere",
564 - "esistere",
565 - "esito",
566 - "esperto",
567 - "espresso",
568 - "essere",
569 - "estasi",
570 - "esterno",
571 - "estrarre",
572 - "eterno",
573 - "etica",
574 - "euforico",
575 - "europa",
576 - "evacuare",
577 - "evasione",
578 - "evento",
579 - "evidenza",
580 - "evitare",
581 - "evolvere",
582 - "fabbrica",
583 - "facciata",
584 - "fagiano",
585 - "fagotto",
586 - "falco",
587 - "fame",
588 - "famiglia",
589 - "fanale",
590 - "fango",
591 - "fantasia",
592 - "farfalla",
593 - "farmacia",
594 - "faro",
595 - "fase",
596 - "fastidio",
597 - "faticare",
598 - "fatto",
599 - "favola",
600 - "febbre",
601 - "femmina",
602 - "femore",
603 - "fenomeno",
604 - "fermata",
605 - "feromoni",
606 - "ferrari",
607 - "fessura",
608 - "festa",
609 - "fiaba",
610 - "fiamma",
611 - "fianco",
612 - "fiat",
613 - "fibbia",
614 - "fidare",
615 - "fieno",
616 - "figa",
617 - "figlio",
618 - "figura",
619 - "filetto",
620 - "filmato",
621 - "filosofo",
622 - "filtrare",
623 - "finanza",
624 - "finestra",
625 - "fingere",
626 - "finire",
627 - "finta",
628 - "finzione",
629 - "fiocco",
630 - "fioraio",
631 - "firewall",
632 - "firmare",
633 - "fisico",
634 - "fissare",
635 - "fittizio",
636 - "fiume",
637 - "flacone",
638 - "flagello",
639 - "flirtare",
640 - "flusso",
641 - "focaccia",
642 - "foglio",
643 - "fognario",
644 - "follia",
645 - "fonderia",
646 - "fontana",
647 - "forbici",
648 - "forcella",
649 - "foresta",
650 - "forgiare",
651 - "formare",
652 - "fornace",
653 - "foro",
654 - "fortuna",
655 - "forzare",
656 - "fosforo",
657 - "fotoni",
658 - "fracasso",
659 - "fragola",
660 - "frantumi",
661 - "fratello",
662 - "frazione",
663 - "freccia",
664 - "freddo",
665 - "frenare",
666 - "fresco",
667 - "friggere",
668 - "frittata",
669 - "frivolo",
670 - "frizione",
671 - "fronte",
672 - "frullato",
673 - "frumento",
674 - "frusta",
675 - "frutto",
676 - "fucile",
677 - "fuggire",
678 - "fulmine",
679 - "fumare",
680 - "funzione",
681 - "fuoco",
682 - "furbizia",
683 - "furgone",
684 - "furia",
685 - "furore",
686 - "fusibile",
687 - "fuso",
688 - "futuro",
689 - "gabbiano",
690 - "galassia",
691 - "gallina",
692 - "gamba",
693 - "gancio",
694 - "garanzia",
695 - "garofano",
696 - "gasolio",
697 - "gatto",
698 - "gazebo",
699 - "gazzetta",
700 - "gelato",
701 - "gemelli",
702 - "generare",
703 - "genitori",
704 - "gennaio",
705 - "geologia",
706 - "germania",
707 - "gestire",
708 - "gettare",
709 - "ghepardo",
710 - "ghiaccio",
711 - "giaccone",
712 - "giaguaro",
713 - "giallo",
714 - "giappone",
715 - "giardino",
716 - "gigante",
717 - "gioco",
718 - "gioiello",
719 - "giorno",
720 - "giovane",
721 - "giraffa",
722 - "giudizio",
723 - "giurare",
724 - "giusto",
725 - "globo",
726 - "gloria",
727 - "glucosio",
728 - "gnocca",
729 - "gocciola",
730 - "godere",
731 - "gomito",
732 - "gomma",
733 - "gonfiare",
734 - "gorilla",
735 - "governo",
736 - "gradire",
737 - "graffiti",
738 - "granchio",
739 - "grappolo",
740 - "grasso",
741 - "grattare",
742 - "gridare",
743 - "grissino",
744 - "grondaia",
745 - "grugnito",
746 - "gruppo",
747 - "guadagno",
748 - "guaio",
749 - "guancia",
750 - "guardare",
751 - "gufo",
752 - "guidare",
753 - "guscio",
754 - "gusto",
755 - "icona",
756 - "idea",
757 - "identico",
758 - "idolo",
759 - "idoneo",
760 - "idrante",
761 - "idrogeno",
762 - "igiene",
763 - "ignoto",
764 - "imbarco",
765 - "immagine",
766 - "immobile",
767 - "imparare",
768 - "impedire",
769 - "impianto",
770 - "importo",
771 - "impresa",
772 - "impulso",
773 - "incanto",
774 - "incendio",
775 - "incidere",
776 - "incontro",
777 - "incrocia",
778 - "incubo",
779 - "indagare",
780 - "indice",
781 - "indotto",
782 - "infanzia",
783 - "inferno",
784 - "infinito",
785 - "infranto",
786 - "ingerire",
787 - "inglese",
788 - "ingoiare",
789 - "ingresso",
790 - "iniziare",
791 - "innesco",
792 - "insalata",
793 - "inserire",
794 - "insicuro",
795 - "insonnia",
796 - "insulto",
797 - "interno",
798 - "introiti",
799 - "invasori",
800 - "inverno",
801 - "invito",
802 - "invocare",
803 - "ipnosi",
804 - "ipocrita",
805 - "ipotesi",
806 - "ironia",
807 - "irrigare",
808 - "iscritto",
809 - "isola",
810 - "ispirare",
811 - "isterico",
812 - "istinto",
813 - "istruire",
814 - "italiano",
815 - "jazz",
816 - "labbra",
817 - "labrador",
818 - "ladro",
819 - "lago",
820 - "lamento",
821 - "lampone",
822 - "lancetta",
823 - "lanterna",
824 - "lapide",
825 - "larva",
826 - "lasagne",
827 - "lasciare",
828 - "lastra",
829 - "latte",
830 - "laurea",
831 - "lavagna",
832 - "lavorare",
833 - "leccare",
834 - "legare",
835 - "leggere",
836 - "lenzuolo",
837 - "leone",
838 - "lepre",
839 - "letargo",
840 - "lettera",
841 - "levare",
842 - "levitare",
843 - "lezione",
844 - "liberare",
845 - "libidine",
846 - "libro",
847 - "licenza",
848 - "lievito",
849 - "limite",
850 - "lince",
851 - "lingua",
852 - "liquore",
853 - "lire",
854 - "listino",
855 - "litigare",
856 - "litro",
857 - "locale",
858 - "lottare",
859 - "lucciola",
860 - "lucidare",
861 - "luglio",
862 - "luna",
863 - "macchina",
864 - "madama",
865 - "madre",
866 - "maestro",
867 - "maggio",
868 - "magico",
869 - "maglione",
870 - "magnolia",
871 - "mago",
872 - "maialino",
873 - "maionese",
874 - "malattia",
875 - "male",
876 - "malloppo",
877 - "mancare",
878 - "mandorla",
879 - "mangiare",
880 - "manico",
881 - "manopola",
882 - "mansarda",
883 - "mantello",
884 - "manubrio",
885 - "manzo",
886 - "mappa",
887 - "mare",
888 - "margine",
889 - "marinaio",
890 - "marmotta",
891 - "marocco",
892 - "martello",
893 - "marzo",
894 - "maschera",
895 - "matrice",
896 - "maturare",
897 - "mazzetta",
898 - "meandri",
899 - "medaglia",
900 - "medico",
901 - "medusa",
902 - "megafono",
903 - "melone",
904 - "membrana",
905 - "menta",
906 - "mercato",
907 - "meritare",
908 - "merluzzo",
909 - "mese",
910 - "mestiere",
911 - "metafora",
912 - "meteo",
913 - "metodo",
914 - "mettere",
915 - "miele",
916 - "miglio",
917 - "miliardo",
918 - "mimetica",
919 - "minatore",
920 - "minuto",
921 - "miracolo",
922 - "mirtillo",
923 - "missile",
924 - "mistero",
925 - "misura",
926 - "mito",
927 - "mobile",
928 - "moda",
929 - "moderare",
930 - "moglie",
931 - "molecola",
932 - "molle",
933 - "momento",
934 - "moneta",
935 - "mongolia",
936 - "monologo",
937 - "montagna",
938 - "morale",
939 - "morbillo",
940 - "mordere",
941 - "mosaico",
942 - "mosca",
943 - "mostro",
944 - "motivare",
945 - "moto",
946 - "mulino",
947 - "mulo",
948 - "muovere",
949 - "muraglia",
950 - "muscolo",
951 - "museo",
952 - "musica",
953 - "mutande",
954 - "nascere",
955 - "nastro",
956 - "natale",
957 - "natura",
958 - "nave",
959 - "navigare",
960 - "negare",
961 - "negozio",
962 - "nemico",
963 - "nero",
964 - "nervo",
965 - "nessuno",
966 - "nettare",
967 - "neutroni",
968 - "neve",
969 - "nevicare",
970 - "nicotina",
971 - "nido",
972 - "nipote",
973 - "nocciola",
974 - "noleggio",
975 - "nome",
976 - "nonno",
977 - "norvegia",
978 - "notare",
979 - "notizia",
980 - "nove",
981 - "nucleo",
982 - "nuda",
983 - "nuotare",
984 - "nutrire",
985 - "obbligo",
986 - "occhio",
987 - "occupare",
988 - "oceano",
989 - "odissea",
990 - "odore",
991 - "offerta",
992 - "officina",
993 - "offrire",
994 - "oggetto",
995 - "oggi",
996 - "olfatto",
997 - "olio",
998 - "oliva",
999 - "ombelico",
1000 - "ombrello",
1001 - "omuncolo",
1002 - "ondata",
1003 - "onore",
1004 - "opera",
1005 - "opinione",
1006 - "opuscolo",
1007 - "opzione",
1008 - "orario",
1009 - "orbita",
1010 - "orchidea",
1011 - "ordine",
1012 - "orecchio",
1013 - "orgasmo",
1014 - "orgoglio",
1015 - "origine",
1016 - "orologio",
1017 - "oroscopo",
1018 - "orso",
1019 - "oscurare",
1020 - "ospedale",
1021 - "ospite",
1022 - "ossigeno",
1023 - "ostacolo",
1024 - "ostriche",
1025 - "ottenere",
1026 - "ottimo",
1027 - "ottobre",
1028 - "ovest",
1029 - "pacco",
1030 - "pace",
1031 - "pacifico",
1032 - "padella",
1033 - "pagare",
1034 - "pagina",
1035 - "pagnotta",
1036 - "palazzo",
1037 - "palestra",
1038 - "palpebre",
1039 - "pancetta",
1040 - "panfilo",
1041 - "panino",
1042 - "pannello",
1043 - "panorama",
1044 - "papa",
1045 - "paperino",
1046 - "paradiso",
1047 - "parcella",
1048 - "parente",
1049 - "parlare",
1050 - "parodia",
1051 - "parrucca",
1052 - "partire",
1053 - "passare",
1054 - "pasta",
1055 - "patata",
1056 - "patente",
1057 - "patogeno",
1058 - "patriota",
1059 - "pausa",
1060 - "pazienza",
1061 - "peccare",
1062 - "pecora",
1063 - "pedalare",
1064 - "pelare",
1065 - "pena",
1066 - "pendenza",
1067 - "penisola",
1068 - "pennello",
1069 - "pensare",
1070 - "pentirsi",
1071 - "percorso",
1072 - "perdono",
1073 - "perfetto",
1074 - "perizoma",
1075 - "perla",
1076 - "permesso",
1077 - "persona",
1078 - "pesare",
1079 - "pesce",
1080 - "peso",
1081 - "petardo",
1082 - "petrolio",
1083 - "pezzo",
1084 - "piacere",
1085 - "pianeta",
1086 - "piastra",
1087 - "piatto",
1088 - "piazza",
1089 - "piccolo",
1090 - "piede",
1091 - "piegare",
1092 - "pietra",
1093 - "pigiama",
1094 - "pigliare",
1095 - "pigrizia",
1096 - "pilastro",
1097 - "pilota",
1098 - "pinguino",
1099 - "pioggia",
1100 - "piombo",
1101 - "pionieri",
1102 - "piovra",
1103 - "pipa",
1104 - "pirata",
1105 - "pirolisi",
1106 - "piscina",
1107 - "pisolino",
1108 - "pista",
1109 - "pitone",
1110 - "piumino",
1111 - "pizza",
1112 - "plastica",
1113 - "platino",
1114 - "poesia",
1115 - "poiana",
1116 - "polaroid",
1117 - "polenta",
1118 - "polimero",
1119 - "pollo",
1120 - "polmone",
1121 - "polpetta",
1122 - "poltrona",
1123 - "pomodoro",
1124 - "pompa",
1125 - "popolo",
1126 - "porco",
1127 - "porta",
1128 - "porzione",
1129 - "possesso",
1130 - "postino",
1131 - "potassio",
1132 - "potere",
1133 - "poverino",
1134 - "pranzo",
1135 - "prato",
1136 - "prefisso",
1137 - "prelievo",
1138 - "premio",
1139 - "prendere",
1140 - "prestare",
1141 - "pretesa",
1142 - "prezzo",
1143 - "primario",
1144 - "privacy",
1145 - "problema",
1146 - "processo",
1147 - "prodotto",
1148 - "profeta",
1149 - "progetto",
1150 - "promessa",
1151 - "pronto",
1152 - "proposta",
1153 - "proroga",
1154 - "prossimo",
1155 - "proteina",
1156 - "prova",
1157 - "prudenza",
1158 - "pubblico",
1159 - "pudore",
1160 - "pugilato",
1161 - "pulire",
1162 - "pulsante",
1163 - "puntare",
1164 - "pupazzo",
1165 - "puzzle",
1166 - "quaderno",
1167 - "qualcuno",
1168 - "quarzo",
1169 - "quercia",
1170 - "quintale",
1171 - "rabbia",
1172 - "racconto",
1173 - "radice",
1174 - "raffica",
1175 - "ragazza",
1176 - "ragione",
1177 - "rammento",
1178 - "ramo",
1179 - "rana",
1180 - "randagio",
1181 - "rapace",
1182 - "rapinare",
1183 - "rapporto",
1184 - "rasatura",
1185 - "ravioli",
1186 - "reagire",
1187 - "realista",
1188 - "reattore",
1189 - "reazione",
1190 - "recitare",
1191 - "recluso",
1192 - "record",
1193 - "recupero",
1194 - "redigere",
1195 - "regalare",
1196 - "regina",
1197 - "regola",
1198 - "relatore",
1199 - "reliquia",
1200 - "remare",
1201 - "rendere",
1202 - "reparto",
1203 - "resina",
1204 - "resto",
1205 - "rete",
1206 - "retorica",
1207 - "rettile",
1208 - "revocare",
1209 - "riaprire",
1210 - "ribadire",
1211 - "ribelle",
1212 - "ricambio",
1213 - "ricetta",
1214 - "richiamo",
1215 - "ricordo",
1216 - "ridurre",
1217 - "riempire",
1218 - "riferire",
1219 - "riflesso",
1220 - "righello",
1221 - "rilancio",
1222 - "rilevare",
1223 - "rilievo",
1224 - "rimanere",
1225 - "rimborso",
1226 - "rinforzo",
1227 - "rinuncia",
1228 - "riparo",
1229 - "ripetere",
1230 - "riposare",
1231 - "ripulire",
1232 - "risalita",
1233 - "riscatto",
1234 - "riserva",
1235 - "riso",
1236 - "rispetto",
1237 - "ritaglio",
1238 - "ritmo",
1239 - "ritorno",
1240 - "ritratto",
1241 - "rituale",
1242 - "riunione",
1243 - "riuscire",
1244 - "riva",
1245 - "robotica",
1246 - "rondine",
1247 - "rosa",
1248 - "rospo",
1249 - "rosso",
1250 - "rotonda",
1251 - "rotta",
1252 - "roulotte",
1253 - "rubare",
1254 - "rubrica",
1255 - "ruffiano",
1256 - "rumore",
1257 - "ruota",
1258 - "ruscello",
1259 - "sabbia",
1260 - "sacco",
1261 - "saggio",
1262 - "sale",
1263 - "salire",
1264 - "salmone",
1265 - "salto",
1266 - "salutare",
1267 - "salvia",
1268 - "sangue",
1269 - "sanzioni",
1270 - "sapere",
1271 - "sapienza",
1272 - "sarcasmo",
1273 - "sardine",
1274 - "sartoria",
1275 - "sbalzo",
1276 - "sbarcare",
1277 - "sberla",
1278 - "sborsare",
1279 - "scadenza",
1280 - "scafo",
1281 - "scala",
1282 - "scambio",
1283 - "scappare",
1284 - "scarpa",
1285 - "scatola",
1286 - "scelta",
1287 - "scena",
1288 - "sceriffo",
1289 - "scheggia",
1290 - "schiuma",
1291 - "sciarpa",
1292 - "scienza",
1293 - "scimmia",
1294 - "sciopero",
1295 - "scivolo",
1296 - "sclerare",
1297 - "scolpire",
1298 - "sconto",
1299 - "scopa",
1300 - "scordare",
1301 - "scossa",
1302 - "scrivere",
1303 - "scrupolo",
1304 - "scuderia",
1305 - "scultore",
1306 - "scuola",
1307 - "scusare",
1308 - "sdraiare",
1309 - "secolo",
1310 - "sedativo",
1311 - "sedere",
1312 - "sedia",
1313 - "segare",
1314 - "segreto",
1315 - "seguire",
1316 - "semaforo",
1317 - "seme",
1318 - "senape",
1319 - "seno",
1320 - "sentiero",
1321 - "separare",
1322 - "sepolcro",
1323 - "sequenza",
1324 - "serata",
1325 - "serpente",
1326 - "servizio",
1327 - "sesso",
1328 - "seta",
1329 - "settore",
1330 - "sfamare",
1331 - "sfera",
1332 - "sfidare",
1333 - "sfiorare",
1334 - "sfogare",
1335 - "sgabello",
1336 - "sicuro",
1337 - "siepe",
1338 - "sigaro",
1339 - "silenzio",
1340 - "silicone",
1341 - "simbiosi",
1342 - "simpatia",
1343 - "simulare",
1344 - "sinapsi",
1345 - "sindrome",
1346 - "sinergia",
1347 - "sinonimo",
1348 - "sintonia",
1349 - "sirena",
1350 - "siringa",
1351 - "sistema",
1352 - "sito",
1353 - "smalto",
1354 - "smentire",
1355 - "smontare",
1356 - "soccorso",
1357 - "socio",
1358 - "soffitto",
1359 - "software",
1360 - "soggetto",
1361 - "sogliola",
1362 - "sognare",
1363 - "soldi",
1364 - "sole",
1365 - "sollievo",
1366 - "solo",
1367 - "sommario",
1368 - "sondare",
1369 - "sonno",
1370 - "sorpresa",
1371 - "sorriso",
1372 - "sospiro",
1373 - "sostegno",
1374 - "sovrano",
1375 - "spaccare",
1376 - "spada",
1377 - "spagnolo",
1378 - "spalla",
1379 - "sparire",
1380 - "spavento",
1381 - "spazio",
1382 - "specchio",
1383 - "spedire",
1384 - "spegnere",
1385 - "spendere",
1386 - "speranza",
1387 - "spessore",
1388 - "spezzare",
1389 - "spiaggia",
1390 - "spiccare",
1391 - "spiegare",
1392 - "spiffero",
1393 - "spingere",
1394 - "sponda",
1395 - "sporcare",
1396 - "spostare",
1397 - "spremuta",
1398 - "spugna",
1399 - "spumante",
1400 - "spuntare",
1401 - "squadra",
1402 - "squillo",
1403 - "staccare",
1404 - "stadio",
1405 - "stagione",
1406 - "stallone",
1407 - "stampa",
1408 - "stancare",
1409 - "starnuto",
1410 - "statura",
1411 - "stella",
1412 - "stendere",
1413 - "sterzo",
1414 - "stilista",
1415 - "stimolo",
1416 - "stinco",
1417 - "stiva",
1418 - "stoffa",
1419 - "storia",
1420 - "strada",
1421 - "stregone",
1422 - "striscia",
1423 - "studiare",
1424 - "stufa",
1425 - "stupendo",
1426 - "subire",
1427 - "successo",
1428 - "sudare",
1429 - "suono",
1430 - "superare",
1431 - "supporto",
1432 - "surfista",
1433 - "sussurro",
1434 - "svelto",
1435 - "svenire",
1436 - "sviluppo",
1437 - "svolta",
1438 - "svuotare",
1439 - "tabacco",
1440 - "tabella",
1441 - "tabu",
1442 - "tacchino",
1443 - "tacere",
1444 - "taglio",
1445 - "talento",
1446 - "tangente",
1447 - "tappeto",
1448 - "tartufo",
1449 - "tassello",
1450 - "tastiera",
1451 - "tavolo",
1452 - "tazza",
1453 - "teatro",
1454 - "tedesco",
1455 - "telaio",
1456 - "telefono",
1457 - "tema",
1458 - "temere",
1459 - "tempo",
1460 - "tendenza",
1461 - "tenebre",
1462 - "tensione",
1463 - "tentare",
1464 - "teologia",
1465 - "teorema",
1466 - "termica",
1467 - "terrazzo",
1468 - "teschio",
1469 - "tesi",
1470 - "tesoro",
1471 - "tessera",
1472 - "testa",
1473 - "thriller",
1474 - "tifoso",
1475 - "tigre",
1476 - "timbrare",
1477 - "timido",
1478 - "tinta",
1479 - "tirare",
1480 - "tisana",
1481 - "titano",
1482 - "titolo",
1483 - "toccare",
1484 - "togliere",
1485 - "topolino",
1486 - "torcia",
1487 - "torrente",
1488 - "tovaglia",
1489 - "traffico",
1490 - "tragitto",
1491 - "training",
1492 - "tramonto",
1493 - "transito",
1494 - "trapezio",
1495 - "trasloco",
1496 - "trattore",
1497 - "trazione",
1498 - "treccia",
1499 - "tregua",
1500 - "treno",
1501 - "triciclo",
1502 - "tridente",
1503 - "trilogia",
1504 - "tromba",
1505 - "troncare",
1506 - "trota",
1507 - "trovare",
1508 - "trucco",
1509 - "tubo",
1510 - "tulipano",
1511 - "tumulto",
1512 - "tunisia",
1513 - "tuono",
1514 - "turista",
1515 - "tuta",
1516 - "tutelare",
1517 - "tutore",
1518 - "ubriaco",
1519 - "uccello",
1520 - "udienza",
1521 - "udito",
1522 - "uffa",
1523 - "umanoide",
1524 - "umore",
1525 - "unghia",
1526 - "unguento",
1527 - "unicorno",
1528 - "unione",
1529 - "universo",
1530 - "uomo",
1531 - "uragano",
1532 - "uranio",
1533 - "urlare",
1534 - "uscire",
1535 - "utente",
1536 - "utilizzo",
1537 - "vacanza",
1538 - "vacca",
1539 - "vaglio",
1540 - "vagonata",
1541 - "valle",
1542 - "valore",
1543 - "valutare",
1544 - "valvola",
1545 - "vampiro",
1546 - "vaniglia",
1547 - "vanto",
1548 - "vapore",
1549 - "variante",
1550 - "vasca",
1551 - "vaselina",
1552 - "vassoio",
1553 - "vedere",
1554 - "vegetale",
1555 - "veglia",
1556 - "veicolo",
1557 - "vela",
1558 - "veleno",
1559 - "velivolo",
1560 - "velluto",
1561 - "vendere",
1562 - "venerare",
1563 - "venire",
1564 - "vento",
1565 - "veranda",
1566 - "verbo",
1567 - "verdura",
1568 - "vergine",
1569 - "verifica",
1570 - "vernice",
1571 - "vero",
1572 - "verruca",
1573 - "versare",
1574 - "vertebra",
1575 - "vescica",
1576 - "vespaio",
1577 - "vestito",
1578 - "vesuvio",
1579 - "veterano",
1580 - "vetro",
1581 - "vetta",
1582 - "viadotto",
1583 - "viaggio",
1584 - "vibrare",
1585 - "vicenda",
1586 - "vichingo",
1587 - "vietare",
1588 - "vigilare",
1589 - "vigneto",
1590 - "villa",
1591 - "vincere",
1592 - "violino",
1593 - "vipera",
1594 - "virgola",
1595 - "virtuoso",
1596 - "visita",
1597 - "vita",
1598 - "vitello",
1599 - "vittima",
1600 - "vivavoce",
1601 - "vivere",
1602 - "viziato",
1603 - "voglia",
1604 - "volare",
1605 - "volpe",
1606 - "volto",
1607 - "volume",
1608 - "vongole",
1609 - "voragine",
1610 - "vortice",
1611 - "votare",
1612 - "vulcano",
1613 - "vuotare",
1614 - "zabaione",
1615 - "zaffiro",
1616 - "zainetto",
1617 - "zampa",
1618 - "zanzara",
1619 - "zattera",
1620 - "zavorra",
1621 - "zenzero",
1622 - "zero",
1623 - "zingaro",
1624 - "zittire",
1625 - "zoccolo",
1626 - "zolfo",
1627 - "zombie",
1628 - "zucchero"
1629 - ];
1630 -}
\ No newline at end of file
2 + static const words = [
3 + "abbinare",
4 + "abbonato",
5 + "abisso",
6 + "abitare",
7 + "abominio",
8 + "accadere",
9 + "accesso",
10 + "acciaio",
11 + "accordo",
12 + "accumulo",
13 + "acido",
14 + "acqua",
15 + "acrobata",
16 + "acustico",
17 + "adattare",
18 + "addetto",
19 + "addio",
20 + "addome",
21 + "adeguato",
22 + "aderire",
23 + "adorare",
24 + "adottare",
25 + "adozione",
26 + "adulto",
27 + "aereo",
28 + "aerobica",
29 + "affare",
30 + "affetto",
31 + "affidare",
32 + "affogato",
33 + "affronto",
34 + "africano",
35 + "afrodite",
36 + "agenzia",
37 + "aggancio",
38 + "aggeggio",
39 + "aggiunta",
40 + "agio",
41 + "agire",
42 + "agitare",
43 + "aglio",
44 + "agnello",
45 + "agosto",
46 + "aiutare",
47 + "albero",
48 + "albo",
49 + "alce",
50 + "alchimia",
51 + "alcool",
52 + "alfabeto",
53 + "algebra",
54 + "alimento",
55 + "allarme",
56 + "alleanza",
57 + "allievo",
58 + "alloggio",
59 + "alluce",
60 + "alpi",
61 + "alterare",
62 + "altro",
63 + "aluminio",
64 + "amante",
65 + "amarezza",
66 + "ambiente",
67 + "ambrosia",
68 + "america",
69 + "amico",
70 + "ammalare",
71 + "ammirare",
72 + "amnesia",
73 + "amnistia",
74 + "amore",
75 + "ampliare",
76 + "amputare",
77 + "analisi",
78 + "anamnesi",
79 + "ananas",
80 + "anarchia",
81 + "anatra",
82 + "anca",
83 + "ancorato",
84 + "andare",
85 + "androide",
86 + "aneddoto",
87 + "anello",
88 + "angelo",
89 + "angolino",
90 + "anguilla",
91 + "anidride",
92 + "anima",
93 + "annegare",
94 + "anno",
95 + "annuncio",
96 + "anomalia",
97 + "antenna",
98 + "anticipo",
99 + "aperto",
100 + "apostolo",
101 + "appalto",
102 + "appello",
103 + "appiglio",
104 + "applauso",
105 + "appoggio",
106 + "appurare",
107 + "aprile",
108 + "aquila",
109 + "arabo",
110 + "arachidi",
111 + "aragosta",
112 + "arancia",
113 + "arbitrio",
114 + "archivio",
115 + "arco",
116 + "argento",
117 + "argilla",
118 + "aria",
119 + "ariete",
120 + "arma",
121 + "armonia",
122 + "aroma",
123 + "arrivare",
124 + "arrosto",
125 + "arsenale",
126 + "arte",
127 + "artiglio",
128 + "asfalto",
129 + "asfissia",
130 + "asino",
131 + "asparagi",
132 + "aspirina",
133 + "assalire",
134 + "assegno",
135 + "assolto",
136 + "assurdo",
137 + "asta",
138 + "astratto",
139 + "atlante",
140 + "atletica",
141 + "atomo",
142 + "atropina",
143 + "attacco",
144 + "attesa",
145 + "attico",
146 + "atto",
147 + "attrarre",
148 + "auguri",
149 + "aula",
150 + "aumento",
151 + "aurora",
152 + "auspicio",
153 + "autista",
154 + "auto",
155 + "autunno",
156 + "avanzare",
157 + "avarizia",
158 + "avere",
159 + "aviatore",
160 + "avido",
161 + "avorio",
162 + "avvenire",
163 + "avviso",
164 + "avvocato",
165 + "azienda",
166 + "azione",
167 + "azzardo",
168 + "azzurro",
169 + "babbuino",
170 + "bacio",
171 + "badante",
172 + "baffi",
173 + "bagaglio",
174 + "bagliore",
175 + "bagno",
176 + "balcone",
177 + "balena",
178 + "ballare",
179 + "balordo",
180 + "balsamo",
181 + "bambola",
182 + "bancomat",
183 + "banda",
184 + "barato",
185 + "barba",
186 + "barista",
187 + "barriera",
188 + "basette",
189 + "basilico",
190 + "bassista",
191 + "bastare",
192 + "battello",
193 + "bavaglio",
194 + "beccare",
195 + "beduino",
196 + "bellezza",
197 + "bene",
198 + "benzina",
199 + "berretto",
200 + "bestia",
201 + "bevitore",
202 + "bianco",
203 + "bibbia",
204 + "biberon",
205 + "bibita",
206 + "bici",
207 + "bidone",
208 + "bilancia",
209 + "biliardo",
210 + "binario",
211 + "binocolo",
212 + "biologia",
213 + "biondina",
214 + "biopsia",
215 + "biossido",
216 + "birbante",
217 + "birra",
218 + "biscotto",
219 + "bisogno",
220 + "bistecca",
221 + "bivio",
222 + "blindare",
223 + "bloccare",
224 + "bocca",
225 + "bollire",
226 + "bombola",
227 + "bonifico",
228 + "borghese",
229 + "borsa",
230 + "bottino",
231 + "botulino",
232 + "braccio",
233 + "bradipo",
234 + "branco",
235 + "bravo",
236 + "bresaola",
237 + "bretelle",
238 + "brevetto",
239 + "briciola",
240 + "brigante",
241 + "brillare",
242 + "brindare",
243 + "brivido",
244 + "broccoli",
245 + "brontolo",
246 + "bruciare",
247 + "brufolo",
248 + "bucare",
249 + "buddista",
250 + "budino",
251 + "bufera",
252 + "buffo",
253 + "bugiardo",
254 + "buio",
255 + "buono",
256 + "burrone",
257 + "bussola",
258 + "bustina",
259 + "buttare",
260 + "cabernet",
261 + "cabina",
262 + "cacao",
263 + "cacciare",
264 + "cactus",
265 + "cadavere",
266 + "caffe",
267 + "calamari",
268 + "calcio",
269 + "caldaia",
270 + "calmare",
271 + "calunnia",
272 + "calvario",
273 + "calzone",
274 + "cambiare",
275 + "camera",
276 + "camion",
277 + "cammello",
278 + "campana",
279 + "canarino",
280 + "cancello",
281 + "candore",
282 + "cane",
283 + "canguro",
284 + "cannone",
285 + "canoa",
286 + "cantare",
287 + "canzone",
288 + "caos",
289 + "capanna",
290 + "capello",
291 + "capire",
292 + "capo",
293 + "capperi",
294 + "capra",
295 + "capsula",
296 + "caraffa",
297 + "carbone",
298 + "carciofo",
299 + "cardigan",
300 + "carenza",
301 + "caricare",
302 + "carota",
303 + "carrello",
304 + "carta",
305 + "casa",
306 + "cascare",
307 + "caserma",
308 + "cashmere",
309 + "casino",
310 + "cassetta",
311 + "castello",
312 + "catalogo",
313 + "catena",
314 + "catorcio",
315 + "cattivo",
316 + "causa",
317 + "cauzione",
318 + "cavallo",
319 + "caverna",
320 + "caviglia",
321 + "cavo",
322 + "cazzotto",
323 + "celibato",
324 + "cemento",
325 + "cenare",
326 + "centrale",
327 + "ceramica",
328 + "cercare",
329 + "ceretta",
330 + "cerniera",
331 + "certezza",
332 + "cervello",
333 + "cessione",
334 + "cestino",
335 + "cetriolo",
336 + "chiave",
337 + "chiedere",
338 + "chilo",
339 + "chimera",
340 + "chiodo",
341 + "chirurgo",
342 + "chitarra",
343 + "chiudere",
344 + "ciabatta",
345 + "ciao",
346 + "cibo",
347 + "ciccia",
348 + "cicerone",
349 + "ciclone",
350 + "cicogna",
351 + "cielo",
352 + "cifra",
353 + "cigno",
354 + "ciliegia",
355 + "cimitero",
356 + "cinema",
357 + "cinque",
358 + "cintura",
359 + "ciondolo",
360 + "ciotola",
361 + "cipolla",
362 + "cippato",
363 + "circuito",
364 + "cisterna",
365 + "citofono",
366 + "ciuccio",
367 + "civetta",
368 + "civico",
369 + "clausola",
370 + "cliente",
371 + "clima",
372 + "clinica",
373 + "cobra",
374 + "coccole",
375 + "cocktail",
376 + "cocomero",
377 + "codice",
378 + "coesione",
379 + "cogliere",
380 + "cognome",
381 + "colla",
382 + "colomba",
383 + "colpire",
384 + "coltello",
385 + "comando",
386 + "comitato",
387 + "commedia",
388 + "comodino",
389 + "compagna",
390 + "comune",
391 + "concerto",
392 + "condotto",
393 + "conforto",
394 + "congiura",
395 + "coniglio",
396 + "consegna",
397 + "conto",
398 + "convegno",
399 + "coperta",
400 + "copia",
401 + "coprire",
402 + "corazza",
403 + "corda",
404 + "corleone",
405 + "cornice",
406 + "corona",
407 + "corpo",
408 + "corrente",
409 + "corsa",
410 + "cortesia",
411 + "corvo",
412 + "coso",
413 + "costume",
414 + "cotone",
415 + "cottura",
416 + "cozza",
417 + "crampo",
418 + "cratere",
419 + "cravatta",
420 + "creare",
421 + "credere",
422 + "crema",
423 + "crescere",
424 + "crimine",
425 + "criterio",
426 + "croce",
427 + "crollare",
428 + "cronaca",
429 + "crostata",
430 + "croupier",
431 + "cubetto",
432 + "cucciolo",
433 + "cucina",
434 + "cultura",
435 + "cuoco",
436 + "cuore",
437 + "cupido",
438 + "cupola",
439 + "cura",
440 + "curva",
441 + "cuscino",
442 + "custode",
443 + "danzare",
444 + "data",
445 + "decennio",
446 + "decidere",
447 + "decollo",
448 + "dedicare",
449 + "dedurre",
450 + "definire",
451 + "delegare",
452 + "delfino",
453 + "delitto",
454 + "demone",
455 + "dentista",
456 + "denuncia",
457 + "deposito",
458 + "derivare",
459 + "deserto",
460 + "designer",
461 + "destino",
462 + "detonare",
463 + "dettagli",
464 + "diagnosi",
465 + "dialogo",
466 + "diamante",
467 + "diario",
468 + "diavolo",
469 + "dicembre",
470 + "difesa",
471 + "digerire",
472 + "digitare",
473 + "diluvio",
474 + "dinamica",
475 + "dipinto",
476 + "diploma",
477 + "diramare",
478 + "dire",
479 + "dirigere",
480 + "dirupo",
481 + "discesa",
482 + "disdetta",
483 + "disegno",
484 + "disporre",
485 + "dissenso",
486 + "distacco",
487 + "dito",
488 + "ditta",
489 + "diva",
490 + "divenire",
491 + "dividere",
492 + "divorare",
493 + "docente",
494 + "dolcetto",
495 + "dolore",
496 + "domatore",
497 + "domenica",
498 + "dominare",
499 + "donatore",
500 + "donna",
501 + "dorato",
502 + "dormire",
503 + "dorso",
504 + "dosaggio",
505 + "dottore",
506 + "dovere",
507 + "download",
508 + "dragone",
509 + "dramma",
510 + "dubbio",
511 + "dubitare",
512 + "duetto",
513 + "durata",
514 + "ebbrezza",
515 + "eccesso",
516 + "eccitare",
517 + "eclissi",
518 + "economia",
519 + "edera",
520 + "edificio",
521 + "editore",
522 + "edizione",
523 + "educare",
524 + "effetto",
525 + "egitto",
526 + "egiziano",
527 + "elastico",
528 + "elefante",
529 + "eleggere",
530 + "elemento",
531 + "elenco",
532 + "elezione",
533 + "elmetto",
534 + "elogio",
535 + "embrione",
536 + "emergere",
537 + "emettere",
538 + "eminenza",
539 + "emisfero",
540 + "emozione",
541 + "empatia",
542 + "energia",
543 + "enfasi",
544 + "enigma",
545 + "entrare",
546 + "enzima",
547 + "epidemia",
548 + "epilogo",
549 + "episodio",
550 + "epoca",
551 + "equivoco",
552 + "erba",
553 + "erede",
554 + "eroe",
555 + "erotico",
556 + "errore",
557 + "eruzione",
558 + "esaltare",
559 + "esame",
560 + "esaudire",
561 + "eseguire",
562 + "esempio",
563 + "esigere",
564 + "esistere",
565 + "esito",
566 + "esperto",
567 + "espresso",
568 + "essere",
569 + "estasi",
570 + "esterno",
571 + "estrarre",
572 + "eterno",
573 + "etica",
574 + "euforico",
575 + "europa",
576 + "evacuare",
577 + "evasione",
578 + "evento",
579 + "evidenza",
580 + "evitare",
581 + "evolvere",
582 + "fabbrica",
583 + "facciata",
584 + "fagiano",
585 + "fagotto",
586 + "falco",
587 + "fame",
588 + "famiglia",
589 + "fanale",
590 + "fango",
591 + "fantasia",
592 + "farfalla",
593 + "farmacia",
594 + "faro",
595 + "fase",
596 + "fastidio",
597 + "faticare",
598 + "fatto",
599 + "favola",
600 + "febbre",
601 + "femmina",
602 + "femore",
603 + "fenomeno",
604 + "fermata",
605 + "feromoni",
606 + "ferrari",
607 + "fessura",
608 + "festa",
609 + "fiaba",
610 + "fiamma",
611 + "fianco",
612 + "fiat",
613 + "fibbia",
614 + "fidare",
615 + "fieno",
616 + "figa",
617 + "figlio",
618 + "figura",
619 + "filetto",
620 + "filmato",
621 + "filosofo",
622 + "filtrare",
623 + "finanza",
624 + "finestra",
625 + "fingere",
626 + "finire",
627 + "finta",
628 + "finzione",
629 + "fiocco",
630 + "fioraio",
631 + "firewall",
632 + "firmare",
633 + "fisico",
634 + "fissare",
635 + "fittizio",
636 + "fiume",
637 + "flacone",
638 + "flagello",
639 + "flirtare",
640 + "flusso",
641 + "focaccia",
642 + "foglio",
643 + "fognario",
644 + "follia",
645 + "fonderia",
646 + "fontana",
647 + "forbici",
648 + "forcella",
649 + "foresta",
650 + "forgiare",
651 + "formare",
652 + "fornace",
653 + "foro",
654 + "fortuna",
655 + "forzare",
656 + "fosforo",
657 + "fotoni",
658 + "fracasso",
659 + "fragola",
660 + "frantumi",
661 + "fratello",
662 + "frazione",
663 + "freccia",
664 + "freddo",
665 + "frenare",
666 + "fresco",
667 + "friggere",
668 + "frittata",
669 + "frivolo",
670 + "frizione",
671 + "fronte",
672 + "frullato",
673 + "frumento",
674 + "frusta",
675 + "frutto",
676 + "fucile",
677 + "fuggire",
678 + "fulmine",
679 + "fumare",
680 + "funzione",
681 + "fuoco",
682 + "furbizia",
683 + "furgone",
684 + "furia",
685 + "furore",
686 + "fusibile",
687 + "fuso",
688 + "futuro",
689 + "gabbiano",
690 + "galassia",
691 + "gallina",
692 + "gamba",
693 + "gancio",
694 + "garanzia",
695 + "garofano",
696 + "gasolio",
697 + "gatto",
698 + "gazebo",
699 + "gazzetta",
700 + "gelato",
701 + "gemelli",
702 + "generare",
703 + "genitori",
704 + "gennaio",
705 + "geologia",
706 + "germania",
707 + "gestire",
708 + "gettare",
709 + "ghepardo",
710 + "ghiaccio",
711 + "giaccone",
712 + "giaguaro",
713 + "giallo",
714 + "giappone",
715 + "giardino",
716 + "gigante",
717 + "gioco",
718 + "gioiello",
719 + "giorno",
720 + "giovane",
721 + "giraffa",
722 + "giudizio",
723 + "giurare",
724 + "giusto",
725 + "globo",
726 + "gloria",
727 + "glucosio",
728 + "gnocca",
729 + "gocciola",
730 + "godere",
731 + "gomito",
732 + "gomma",
733 + "gonfiare",
734 + "gorilla",
735 + "governo",
736 + "gradire",
737 + "graffiti",
738 + "granchio",
739 + "grappolo",
740 + "grasso",
741 + "grattare",
742 + "gridare",
743 + "grissino",
744 + "grondaia",
745 + "grugnito",
746 + "gruppo",
747 + "guadagno",
748 + "guaio",
749 + "guancia",
750 + "guardare",
751 + "gufo",
752 + "guidare",
753 + "guscio",
754 + "gusto",
755 + "icona",
756 + "idea",
757 + "identico",
758 + "idolo",
759 + "idoneo",
760 + "idrante",
761 + "idrogeno",
762 + "igiene",
763 + "ignoto",
764 + "imbarco",
765 + "immagine",
766 + "immobile",
767 + "imparare",
768 + "impedire",
769 + "impianto",
770 + "importo",
771 + "impresa",
772 + "impulso",
773 + "incanto",
774 + "incendio",
775 + "incidere",
776 + "incontro",
777 + "incrocia",
778 + "incubo",
779 + "indagare",
780 + "indice",
781 + "indotto",
782 + "infanzia",
783 + "inferno",
784 + "infinito",
785 + "infranto",
786 + "ingerire",
787 + "inglese",
788 + "ingoiare",
789 + "ingresso",
790 + "iniziare",
791 + "innesco",
792 + "insalata",
793 + "inserire",
794 + "insicuro",
795 + "insonnia",
796 + "insulto",
797 + "interno",
798 + "introiti",
799 + "invasori",
800 + "inverno",
801 + "invito",
802 + "invocare",
803 + "ipnosi",
804 + "ipocrita",
805 + "ipotesi",
806 + "ironia",
807 + "irrigare",
808 + "iscritto",
809 + "isola",
810 + "ispirare",
811 + "isterico",
812 + "istinto",
813 + "istruire",
814 + "italiano",
815 + "jazz",
816 + "labbra",
817 + "labrador",
818 + "ladro",
819 + "lago",
820 + "lamento",
821 + "lampone",
822 + "lancetta",
823 + "lanterna",
824 + "lapide",
825 + "larva",
826 + "lasagne",
827 + "lasciare",
828 + "lastra",
829 + "latte",
830 + "laurea",
831 + "lavagna",
832 + "lavorare",
833 + "leccare",
834 + "legare",
835 + "leggere",
836 + "lenzuolo",
837 + "leone",
838 + "lepre",
839 + "letargo",
840 + "lettera",
841 + "levare",
842 + "levitare",
843 + "lezione",
844 + "liberare",
845 + "libidine",
846 + "libro",
847 + "licenza",
848 + "lievito",
849 + "limite",
850 + "lince",
851 + "lingua",
852 + "liquore",
853 + "lire",
854 + "listino",
855 + "litigare",
856 + "litro",
857 + "locale",
858 + "lottare",
859 + "lucciola",
860 + "lucidare",
861 + "luglio",
862 + "luna",
863 + "macchina",
864 + "madama",
865 + "madre",
866 + "maestro",
867 + "maggio",
868 + "magico",
869 + "maglione",
870 + "magnolia",
871 + "mago",
872 + "maialino",
873 + "maionese",
874 + "malattia",
875 + "male",
876 + "malloppo",
877 + "mancare",
878 + "mandorla",
879 + "mangiare",
880 + "manico",
881 + "manopola",
882 + "mansarda",
883 + "mantello",
884 + "manubrio",
885 + "manzo",
886 + "mappa",
887 + "mare",
888 + "margine",
889 + "marinaio",
890 + "marmotta",
891 + "marocco",
892 + "martello",
893 + "marzo",
894 + "maschera",
895 + "matrice",
896 + "maturare",
897 + "mazzetta",
898 + "meandri",
899 + "medaglia",
900 + "medico",
901 + "medusa",
902 + "megafono",
903 + "melone",
904 + "membrana",
905 + "menta",
906 + "mercato",
907 + "meritare",
908 + "merluzzo",
909 + "mese",
910 + "mestiere",
911 + "metafora",
912 + "meteo",
913 + "metodo",
914 + "mettere",
915 + "miele",
916 + "miglio",
917 + "miliardo",
918 + "mimetica",
919 + "minatore",
920 + "minuto",
921 + "miracolo",
922 + "mirtillo",
923 + "missile",
924 + "mistero",
925 + "misura",
926 + "mito",
927 + "mobile",
928 + "moda",
929 + "moderare",
930 + "moglie",
931 + "molecola",
932 + "molle",
933 + "momento",
934 + "moneta",
935 + "mongolia",
936 + "monologo",
937 + "montagna",
938 + "morale",
939 + "morbillo",
940 + "mordere",
941 + "mosaico",
942 + "mosca",
943 + "mostro",
944 + "motivare",
945 + "moto",
946 + "mulino",
947 + "mulo",
948 + "muovere",
949 + "muraglia",
950 + "muscolo",
951 + "museo",
952 + "musica",
953 + "mutande",
954 + "nascere",
955 + "nastro",
956 + "natale",
957 + "natura",
958 + "nave",
959 + "navigare",
960 + "negare",
961 + "negozio",
962 + "nemico",
963 + "nero",
964 + "nervo",
965 + "nessuno",
966 + "nettare",
967 + "neutroni",
968 + "neve",
969 + "nevicare",
970 + "nicotina",
971 + "nido",
972 + "nipote",
973 + "nocciola",
974 + "noleggio",
975 + "nome",
976 + "nonno",
977 + "norvegia",
978 + "notare",
979 + "notizia",
980 + "nove",
981 + "nucleo",
982 + "nuda",
983 + "nuotare",
984 + "nutrire",
985 + "obbligo",
986 + "occhio",
987 + "occupare",
988 + "oceano",
989 + "odissea",
990 + "odore",
991 + "offerta",
992 + "officina",
993 + "offrire",
994 + "oggetto",
995 + "oggi",
996 + "olfatto",
997 + "olio",
998 + "oliva",
999 + "ombelico",
1000 + "ombrello",
1001 + "omuncolo",
1002 + "ondata",
1003 + "onore",
1004 + "opera",
1005 + "opinione",
1006 + "opuscolo",
1007 + "opzione",
1008 + "orario",
1009 + "orbita",
1010 + "orchidea",
1011 + "ordine",
1012 + "orecchio",
1013 + "orgasmo",
1014 + "orgoglio",
1015 + "origine",
1016 + "orologio",
1017 + "oroscopo",
1018 + "orso",
1019 + "oscurare",
1020 + "ospedale",
1021 + "ospite",
1022 + "ossigeno",
1023 + "ostacolo",
1024 + "ostriche",
1025 + "ottenere",
1026 + "ottimo",
1027 + "ottobre",
1028 + "ovest",
1029 + "pacco",
1030 + "pace",
1031 + "pacifico",
1032 + "padella",
1033 + "pagare",
1034 + "pagina",
1035 + "pagnotta",
1036 + "palazzo",
1037 + "palestra",
1038 + "palpebre",
1039 + "pancetta",
1040 + "panfilo",
1041 + "panino",
1042 + "pannello",
1043 + "panorama",
1044 + "papa",
1045 + "paperino",
1046 + "paradiso",
1047 + "parcella",
1048 + "parente",
1049 + "parlare",
1050 + "parodia",
1051 + "parrucca",
1052 + "partire",
1053 + "passare",
1054 + "pasta",
1055 + "patata",
1056 + "patente",
1057 + "patogeno",
1058 + "patriota",
1059 + "pausa",
1060 + "pazienza",
1061 + "peccare",
1062 + "pecora",
1063 + "pedalare",
1064 + "pelare",
1065 + "pena",
1066 + "pendenza",
1067 + "penisola",
1068 + "pennello",
1069 + "pensare",
1070 + "pentirsi",
1071 + "percorso",
1072 + "perdono",
1073 + "perfetto",
1074 + "perizoma",
1075 + "perla",
1076 + "permesso",
1077 + "persona",
1078 + "pesare",
1079 + "pesce",
1080 + "peso",
1081 + "petardo",
1082 + "petrolio",
1083 + "pezzo",
1084 + "piacere",
1085 + "pianeta",
1086 + "piastra",
1087 + "piatto",
1088 + "piazza",
1089 + "piccolo",
1090 + "piede",
1091 + "piegare",
1092 + "pietra",
1093 + "pigiama",
1094 + "pigliare",
1095 + "pigrizia",
1096 + "pilastro",
1097 + "pilota",
1098 + "pinguino",
1099 + "pioggia",
1100 + "piombo",
1101 + "pionieri",
1102 + "piovra",
1103 + "pipa",
1104 + "pirata",
1105 + "pirolisi",
1106 + "piscina",
1107 + "pisolino",
1108 + "pista",
1109 + "pitone",
1110 + "piumino",
1111 + "pizza",
1112 + "plastica",
1113 + "platino",
1114 + "poesia",
1115 + "poiana",
1116 + "polaroid",
1117 + "polenta",
1118 + "polimero",
1119 + "pollo",
1120 + "polmone",
1121 + "polpetta",
1122 + "poltrona",
1123 + "pomodoro",
1124 + "pompa",
1125 + "popolo",
1126 + "porco",
1127 + "porta",
1128 + "porzione",
1129 + "possesso",
1130 + "postino",
1131 + "potassio",
1132 + "potere",
1133 + "poverino",
1134 + "pranzo",
1135 + "prato",
1136 + "prefisso",
1137 + "prelievo",
1138 + "premio",
1139 + "prendere",
1140 + "prestare",
1141 + "pretesa",
1142 + "prezzo",
1143 + "primario",
1144 + "privacy",
1145 + "problema",
1146 + "processo",
1147 + "prodotto",
1148 + "profeta",
1149 + "progetto",
1150 + "promessa",
1151 + "pronto",
1152 + "proposta",
1153 + "proroga",
1154 + "prossimo",
1155 + "proteina",
1156 + "prova",
1157 + "prudenza",
1158 + "pubblico",
1159 + "pudore",
1160 + "pugilato",
1161 + "pulire",
1162 + "pulsante",
1163 + "puntare",
1164 + "pupazzo",
1165 + "puzzle",
1166 + "quaderno",
1167 + "qualcuno",
1168 + "quarzo",
1169 + "quercia",
1170 + "quintale",
1171 + "rabbia",
1172 + "racconto",
1173 + "radice",
1174 + "raffica",
1175 + "ragazza",
1176 + "ragione",
1177 + "rammento",
1178 + "ramo",
1179 + "rana",
1180 + "randagio",
1181 + "rapace",
1182 + "rapinare",
1183 + "rapporto",
1184 + "rasatura",
1185 + "ravioli",
1186 + "reagire",
1187 + "realista",
1188 + "reattore",
1189 + "reazione",
1190 + "recitare",
1191 + "recluso",
1192 + "record",
1193 + "recupero",
1194 + "redigere",
1195 + "regalare",
1196 + "regina",
1197 + "regola",
1198 + "relatore",
1199 + "reliquia",
1200 + "remare",
1201 + "rendere",
1202 + "reparto",
1203 + "resina",
1204 + "resto",
1205 + "rete",
1206 + "retorica",
1207 + "rettile",
1208 + "revocare",
1209 + "riaprire",
1210 + "ribadire",
1211 + "ribelle",
1212 + "ricambio",
1213 + "ricetta",
1214 + "richiamo",
1215 + "ricordo",
1216 + "ridurre",
1217 + "riempire",
1218 + "riferire",
1219 + "riflesso",
1220 + "righello",
1221 + "rilancio",
1222 + "rilevare",
1223 + "rilievo",
1224 + "rimanere",
1225 + "rimborso",
1226 + "rinforzo",
1227 + "rinuncia",
1228 + "riparo",
1229 + "ripetere",
1230 + "riposare",
1231 + "ripulire",
1232 + "risalita",
1233 + "riscatto",
1234 + "riserva",
1235 + "riso",
1236 + "rispetto",
1237 + "ritaglio",
1238 + "ritmo",
1239 + "ritorno",
1240 + "ritratto",
1241 + "rituale",
1242 + "riunione",
1243 + "riuscire",
1244 + "riva",
1245 + "robotica",
1246 + "rondine",
1247 + "rosa",
1248 + "rospo",
1249 + "rosso",
1250 + "rotonda",
1251 + "rotta",
1252 + "roulotte",
1253 + "rubare",
1254 + "rubrica",
1255 + "ruffiano",
1256 + "rumore",
1257 + "ruota",
1258 + "ruscello",
1259 + "sabbia",
1260 + "sacco",
1261 + "saggio",
1262 + "sale",
1263 + "salire",
1264 + "salmone",
1265 + "salto",
1266 + "salutare",
1267 + "salvia",
1268 + "sangue",
1269 + "sanzioni",
1270 + "sapere",
1271 + "sapienza",
1272 + "sarcasmo",
1273 + "sardine",
1274 + "sartoria",
1275 + "sbalzo",
1276 + "sbarcare",
1277 + "sberla",
1278 + "sborsare",
1279 + "scadenza",
1280 + "scafo",
1281 + "scala",
1282 + "scambio",
1283 + "scappare",
1284 + "scarpa",
1285 + "scatola",
1286 + "scelta",
1287 + "scena",
1288 + "sceriffo",
1289 + "scheggia",
1290 + "schiuma",
1291 + "sciarpa",
1292 + "scienza",
1293 + "scimmia",
1294 + "sciopero",
1295 + "scivolo",
1296 + "sclerare",
1297 + "scolpire",
1298 + "sconto",
1299 + "scopa",
1300 + "scordare",
1301 + "scossa",
1302 + "scrivere",
1303 + "scrupolo",
1304 + "scuderia",
1305 + "scultore",
1306 + "scuola",
1307 + "scusare",
1308 + "sdraiare",
1309 + "secolo",
1310 + "sedativo",
1311 + "sedere",
1312 + "sedia",
1313 + "segare",
1314 + "segreto",
1315 + "seguire",
1316 + "semaforo",
1317 + "seme",
1318 + "senape",
1319 + "seno",
1320 + "sentiero",
1321 + "separare",
1322 + "sepolcro",
1323 + "sequenza",
1324 + "serata",
1325 + "serpente",
1326 + "servizio",
1327 + "sesso",
1328 + "seta",
1329 + "settore",
1330 + "sfamare",
1331 + "sfera",
1332 + "sfidare",
1333 + "sfiorare",
1334 + "sfogare",
1335 + "sgabello",
1336 + "sicuro",
1337 + "siepe",
1338 + "sigaro",
1339 + "silenzio",
1340 + "silicone",
1341 + "simbiosi",
1342 + "simpatia",
1343 + "simulare",
1344 + "sinapsi",
1345 + "sindrome",
1346 + "sinergia",
1347 + "sinonimo",
1348 + "sintonia",
1349 + "sirena",
1350 + "siringa",
1351 + "sistema",
1352 + "sito",
1353 + "smalto",
1354 + "smentire",
1355 + "smontare",
1356 + "soccorso",
1357 + "socio",
1358 + "soffitto",
1359 + "software",
1360 + "soggetto",
1361 + "sogliola",
1362 + "sognare",
1363 + "soldi",
1364 + "sole",
1365 + "sollievo",
1366 + "solo",
1367 + "sommario",
1368 + "sondare",
1369 + "sonno",
1370 + "sorpresa",
1371 + "sorriso",
1372 + "sospiro",
1373 + "sostegno",
1374 + "sovrano",
1375 + "spaccare",
1376 + "spada",
1377 + "spagnolo",
1378 + "spalla",
1379 + "sparire",
1380 + "spavento",
1381 + "spazio",
1382 + "specchio",
1383 + "spedire",
1384 + "spegnere",
1385 + "spendere",
1386 + "speranza",
1387 + "spessore",
1388 + "spezzare",
1389 + "spiaggia",
1390 + "spiccare",
1391 + "spiegare",
1392 + "spiffero",
1393 + "spingere",
1394 + "sponda",
1395 + "sporcare",
1396 + "spostare",
1397 + "spremuta",
1398 + "spugna",
1399 + "spumante",
1400 + "spuntare",
1401 + "squadra",
1402 + "squillo",
1403 + "staccare",
1404 + "stadio",
1405 + "stagione",
1406 + "stallone",
1407 + "stampa",
1408 + "stancare",
1409 + "starnuto",
1410 + "statura",
1411 + "stella",
1412 + "stendere",
1413 + "sterzo",
1414 + "stilista",
1415 + "stimolo",
1416 + "stinco",
1417 + "stiva",
1418 + "stoffa",
1419 + "storia",
1420 + "strada",
1421 + "stregone",
1422 + "striscia",
1423 + "studiare",
1424 + "stufa",
1425 + "stupendo",
1426 + "subire",
1427 + "successo",
1428 + "sudare",
1429 + "suono",
1430 + "superare",
1431 + "supporto",
1432 + "surfista",
1433 + "sussurro",
1434 + "svelto",
1435 + "svenire",
1436 + "sviluppo",
1437 + "svolta",
1438 + "svuotare",
1439 + "tabacco",
1440 + "tabella",
1441 + "tabu",
1442 + "tacchino",
1443 + "tacere",
1444 + "taglio",
1445 + "talento",
1446 + "tangente",
1447 + "tappeto",
1448 + "tartufo",
1449 + "tassello",
1450 + "tastiera",
1451 + "tavolo",
1452 + "tazza",
1453 + "teatro",
1454 + "tedesco",
1455 + "telaio",
1456 + "telefono",
1457 + "tema",
1458 + "temere",
1459 + "tempo",
1460 + "tendenza",
1461 + "tenebre",
1462 + "tensione",
1463 + "tentare",
1464 + "teologia",
1465 + "teorema",
1466 + "termica",
1467 + "terrazzo",
1468 + "teschio",
1469 + "tesi",
1470 + "tesoro",
1471 + "tessera",
1472 + "testa",
1473 + "thriller",
1474 + "tifoso",
1475 + "tigre",
1476 + "timbrare",
1477 + "timido",
1478 + "tinta",
1479 + "tirare",
1480 + "tisana",
1481 + "titano",
1482 + "titolo",
1483 + "toccare",
1484 + "togliere",
1485 + "topolino",
1486 + "torcia",
1487 + "torrente",
1488 + "tovaglia",
1489 + "traffico",
1490 + "tragitto",
1491 + "training",
1492 + "tramonto",
1493 + "transito",
1494 + "trapezio",
1495 + "trasloco",
1496 + "trattore",
1497 + "trazione",
1498 + "treccia",
1499 + "tregua",
1500 + "treno",
1501 + "triciclo",
1502 + "tridente",
1503 + "trilogia",
1504 + "tromba",
1505 + "troncare",
1506 + "trota",
1507 + "trovare",
1508 + "trucco",
1509 + "tubo",
1510 + "tulipano",
1511 + "tumulto",
1512 + "tunisia",
1513 + "tuono",
1514 + "turista",
1515 + "tuta",
1516 + "tutelare",
1517 + "tutore",
1518 + "ubriaco",
1519 + "uccello",
1520 + "udienza",
1521 + "udito",
1522 + "uffa",
1523 + "umanoide",
1524 + "umore",
1525 + "unghia",
1526 + "unguento",
1527 + "unicorno",
1528 + "unione",
1529 + "universo",
1530 + "uomo",
1531 + "uragano",
1532 + "uranio",
1533 + "urlare",
1534 + "uscire",
1535 + "utente",
1536 + "utilizzo",
1537 + "vacanza",
1538 + "vacca",
1539 + "vaglio",
1540 + "vagonata",
1541 + "valle",
1542 + "valore",
1543 + "valutare",
1544 + "valvola",
1545 + "vampiro",
1546 + "vaniglia",
1547 + "vanto",
1548 + "vapore",
1549 + "variante",
1550 + "vasca",
1551 + "vaselina",
1552 + "vassoio",
1553 + "vedere",
1554 + "vegetale",
1555 + "veglia",
1556 + "veicolo",
1557 + "vela",
1558 + "veleno",
1559 + "velivolo",
1560 + "velluto",
1561 + "vendere",
1562 + "venerare",
1563 + "venire",
1564 + "vento",
1565 + "veranda",
1566 + "verbo",
1567 + "verdura",
1568 + "vergine",
1569 + "verifica",
1570 + "vernice",
1571 + "vero",
1572 + "verruca",
1573 + "versare",
1574 + "vertebra",
1575 + "vescica",
1576 + "vespaio",
1577 + "vestito",
1578 + "vesuvio",
1579 + "veterano",
1580 + "vetro",
1581 + "vetta",
1582 + "viadotto",
1583 + "viaggio",
1584 + "vibrare",
1585 + "vicenda",
1586 + "vichingo",
1587 + "vietare",
1588 + "vigilare",
1589 + "vigneto",
1590 + "villa",
1591 + "vincere",
1592 + "violino",
1593 + "vipera",
1594 + "virgola",
1595 + "virtuoso",
1596 + "visita",
1597 + "vita",
1598 + "vitello",
1599 + "vittima",
1600 + "vivavoce",
1601 + "vivere",
1602 + "viziato",
1603 + "voglia",
1604 + "volare",
1605 + "volpe",
1606 + "volto",
1607 + "volume",
1608 + "vongole",
1609 + "voragine",
1610 + "vortice",
1611 + "votare",
1612 + "vulcano",
1613 + "vuotare",
1614 + "zabaione",
1615 + "zaffiro",
1616 + "zainetto",
1617 + "zampa",
1618 + "zanzara",
1619 + "zattera",
1620 + "zavorra",
1621 + "zenzero",
1622 + "zero",
1623 + "zingaro",
1624 + "zittire",
1625 + "zoccolo",
1626 + "zolfo",
1627 + "zombie",
1628 + "zucchero"
1629 + ];
1630 +}
cw_monero/lib/mnemonics/japanese.dart
+1 -1
@@ -1627,4 +1627,4 @@ class JapaneseMnemonics {
1627 "びじゅつかん",
1628 "ひしょ"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_monero/lib/mnemonics/portuguese.dart
+1 -1
@@ -1627,4 +1627,4 @@ class PortugueseMnemonics {
1627 "zenite",
1628 "zumbi"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_monero/lib/mnemonics/russian.dart
+1 -1
@@ -1627,4 +1627,4 @@ class RussianMnemonics {
1627 "ячейка",
1628 "ящик"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_monero/lib/mnemonics/spanish.dart
+1 -1
@@ -1627,4 +1627,4 @@ class SpanishMnemonics {
1627 "ritmo",
1628 "rito"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_monero/lib/monero_account_list.dart
+13 -12
@@ -46,26 +46,27 @@ abstract class MoneroAccountListBase with Store {
46 }
47
48 static Map<int, List<Account>> cachedAccounts = {};
49 -
49 +
50 List<Account> getAll() {
51 final allAccounts = account_list.getAllAccount();
52 final currentCount = allAccounts.length;
53 cachedAccounts[account_list.currentWallet!.ffiAddress()] ??= [];
54 -
54 +
55 if (cachedAccounts[account_list.currentWallet!.ffiAddress()]!.length == currentCount) {
56 return cachedAccounts[account_list.currentWallet!.ffiAddress()]!;
57 }
58 -
58 +
59 cachedAccounts[account_list.currentWallet!.ffiAddress()] = allAccounts.map((accountRow) {
60 - final balance = accountRow.getUnlockedBalance();
61 -
62 - return Account(
63 - id: accountRow.getRowId(),
64 - label: accountRow.getLabel(),
65 - balance: moneroAmountToString(amount: account_list.currentWallet!.amountFromString(balance)),
66 - );
67 - }).toList();
68 -
60 + final balance = accountRow.getUnlockedBalance();
61 +
62 + return Account(
63 + id: accountRow.getRowId(),
64 + label: accountRow.getLabel(),
65 + balance:
66 + moneroAmountToString(amount: account_list.currentWallet!.amountFromString(balance)),
67 + );
68 + }).toList();
69 +
70 return cachedAccounts[account_list.currentWallet!.ffiAddress()]!;
71 }
72
cw_monero/lib/monero_subaddress_list.dart
+13 -11
@@ -45,7 +45,7 @@ abstract class MoneroSubaddressListBase with Store {
45 }
46
47 Future<List<Subaddress>> getAll() async {
48 - var subaddresses = await subaddress_list.getAllSubaddresses();
48 + var subaddresses = await subaddress_list.getAllSubaddresses();
49
50 if (subaddresses.length > 2) {
51 final primary = subaddresses.first;
@@ -60,7 +60,7 @@ abstract class MoneroSubaddressListBase with Store {
60 return Subaddress(
61 id: id,
62 address: address,
63 - balance: (s.received/1e12).toStringAsFixed(6),
63 + balance: (s.received / 1e12).toStringAsFixed(6),
64 txCount: s.txCount,
65 label: label);
66 }).toList();
@@ -138,15 +138,17 @@ abstract class MoneroSubaddressListBase with Store {
138 final address = s.address;
139 final label = s.label;
140 return Subaddress(
141 - id: id,
142 - address: address,
143 - balance: (s.received/1e12).toStringAsFixed(6),
144 - txCount: s.txCount,
145 - label: id == 0 &&
146 - label.toLowerCase() == 'Primary account'.toLowerCase()
147 - ? 'Primary address'
148 - : label);
149 - }).toList().reversed.toList();
141 + id: id,
142 + address: address,
143 + balance: (s.received / 1e12).toStringAsFixed(6),
144 + txCount: s.txCount,
145 + label: id == 0 && label.toLowerCase() == 'Primary account'.toLowerCase()
146 + ? 'Primary address'
147 + : label);
148 + })
149 + .toList()
150 + .reversed
151 + .toList();
152 }
153
154 Future<bool> _newSubaddress({required int accountIndex, required String label}) async {
cw_monero/lib/monero_transaction_history.dart
+4 -7
@@ -5,11 +5,10 @@ import 'package:cw_monero/monero_transaction_info.dart';
5
6 part 'monero_transaction_history.g.dart';
7
8 -class MoneroTransactionHistory = MoneroTransactionHistoryBase
9 - with _$MoneroTransactionHistory;
8 +class MoneroTransactionHistory = MoneroTransactionHistoryBase with _$MoneroTransactionHistory;
9
11 -abstract class MoneroTransactionHistoryBase
12 - extends TransactionHistoryBase<MoneroTransactionInfo> with Store {
10 +abstract class MoneroTransactionHistoryBase extends TransactionHistoryBase<MoneroTransactionInfo>
11 + with Store {
12 MoneroTransactionHistoryBase() {
13 transactions = ObservableMap<String, MoneroTransactionInfo>();
14 }
@@ -18,11 +17,9 @@ abstract class MoneroTransactionHistoryBase
17 Future<void> save() async {}
18
19 @override
21 - void addOne(MoneroTransactionInfo transaction) =>
22 - transactions[transaction.id] = transaction;
20 + void addOne(MoneroTransactionInfo transaction) => transactions[transaction.id] = transaction;
21
22 @override
23 void addMany(Map<String, MoneroTransactionInfo> transactions) =>
24 this.transactions.addAll(transactions);
27 -
25 }
cw_monero/lib/monero_wallet.dart
+55 -76
@@ -52,8 +52,8 @@ const MIN_RESTORE_HEIGHT = 1000;
52
53 class MoneroWallet = MoneroWalletBase with _$MoneroWallet;
54
55 -abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
56 - MoneroTransactionHistory, MoneroTransactionInfo> with Store {
55 +abstract class MoneroWalletBase
56 + extends WalletBase<MoneroBalance, MoneroTransactionHistory, MoneroTransactionInfo> with Store {
57 MoneroWalletBase(
58 {required WalletInfo walletInfo,
59 required DerivationInfo derivationInfo,
@@ -76,16 +76,13 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
76 transactionHistory = MoneroTransactionHistory();
77 walletAddresses = MoneroWalletAddresses(walletInfo, transactionHistory);
78
79 - _onAccountChangeReaction =
80 - reaction((_) => walletAddresses.account, (Account? account) {
79 + _onAccountChangeReaction = reaction((_) => walletAddresses.account, (Account? account) {
80 if (account == null) return;
81
83 - balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(<CryptoCurrency,
84 - MoneroBalance>{
82 + balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(<CryptoCurrency, MoneroBalance>{
83 currency: MoneroBalance(
84 fullBalance: monero_wallet.getFullBalance(accountIndex: account.id),
87 - unlockedBalance:
88 - monero_wallet.getUnlockedBalance(accountIndex: account.id))
85 + unlockedBalance: monero_wallet.getUnlockedBalance(accountIndex: account.id))
86 });
87 _updateSubAddress(isEnabledAutoGenerateSubaddress, account: account);
88 unawaited(updateTransactions());
@@ -143,7 +140,8 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
140 passphrase: monero_wallet.getPassphrase());
141
142 int? get restoreHeight =>
146 - transactionHistory.transactions.values.firstOrNull?.height ?? currentWallet?.getRefreshFromBlockHeight();
143 + transactionHistory.transactions.values.firstOrNull?.height ??
144 + currentWallet?.getRefreshFromBlockHeight();
145
146 monero_wallet.SyncListener? _listener;
147 ReactionDisposer? _onAccountChangeReaction;
@@ -156,13 +154,11 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
154
155 Future<void> init() async {
156 await walletAddresses.init();
159 - balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(<CryptoCurrency,
160 - MoneroBalance>{
157 + balance = ObservableMap<CryptoCurrency, MoneroBalance>.of(<CryptoCurrency, MoneroBalance>{
158 currency: MoneroBalance(
162 - fullBalance: monero_wallet.getFullBalance(
163 - accountIndex: walletAddresses.account!.id),
164 - unlockedBalance: monero_wallet.getUnlockedBalance(
165 - accountIndex: walletAddresses.account!.id))
159 + fullBalance: monero_wallet.getFullBalance(accountIndex: walletAddresses.account!.id),
160 + unlockedBalance:
161 + monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id))
162 });
163 _setListeners();
164 await updateTransactions();
@@ -171,16 +167,15 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
167 monero_wallet.setRecoveringFromSeed(isRecovery: walletInfo.isRecovery);
168
169 if (monero_wallet.getCurrentHeight() <= 1) {
174 - monero_wallet.setRefreshFromBlockHeight(
175 - height: walletInfo.restoreHeight);
170 + monero_wallet.setRefreshFromBlockHeight(height: walletInfo.restoreHeight);
171 setupBackgroundSync(password, currentWallet!);
172 }
173 }
174
180 - _autoSaveTimer = Timer.periodic(
181 - Duration(seconds: _autoSaveInterval), (_) async => await save());
175 + _autoSaveTimer =
176 + Timer.periodic(Duration(seconds: _autoSaveInterval), (_) async => await save());
177 // update transaction details after restore
183 - await walletAddresses.subaddressList.update(accountIndex: walletAddresses.account?.id??0);
178 + await walletAddresses.subaddressList.update(accountIndex: walletAddresses.account?.id ?? 0);
179 }
180
181 @override
@@ -191,11 +186,11 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
186 try {
187 // Check if the wallet is currently connected to the daemon
188 final isConnected = await monero_wallet.isConnected();
194 -
189 +
190 if (!isConnected) {
191 return false; // It's not connected to daemon
192 }
198 -
193 +
194 // Check to get current node height to ensure daemon is responsive
195 final nodeHeight = await monero_wallet.getNodeHeight();
196 return nodeHeight > 0;
@@ -420,14 +415,14 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
415 }
416 return await _createTransaction(credentials);
417 }
423 -
418 +
419 Future<PendingTransaction> _createTransaction(Object credentials) async {
420 final _credentials = credentials as MoneroTransactionCreationCredentials;
421 final inputs = <String>[];
422 final outputs = _credentials.outputs;
423 final hasMultiDestination = outputs.length > 1;
429 - final unlockedBalance = monero_wallet.getUnlockedBalance(
430 - accountIndex: walletAddresses.account!.id);
424 + final unlockedBalance =
425 + monero_wallet.getUnlockedBalance(accountIndex: walletAddresses.account!.id);
426
427 PendingTransactionDescription pendingTransactionDescription;
428
@@ -462,17 +457,15 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
457 return MoneroOutput(address: outputAddress!, amount: output.cryptoAmount.toString());
458 }).toList();
459
465 - pendingTransactionDescription =
466 - await transaction_history.createTransactionMultDest(
467 - outputs: moneroOutputs,
468 - priorityRaw: _credentials.priority.serialize(),
469 - accountIndex: walletAddresses.account!.id,
470 - paymentId: "",
471 - preferredInputs: inputs);
460 + pendingTransactionDescription = await transaction_history.createTransactionMultDest(
461 + outputs: moneroOutputs,
462 + priorityRaw: _credentials.priority.serialize(),
463 + accountIndex: walletAddresses.account!.id,
464 + paymentId: "",
465 + preferredInputs: inputs);
466 } else {
467 final output = outputs.first;
474 - final address =
475 - output.isParsedAddress ? output.extractedAddress : output.address;
468 + final address = output.isParsedAddress ? output.extractedAddress : output.address;
469 final amount = output.sendAll ? null : output.cryptoAmount.toString();
470
471 // if ((formattedAmount != null && unlockedBalance < formattedAmount) ||
@@ -484,14 +477,13 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
477 // }
478
479 if (inputs.isEmpty) MoneroTransactionCreationException('No inputs selected');
487 - pendingTransactionDescription =
488 - await transaction_history.createTransactionSync(
489 - address: address!,
490 - amount: amount,
491 - priorityRaw: _credentials.priority.serialize(),
492 - accountIndex: walletAddresses.account!.id,
493 - preferredInputs: inputs,
494 - paymentId: '');
480 + pendingTransactionDescription = await transaction_history.createTransactionSync(
481 + address: address!,
482 + amount: amount,
483 + priorityRaw: _credentials.priority.serialize(),
484 + accountIndex: walletAddresses.account!.id,
485 + preferredInputs: inputs,
486 + paymentId: '');
487 }
488
489 // final status = monero.PendingTransaction_status(pendingTransactionDescription);
@@ -569,17 +561,15 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
561 }
562 try {
563 // -- rename the waller folder --
572 - final currentWalletDir =
573 - Directory(await pathForWalletDir(name: name, type: type));
574 - final newWalletDirPath =
575 - await pathForWalletDir(name: newWalletName, type: type);
576 -
564 + final currentWalletDir = Directory(await pathForWalletDir(name: name, type: type));
565 + final newWalletDirPath = await pathForWalletDir(name: newWalletName, type: type);
566 +
567 // Create new directory if it doesn't exist
568 await Directory(newWalletDirPath).create(recursive: true);
579 -
569 +
570 // -- use new waller folder to copy files with old names still --
571 final currentWalletPath = currentWalletDir.path + '/$name';
582 -
572 +
573 final currentCacheFile = File(currentWalletPath);
574 final currentKeysFile = File('$currentWalletPath.keys');
575 final currentAddressListFile = File('$currentWalletPath.address.txt');
@@ -599,7 +589,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
589 }
590
591 await currentWalletDir.delete(recursive: true);
602 -
592 +
593 await backupWalletFiles(newWalletName);
594 } catch (e) {
595 final currentWalletPath = await pathForWallet(name: name, type: type);
@@ -608,8 +598,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
598 final currentKeysFile = File('$currentWalletPath.keys');
599 final currentAddressListFile = File('$currentWalletPath.address.txt');
600
611 - final newWalletPath =
612 - await pathForWallet(name: newWalletName, type: type);
601 + final newWalletPath = await pathForWallet(name: newWalletName, type: type);
602
603 // Copies current wallet files into new wallet name's dir and files
604 if (currentCacheFile.existsSync()) {
@@ -628,8 +617,7 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
617 }
618
619 @override
631 - Future<void> changePassword(String password) async =>
632 - monero_wallet.setPasswordSync(password);
620 + Future<void> changePassword(String password) async => monero_wallet.setPasswordSync(password);
621
622 Future<int> getNodeHeight() async => monero_wallet.getNodeHeight();
623
@@ -740,15 +728,13 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
728 Future<void> _refreshUnspentCoinsInfo() async {
729 try {
730 final List<dynamic> keys = <dynamic>[];
743 - final currentWalletUnspentCoins = unspentCoinsInfo.values.where(
744 - (element) =>
745 - element.walletId.contains(id) &&
746 - element.accountIndex == walletAddresses.account!.id);
731 + final currentWalletUnspentCoins = unspentCoinsInfo.values.where((element) =>
732 + element.walletId.contains(id) && element.accountIndex == walletAddresses.account!.id);
733
734 if (currentWalletUnspentCoins.isNotEmpty) {
735 currentWalletUnspentCoins.forEach((element) {
750 - final existUnspentCoins = unspentCoins
751 - .where((coin) => element.keyImage!.contains(coin.keyImage!));
736 + final existUnspentCoins =
737 + unspentCoins.where((coin) => element.keyImage!.contains(coin.keyImage!));
738
739 if (existUnspentCoins.isEmpty) {
740 keys.add(element.key);
@@ -765,15 +751,13 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
751 }
752
753 String getTransactionAddress(int accountIndex, int addressIndex) =>
768 - monero_wallet.getAddress(
769 - accountIndex: accountIndex, addressIndex: addressIndex);
754 + monero_wallet.getAddress(accountIndex: accountIndex, addressIndex: addressIndex);
755
756 @override
757 Future<Map<String, MoneroTransactionInfo>> fetchTransactions() async {
758 await transaction_history.refreshTransactions();
759 final resp = (await _getAllTransactionsOfAccount(walletAddresses.account?.id))
775 - .fold<Map<String, MoneroTransactionInfo>>(
776 - <String, MoneroTransactionInfo>{},
760 + .fold<Map<String, MoneroTransactionInfo>>(<String, MoneroTransactionInfo>{},
761 (Map<String, MoneroTransactionInfo> acc, MoneroTransactionInfo tx) {
762 acc[tx.id] = tx;
763 return acc;
@@ -794,14 +778,12 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
778
779 final currentIds = transactionHistory.transactions.keys.toSet();
780 final newIds = transactions.keys.toSet();
797 -
781 +
782 // Remove transactions that no longer exist
799 - currentIds.difference(newIds).forEach((id) =>
800 - transactionHistory.transactions.remove(id));
801 -
783 + currentIds.difference(newIds).forEach((id) => transactionHistory.transactions.remove(id));
784 +
785 // Add or update transactions
803 - transactions.forEach((key, tx) =>
804 - transactionHistory.transactions[key] = tx);
786 + transactions.forEach((key, tx) => transactionHistory.transactions[key] = tx);
787 await transactionHistory.save();
788 _isTransactionUpdating = false;
789 } catch (e) {
@@ -814,21 +796,18 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
796 monero_wallet.getSubaddressLabel(accountIndex, addressIndex);
797
798 Future<List<MoneroTransactionInfo>> _getAllTransactionsOfAccount(int? accountIndex) async =>
817 - (await transaction_history
818 - .getAllTransactions())
799 + (await transaction_history.getAllTransactions())
800 .map(
801 (row) => MoneroTransactionInfo(
802 row.hash,
803 row.blockheight,
823 - row.isSpend
824 - ? TransactionDirection.outgoing
825 - : TransactionDirection.incoming,
804 + row.isSpend ? TransactionDirection.outgoing : TransactionDirection.incoming,
805 row.timeStamp,
806 row.isPending,
807 Money.fromInt(row.amount, currency),
808 row.accountIndex,
809 0,
831 - Money.fromInt(row.fee,currency),
810 + Money.fromInt(row.fee, currency),
811 row.confirmations,
812 )..additionalInfo = <String, dynamic>{
813 'key': row.key,
cw_monero/lib/monero_wallet_addresses.dart
+21 -13
@@ -34,24 +34,28 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store {
34
35 @override
36 String get latestAddress {
37 - var addressIndex = subaddress_list.numSubaddresses(account?.id??0) - 1;
38 - var address = getAddress(accountIndex: account?.id??0, addressIndex: addressIndex);
37 + var addressIndex = subaddress_list.numSubaddresses(account?.id ?? 0) - 1;
38 + var address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
39 while (hiddenAddresses.contains(address)) {
40 addressIndex++;
41 - address = getAddress(accountIndex: account?.id??0, addressIndex: addressIndex);
42 - subaddressList.update(accountIndex: account?.id??0);
41 + address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
42 + subaddressList.update(accountIndex: account?.id ?? 0);
43 }
44 return address;
45 }
46
47 @override
48 String get addressForExchange {
49 - var addressIndex = subaddress_list.numSubaddresses(account?.id??0) - 1;
50 - var address = getAddress(accountIndex: account?.id??0, addressIndex: addressIndex);
51 - while (hiddenAddresses.contains(address) || manualAddresses.contains(address) || subaddress_list.getRawLabel(accountIndex: account?.id??0, addressIndex: addressIndex).isNotEmpty) {
49 + var addressIndex = subaddress_list.numSubaddresses(account?.id ?? 0) - 1;
50 + var address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
51 + while (hiddenAddresses.contains(address) ||
52 + manualAddresses.contains(address) ||
53 + subaddress_list
54 + .getRawLabel(accountIndex: account?.id ?? 0, addressIndex: addressIndex)
55 + .isNotEmpty) {
56 addressIndex++;
53 - address = getAddress(accountIndex: account?.id??0, addressIndex: addressIndex);
54 - subaddressList.update(accountIndex: account?.id??0);
57 + address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
58 + subaddressList.update(accountIndex: account?.id ?? 0);
59 }
60 return address;
61 }
@@ -71,7 +75,9 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store {
75 @override
76 Future<void> init() async {
77 accountList.update();
74 - account = accountList.accounts.isEmpty ? Account(id: 0, label: "Primary address") : accountList.accounts.first;
78 + account = accountList.accounts.isEmpty
79 + ? Account(id: 0, label: "Primary address")
80 + : accountList.accounts.first;
81 await updateSubaddressList(accountIndex: account?.id ?? 0);
82 await updateAddressesInBox();
83 }
@@ -145,9 +151,11 @@ abstract class MoneroWalletAddressesBase extends WalletAddresses with Store {
151 accountIndex: accountIndex,
152 defaultLabel: defaultLabel,
153 usedAddresses: usedAddresses.toList());
148 - subaddress = (subaddressList.subaddresses.isEmpty) ? Subaddress(id: 0, address: address, label: defaultLabel, balance: '0', txCount: 0) : subaddressList.subaddresses.last;
149 - if (num.tryParse(subaddress!.balance??'0') != 0) {
150 - getAddress(accountIndex: accountIndex, addressIndex: (subaddress?.id??0)+1);
154 + subaddress = (subaddressList.subaddresses.isEmpty)
155 + ? Subaddress(id: 0, address: address, label: defaultLabel, balance: '0', txCount: 0)
156 + : subaddressList.subaddresses.last;
157 + if (num.tryParse(subaddress!.balance ?? '0') != 0) {
158 + getAddress(accountIndex: accountIndex, addressIndex: (subaddress?.id ?? 0) + 1);
159 }
160 address = subaddress!.address;
161 }
cw_monero/lib/monero_wallet_service.dart
+26 -41
@@ -45,10 +45,7 @@ class MoneroNewWalletCredentials extends WalletCredentials {
45
46 class MoneroRestoreWalletFromHardwareCredentials extends WalletCredentials {
47 MoneroRestoreWalletFromHardwareCredentials(
48 - {required String name,
49 - required this.hardwareWalletService,
50 - int height = 0,
51 - String? password})
48 + {required String name, required this.hardwareWalletService, int height = 0, String? password})
49 : super(name: name, password: password, height: height);
50 HardwareWalletService hardwareWalletService;
51 }
@@ -111,8 +108,7 @@ class MoneroWalletService extends WalletService<
108 WalletType getType() => WalletType.monero;
109
110 @override
114 - Future<MoneroWallet> create(MoneroNewWalletCredentials credentials,
115 - {bool? isTestnet}) async {
111 + Future<MoneroWallet> create(MoneroNewWalletCredentials credentials, {bool? isTestnet}) async {
112 try {
113 final path = await pathForWallet(name: credentials.name, type: getType());
114
@@ -130,14 +126,13 @@ class MoneroWalletService extends WalletService<
126 final polyseed = Polyseed.create();
127 final lang = PolyseedLang.getByEnglishName(credentials.language);
128
133 - if (credentials.passphrase != null)
134 - polyseed.crypt(credentials.passphrase!);
129 + if (credentials.passphrase != null) polyseed.crypt(credentials.passphrase!);
130
136 - final heightOverride = getMoneroHeigthByDate(
137 - date: DateTime.now().subtract(Duration(days: 2)));
131 + final heightOverride =
132 + getMoneroHeigthByDate(date: DateTime.now().subtract(Duration(days: 2)));
133
139 - return _restoreFromPolyseed(path, credentials.password!, polyseed,
140 - credentials.walletInfo!, lang,
134 + return _restoreFromPolyseed(
135 + path, credentials.password!, polyseed, credentials.walletInfo!, lang,
136 overrideHeight: heightOverride, passphrase: credentials.passphrase);
137 }
138
@@ -181,8 +176,7 @@ class MoneroWalletService extends WalletService<
176
177 if (walletFilesExist(path)) await repairOldAndroidWallet(name);
178
184 - await monero_wallet_manager
185 - .openWallet(path: path, password: password);
179 + await monero_wallet_manager.openWallet(path: path, password: password);
180 final walletInfo = await WalletInfo.get(name, getType());
181 if (walletInfo == null) {
182 throw Exception('Wallet not found');
@@ -315,13 +309,13 @@ class MoneroWalletService extends WalletService<
309 final watchCredentials = await Trezor(service).getWatchCredentials();
310
311 monero_wallet_manager.restoreWalletFromKeys(
318 - path: path,
319 - password: credentials.password!,
320 - language: "English",
321 - restoreHeight: credentials.height!,
322 - address: watchCredentials.address,
323 - viewKey: watchCredentials.watchKey,
324 - spendKey: "",
312 + path: path,
313 + password: credentials.password!,
314 + language: "English",
315 + restoreHeight: credentials.height!,
316 + address: watchCredentials.address,
317 + viewKey: watchCredentials.watchKey,
318 + spendKey: "",
319 );
320 }
321
@@ -341,8 +335,7 @@ class MoneroWalletService extends WalletService<
335 }
336
337 @override
344 - Future<MoneroWallet> restoreFromSeed(
345 - MoneroRestoreWalletFromSeedCredentials credentials,
338 + Future<MoneroWallet> restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials,
339 {bool? isTestnet}) async {
340 // Restore from Polyseed
341 try {
@@ -356,8 +349,7 @@ class MoneroWalletService extends WalletService<
349
350 try {
351 if (isBip39Seed(credentials.mnemonic)) {
359 - final path =
360 - await pathForWallet(name: credentials.name, type: getType());
352 + final path = await pathForWallet(name: credentials.name, type: getType());
353
354 return _restoreFromBip39(
355 path: path,
@@ -410,10 +402,8 @@ class MoneroWalletService extends WalletService<
402 derivationInfo.derivationPath = "m/44'/128'/0'/0/0";
403 await derivationInfo.save();
404
413 - final legacyMnemonic =
414 - getLegacySeedFromBip39(mnemonic, passphrase: passphrase ?? "");
415 - final height =
416 - overrideHeight ?? getMoneroHeigthByDate(date: DateTime.now());
405 + final legacyMnemonic = getLegacySeedFromBip39(mnemonic, passphrase: passphrase ?? "");
406 + final height = overrideHeight ?? getMoneroHeigthByDate(date: DateTime.now());
407
408 walletInfo.isRecovery = true;
409 walletInfo.restoreHeight = height;
@@ -426,10 +416,8 @@ class MoneroWalletService extends WalletService<
416 restoreHeight: height,
417 );
418
429 - currentWallet!.setCacheAttribute(
430 - key: "cakewallet.seed.bip39", value: mnemonic);
431 - currentWallet!.setCacheAttribute(
432 - key: "cakewallet.passphrase", value: passphrase ?? '');
419 + currentWallet!.setCacheAttribute(key: "cakewallet.seed.bip39", value: mnemonic);
420 + currentWallet!.setCacheAttribute(key: "cakewallet.passphrase", value: passphrase ?? '');
421
422 currentWallet!.store();
423
@@ -450,8 +438,7 @@ class MoneroWalletService extends WalletService<
438 final path = await pathForWallet(name: credentials.name, type: getType());
439 final polyseedCoin = PolyseedCoin.POLYSEED_MONERO;
440 final lang = PolyseedLang.getByPhrase(credentials.mnemonic);
453 - final polyseed =
454 - Polyseed.decode(credentials.mnemonic, lang, polyseedCoin);
441 + final polyseed = Polyseed.decode(credentials.mnemonic, lang, polyseedCoin);
442
443 return _restoreFromPolyseed(
444 path, credentials.password!, polyseed, credentials.walletInfo!, lang,
@@ -463,8 +450,8 @@ class MoneroWalletService extends WalletService<
450 }
451 }
452
466 - Future<MoneroWallet> _restoreFromPolyseed(String path, String password,
467 - Polyseed polyseed, WalletInfo walletInfo, PolyseedLang lang,
453 + Future<MoneroWallet> _restoreFromPolyseed(
454 + String path, String password, Polyseed polyseed, WalletInfo walletInfo, PolyseedLang lang,
455 {PolyseedCoin coin = PolyseedCoin.POLYSEED_MONERO,
456 int? overrideHeight,
457 String? passphrase}) async {
@@ -507,9 +494,8 @@ class MoneroWalletService extends WalletService<
494 restoreHeight: height,
495 spendKey: spendKey);
496
510 -
497 currentWallet!.setCacheAttribute(key: "cakewallet.seed", value: seed);
512 - currentWallet!.setCacheAttribute(key: "cakewallet.passphrase", value: passphrase??'');
498 + currentWallet!.setCacheAttribute(key: "cakewallet.passphrase", value: passphrase ?? '');
499
500 final wallet = MoneroWallet(
501 walletInfo: walletInfo,
@@ -556,8 +542,7 @@ class MoneroWalletService extends WalletService<
542
543 if (walletFilesExist(path)) await repairOldAndroidWallet(name);
544
559 - await monero_wallet_manager
560 - .openWallet(path: path, password: password);
545 + await monero_wallet_manager.openWallet(path: path, password: password);
546 final walletInfo = await WalletInfo.get(name, getType());
547 if (walletInfo == null) {
548 throw Exception('Wallet not found');
cw_monero/lib/pending_monero_transaction.dart
+2 -4
@@ -63,8 +63,7 @@ class PendingMoneroTransaction with PendingTransaction {
63 } else {
64 try {
65 await monero_transaction_history.commitTransactionFromPointerAddress(
66 - address: pendingTransactionDescription.pointerAddress,
67 - useUR: false);
66 + address: pendingTransactionDescription.pointerAddress, useUR: false);
67 } catch (e) {
68 final message = e.toString();
69
@@ -86,8 +85,7 @@ class PendingMoneroTransaction with PendingTransaction {
85 Future<Map<String, String>> commitUR() async {
86 try {
87 final ret = await monero_transaction_history.commitTransactionFromPointerAddress(
89 - address: pendingTransactionDescription.pointerAddress,
90 - useUR: true);
88 + address: pendingTransactionDescription.pointerAddress, useUR: true);
89 storeSync(force: true);
90 unawaited(() async {
91 await Future.delayed(const Duration(milliseconds: 250));
cw_monero/lib/trezor.dart
+7 -7
@@ -34,13 +34,13 @@ class Trezor {
34 final txIds = <MoneroKeyImageTxData>[];
35 for (final tdi in tdisList) {
36 txIds.add(MoneroKeyImageTxData(
37 - outKey: tdi["out_key"],
38 - txPubKey: tdi["tx_pub_key"],
39 - internalOutputIndex: tdi["internal_output_index"],
40 - subAddrMajor: tdi["sub_addr_major"],
41 - subAddrMinor: tdi["sub_addr_minor"],
42 - additionalTxPubKeys: (tdi["additional_tx_pub_keys"] as List?)?.map((e) => e as String).toList() ?? []
43 - ));
37 + outKey: tdi["out_key"],
38 + txPubKey: tdi["tx_pub_key"],
39 + internalOutputIndex: tdi["internal_output_index"],
40 + subAddrMajor: tdi["sub_addr_major"],
41 + subAddrMinor: tdi["sub_addr_minor"],
42 + additionalTxPubKeys:
43 + (tdi["additional_tx_pub_keys"] as List?)?.map((e) => e as String).toList() ?? []));
44 }
45 final keyImages = await TrezorMonero(service.client).syncKeyImages(txIds);
46
cw_monero/test/bip39_seed_test.dart
+12 -7
@@ -4,9 +4,12 @@ import 'package:flutter_test/flutter_test.dart';
4 void main() {
5 group("Exodus Style bip39", () {
6 group("Test Wallet 1", () {
7 - final bip39Seed = 'meadow tip best belt boss eyebrow control affair eternal piece very shiver';
8 - final expectedLegacySeed0 = "tasked eight afraid laboratory tail feline rift reinvest vane cafe bailed foggy dormant paper jigsaw king hazard suture king dapper dummy jolted dating dwindling king";
9 - final expectedLegacySeed1 = "palace pairing axes mohawk rekindle excess awful juvenile shipped talent nibs efficient dapper biggest swung fight pact innocent emerge issued titans affair nearby noises emerge";
7 + final bip39Seed =
8 + 'meadow tip best belt boss eyebrow control affair eternal piece very shiver';
9 + final expectedLegacySeed0 =
10 + "tasked eight afraid laboratory tail feline rift reinvest vane cafe bailed foggy dormant paper jigsaw king hazard suture king dapper dummy jolted dating dwindling king";
11 + final expectedLegacySeed1 =
12 + "palace pairing axes mohawk rekindle excess awful juvenile shipped talent nibs efficient dapper biggest swung fight pact innocent emerge issued titans affair nearby noises emerge";
13
14 test("Get legacy Seed from bip39", () {
15 final legacySeed = getLegacySeedFromBip39(bip39Seed);
@@ -20,9 +23,12 @@ void main() {
23 });
24
25 group("Test Wallet 2", () {
23 - final bip39Seed = "color ranch color remove subway public water embrace before begin liberty fault";
24 - final expectedLegacySeed0 = "somewhere problems gauze gigantic intended foxes upcoming saved waffle pipeline lurk bogeys empty wipeout abbey italics novelty tucks rafts elite lunar obnoxious awful bugs elite";
25 - final expectedLegacySeed1 = "playful toxic wildly eluded mesh fainted february mugged maps repent vigilant hitched seventh threaten clue fetches sample diet number alkaline future cottage tuition vegan alkaline";
26 + final bip39Seed =
27 + "color ranch color remove subway public water embrace before begin liberty fault";
28 + final expectedLegacySeed0 =
29 + "somewhere problems gauze gigantic intended foxes upcoming saved waffle pipeline lurk bogeys empty wipeout abbey italics novelty tucks rafts elite lunar obnoxious awful bugs elite";
30 + final expectedLegacySeed1 =
31 + "playful toxic wildly eluded mesh fainted february mugged maps repent vigilant hitched seventh threaten clue fetches sample diet number alkaline future cottage tuition vegan alkaline";
32
33 test("Get legacy Seed from bip39", () {
34 final legacySeed = getLegacySeedFromBip39(bip39Seed);
@@ -34,6 +40,5 @@ void main() {
40 expect(legacySeed, expectedLegacySeed1);
41 });
42 });
37 -
43 });
44 }
cw_monero/test/monero_wallet_service_test.dart
+3 -9
@@ -40,9 +40,7 @@ Future<void> main() async {
40 group("Create wallet", () {
41 test("Create Legacy Wallet", () async {
42 final credentials = _getTestCreateCredentials(
43 - name: 'Create Wallet LS',
44 - language: 'English',
45 - seedType: MoneroSeedType.legacy);
43 + name: 'Create Wallet LS', language: 'English', seedType: MoneroSeedType.legacy);
44 final wallet = await walletService.create(credentials);
45
46 expect(wallet.seed.split(" ").length, 25);
@@ -51,9 +49,7 @@ Future<void> main() async {
49
50 test("Create Polyseed Wallet", () async {
51 final credentials = _getTestCreateCredentials(
54 - name: 'Create Wallet PS',
55 - language: 'English',
56 - seedType: MoneroSeedType.polyseed);
52 + name: 'Create Wallet PS', language: 'English', seedType: MoneroSeedType.polyseed);
53 final wallet = await walletService.create(credentials);
54
55 expect(wallet.seed.split(" ").length, 16);
@@ -62,9 +58,7 @@ Future<void> main() async {
58
59 test("Create Bip39 Wallet", () async {
60 final credentials = _getTestCreateCredentials(
65 - name: 'Create Wallet BS',
66 - language: 'English',
67 - seedType: MoneroSeedType.bip39);
61 + name: 'Create Wallet BS', language: 'English', seedType: MoneroSeedType.bip39);
62 final wallet = await walletService.create(credentials);
63
64 expect(wallet.seed.split(" ").length, 12);
cw_monero/test/utils/setup_monero_c.dart
+5 -8
@@ -4,20 +4,17 @@ import 'package:path/path.dart' as p;
4 File getMoneroCBinary() {
5 final baseDir = Directory('../scripts/monero_c/release');
6
7 - final versionDir =
8 - baseDir.listSync().whereType<Directory>().map((d) => d.path).firstWhere(
9 - (path) => p.basename(path).startsWith('v'),
10 - );
7 + final versionDir = baseDir.listSync().whereType<Directory>().map((d) => d.path).firstWhere(
8 + (path) => p.basename(path).startsWith('v'),
9 + );
10
11 if (Platform.isWindows) {
13 - return File(p.join(
14 - versionDir, 'x86_64-w64-mingw32', 'libmonero_wallet2_api_c.dll'));
12 + return File(p.join(versionDir, 'x86_64-w64-mingw32', 'libmonero_wallet2_api_c.dll'));
13 }
14 if (Platform.isMacOS) {
15 return File(p.join(versionDir, 'macos', 'libmonero_wallet2_api_c.dylib'));
16 }
19 - return File(
20 - p.join(versionDir, 'x86_64-linux-gnu', 'libmonero_wallet2_api_c.so'));
17 + return File(p.join(versionDir, 'x86_64-linux-gnu', 'libmonero_wallet2_api_c.so'));
18 }
19
20 String get moneroCBinaryName {
cw_nano/lib/nano_client.dart
+5 -7
@@ -78,7 +78,7 @@ class NanoClient {
78 },
79 ),
80 );
81 -
81 +
82 final data = jsonDecode(response.body) as Map<String, dynamic>;
83 if (response.statusCode != 200 ||
84 data["error"] != null ||
@@ -107,7 +107,7 @@ class NanoClient {
107 },
108 ),
109 );
110 -
110 +
111 final data = jsonDecode(response.body) as Map<String, dynamic>;
112 return AccountInfoResponse.fromJson(data);
113 } catch (e) {
@@ -132,7 +132,7 @@ class NanoClient {
132 },
133 ),
134 );
135 -
135 +
136 final data = jsonDecode(response.body) as Map<String, dynamic>;
137 return BlockContentsResponse.fromJson(data["contents"] as Map<String, dynamic>);
138 } catch (e) {
@@ -199,7 +199,7 @@ class NanoClient {
199 },
200 ),
201 );
202 -
202 +
203 if (response.statusCode == 200) {
204 final decoded = jsonDecode(response.body) as Map<String, dynamic>;
205 if (decoded.containsKey("error")) {
@@ -510,7 +510,7 @@ class NanoClient {
510 // "raw": true,
511 }),
512 );
513 -
513 +
514 final data = jsonDecode(response.body) as Map<String, dynamic>;
515 final transactions = data["history"] is List ? data["history"] as List<dynamic> : [];
516
@@ -533,7 +533,6 @@ class NanoClient {
533 body: jsonEncode({"action": "reps"}),
534 );
535 try {
536 -
536 final List<N2Node> nodes = (jsonDecode(response.body) as List<dynamic>)
537 .map((dynamic e) => N2Node.fromJson(e as Map<String, dynamic>))
538 .toList();
@@ -554,7 +553,6 @@ class NanoClient {
553 }),
554 );
555 try {
557 -
556 final N2Node node = N2Node.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
557 return node.score ?? 100;
558 } catch (error) {
cw_nano/lib/nano_transaction_model.dart
+2 -2
@@ -20,8 +20,8 @@ class NanoTransactionModel {
20 factory NanoTransactionModel.fromJson(dynamic json) {
21 DateTime? localTimestamp;
22 try {
23 - localTimestamp = DateTime.fromMillisecondsSinceEpoch(
24 - int.parse(json["local_timestamp"] as String) * 1000);
23 + localTimestamp =
24 + DateTime.fromMillisecondsSinceEpoch(int.parse(json["local_timestamp"] as String) * 1000);
25 } catch (e) {
26 localTimestamp = DateTime.now();
27 }
cw_nano/lib/nano_wallet.dart
+4 -2
@@ -208,7 +208,8 @@ abstract class NanoWalletBase
208 amt = txOut.cryptoAmount.amount;
209 }
210
211 - if (balance[currency]?.currentBalance != null && amt > balance[currency]!.currentBalance.amount) {
211 + if (balance[currency]?.currentBalance != null &&
212 + amt > balance[currency]!.currentBalance.amount) {
213 throw Exception("Trying to send more than entire balance!");
214 }
215
@@ -235,7 +236,8 @@ abstract class NanoWalletBase
236 }
237
238 try {
238 - if (runningAmount > balance[currency]!.currentBalance.amount || runningBalance < BigInt.zero) {
239 + if (runningAmount > balance[currency]!.currentBalance.amount ||
240 + runningBalance < BigInt.zero) {
241 throw Exception(("Trying to send more than entire balance!"));
242 }
243 } catch (e) {
cw_nano/lib/nano_wallet_service.dart
+2 -1
@@ -32,7 +32,8 @@ class NanoWalletService extends WalletService<
32 @override
33 Future<WalletBase> create(NanoNewWalletCredentials credentials, {bool? isTestnet}) async {
34 final String mnemonic;
35 - final derivationInfo = credentials.derivationInfo ?? await credentials.walletInfo!.getDerivationInfo();
35 + final derivationInfo =
36 + credentials.derivationInfo ?? await credentials.walletInfo!.getDerivationInfo();
37 switch (derivationInfo.derivationType) {
38 case DerivationType.nano:
39 String seedKey = NanoSeeds.generateSeed();
cw_nano/lib/pending_nano_transaction.dart
+1 -1
@@ -31,7 +31,7 @@ class PendingNanoTransaction with PendingTransaction {
31 await nanoClient.processBlock(block, "send");
32 }
33 }
34 -
34 +
35 @override
36 Future<Map<String, String>> commitUR() => throw UnimplementedError();
37 }
cw_shared_external/lib/cw_shared_external.dart
+1 -3
@@ -1,11 +1,9 @@
1 -
1 import 'dart:async';
2
3 import 'package:flutter/services.dart';
4
5 class CwSharedExternal {
7 - static const MethodChannel _channel =
8 - const MethodChannel('cw_shared_external');
6 + static const MethodChannel _channel = const MethodChannel('cw_shared_external');
7
8 static Future<String> get platformVersion async {
9 final String version = (await _channel.invokeMethod('getPlatformVersion')).toString();
cw_solana/lib/pending_solana_transaction.dart
+1 -1
@@ -42,7 +42,7 @@ class PendingSolanaTransaction with PendingTransaction {
42
43 @override
44 String get id => _sig ?? '';
45 -
45 +
46 @override
47 Future<Map<String, String>> commitUR() {
48 throw UnimplementedError();
cw_solana/lib/solana_client.dart
+6 -6
@@ -493,7 +493,8 @@ class SolanaWalletClient {
493 outgoingAmount = diff.toDouble();
494 outgoingMintAddress = mint;
495 final token = await getTokenInfo(mint);
496 - outgoingToken = token ?? const CryptoCurrency(name: "TOKEN", title: "TOKEN", decimals: 6);
496 + outgoingToken =
497 + token ?? const CryptoCurrency(name: "TOKEN", title: "TOKEN", decimals: 6);
498 outgoingFrom = walletAddress;
499 // We find the intermediate account
500 if (instructions.isNotEmpty && instructions[0].accounts.isNotEmpty) {
@@ -626,7 +627,8 @@ class SolanaWalletClient {
627 final token = await getTokenInfo(mint);
628 printV(token?.symbol);
629 printV(token?.decimals);
629 - incomingToken = token ?? const CryptoCurrency(name: "TOKEN", title: "TOKEN", decimals: 6);
630 + incomingToken =
631 + token ?? const CryptoCurrency(name: "TOKEN", title: "TOKEN", decimals: 6);
632 incomingTo = walletAddress;
633 // We find the intermediate account
634 if (instructions.isNotEmpty && instructions[0].accounts.isNotEmpty) {
@@ -1745,10 +1747,8 @@ class SolanaWalletClient {
1747 return transaction.serializeString();
1748 }
1749
1748 - Future<String> sendTransaction({
1749 - required String serializedTransaction,
1750 - required Commitment commitment
1751 - }) =>
1750 + Future<String> sendTransaction(
1751 + {required String serializedTransaction, required Commitment commitment}) =>
1752 _provider!.request(
1753 SolanaRPCSendTransaction(
1754 encodedTransaction: serializedTransaction,
cw_solana/lib/solana_wallet.dart
+9 -15
@@ -163,12 +163,9 @@ abstract class SolanaWalletBase
163 final prefs = await _sharedPrefs.future;
164 if (prefs.getBool(_scamCheckDoneKey) == true) return;
165
166 - final defaultMints =
167 - DefaultSPLTokens().initialSPLTokens.map((t) => t.mintAddress).toSet();
168 - final defaultSymbolsUpper = DefaultSPLTokens()
169 - .initialSPLTokens
170 - .map((t) => t.symbol.toUpperCase())
171 - .toSet();
166 + final defaultMints = DefaultSPLTokens().initialSPLTokens.map((t) => t.mintAddress).toSet();
167 + final defaultSymbolsUpper =
168 + DefaultSPLTokens().initialSPLTokens.map((t) => t.symbol.toUpperCase()).toSet();
169
170 for (final token in splTokensBox.values) {
171 final suspicious = isTokenPropertiesSuspicious(
@@ -720,8 +717,7 @@ abstract class SolanaWalletBase
717 'distribution',
718 ];
719
723 - static final _suspiciousWordPattern =
724 - RegExp(r'\b(bot|claim|reward)\b', caseSensitive: false);
720 + static final _suspiciousWordPattern = RegExp(r'\b(bot|claim|reward)\b', caseSensitive: false);
721
722 static const _knownNonSolanaNativeSymbols = {
723 'BTC',
@@ -758,13 +754,10 @@ abstract class SolanaWalletBase
754 Set<String>? cachedDefaultMints,
755 Set<String>? cachedDefaultSymbolsUpper,
756 }) {
761 - final defaultMints = cachedDefaultMints ??
762 - DefaultSPLTokens().initialSPLTokens.map((t) => t.mintAddress).toSet();
757 + final defaultMints =
758 + cachedDefaultMints ?? DefaultSPLTokens().initialSPLTokens.map((t) => t.mintAddress).toSet();
759 final defaultSymbolsUpper = cachedDefaultSymbolsUpper ??
764 - DefaultSPLTokens()
765 - .initialSPLTokens
766 - .map((t) => t.symbol.toUpperCase())
767 - .toSet();
760 + DefaultSPLTokens().initialSPLTokens.map((t) => t.symbol.toUpperCase()).toSet();
761
762 final isTokenWhitelisted = defaultMints.contains(token.mintAddress);
763
@@ -799,7 +792,8 @@ abstract class SolanaWalletBase
792
793 if (token.enabled) {
794 final tokenBalance = await _client.getSplTokenBalance(token, solanaAddress) ??
802 - balance[token] ?? SolanaBalance.zero(token);
795 + balance[token] ??
796 + SolanaBalance.zero(token);
797
798 balance[token] = tokenBalance;
799 } else {
cw_solana/lib/solana_wallet_service.dart
+7 -3
@@ -14,8 +14,11 @@ import 'package:cw_solana/solana_mnemonics.dart';
14 import 'package:cw_solana/solana_wallet.dart';
15 import 'package:cw_solana/solana_wallet_creation_credentials.dart';
16
17 -class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
18 - SolanaRestoreWalletFromSeedCredentials, SolanaRestoreWalletFromPrivateKey, SolanaNewWalletCredentials> {
17 +class SolanaWalletService extends WalletService<
18 + SolanaNewWalletCredentials,
19 + SolanaRestoreWalletFromSeedCredentials,
20 + SolanaRestoreWalletFromPrivateKey,
21 + SolanaNewWalletCredentials> {
22 SolanaWalletService(this.isDirect);
23
24 final bool isDirect;
@@ -137,7 +140,8 @@ class SolanaWalletService extends WalletService<SolanaNewWalletCredentials,
140 }
141
142 @override
140 - Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>> restoreFromHardwareWallet(SolanaNewWalletCredentials credentials) {
143 + Future<WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>>
144 + restoreFromHardwareWallet(SolanaNewWalletCredentials credentials) {
145 // TODO: implement restoreFromHardwareWallet
146 throw UnimplementedError();
147 }
cw_tron/lib/pending_tron_transaction.dart
+1 -1
@@ -31,7 +31,7 @@ class PendingTronTransaction with PendingTransaction {
31
32 @override
33 String id;
34 -
34 +
35 @override
36 Future<Map<String, String>> commitUR() {
37 throw UnimplementedError();
cw_tron/lib/tron_balance.dart
+1 -1
@@ -9,7 +9,7 @@ class TronBalance extends Balance {
9
10 final Money balance;
11
12 - String toJSON() => json.encode({ 'balance': balance.amount.toString() });
12 + String toJSON() => json.encode({'balance': balance.amount.toString()});
13
14 static TronBalance? fromJSON(String? jsonSource, Currency currency) {
15 if (jsonSource == null) return null;
cw_tron/lib/tron_client.dart
+5 -6
@@ -328,12 +328,11 @@ class TronClient {
328 );
329
330 return PendingTronTransaction(
331 - signedTransaction: signature,
332 - amount: totalAmount,
333 - fee: Money(rawTransaction.feeLimit ?? BigInt.zero, CryptoCurrency.trx),
334 - sendTransaction: sendTx,
335 - id: rawTransaction.txID
336 - );
331 + signedTransaction: signature,
332 + amount: totalAmount,
333 + fee: Money(rawTransaction.feeLimit ?? BigInt.zero, CryptoCurrency.trx),
334 + sendTransaction: sendTx,
335 + id: rawTransaction.txID);
336 }
337
338 Future<TransactionRaw> _signNativeTransaction(
cw_tron/lib/tron_exception.dart
+2 -1
@@ -5,6 +5,7 @@ class TronMnemonicIsIncorrectException implements Exception {
5 String toString() =>
6 'Tron mnemonic has incorrect format. Mnemonic should contain 12 or 24 words separated by space.';
7 }
8 +
9 class TronTransactionCreationException implements Exception {
10 final String exceptionMessage;
11
@@ -13,4 +14,4 @@ class TronTransactionCreationException implements Exception {
14
15 @override
16 String toString() => exceptionMessage;
16 -}
\ No newline at end of file
17 +}
cw_tron/lib/tron_http_provider.dart
+5 -11
@@ -5,9 +5,7 @@ import 'package:on_chain/tron/tron.dart';
5 import '.secrets.g.dart' as secrets;
6
7 class TronHTTPProvider implements TronServiceProvider {
8 - TronHTTPProvider(
9 - {required this.url,
10 - this.defaultRequestTimeout = const Duration(seconds: 30)});
8 + TronHTTPProvider({required this.url, this.defaultRequestTimeout = const Duration(seconds: 30)});
9
10 @override
11 final String url;
@@ -15,8 +13,7 @@ class TronHTTPProvider implements TronServiceProvider {
13 final Duration defaultRequestTimeout;
14
15 @override
18 - Future<Map<String, dynamic>> get(TronRequestDetails params,
19 - [Duration? timeout]) async {
16 + Future<Map<String, dynamic>> get(TronRequestDetails params, [Duration? timeout]) async {
17 final response = await client.get(Uri.parse(params.url(url)), headers: {
18 'Content-Type': 'application/json',
19 if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
@@ -27,16 +24,13 @@ class TronHTTPProvider implements TronServiceProvider {
24 }
25
26 @override
30 - Future<Map<String, dynamic>> post(TronRequestDetails params,
31 - [Duration? timeout]) async {
27 + Future<Map<String, dynamic>> post(TronRequestDetails params, [Duration? timeout]) async {
28 final response = await client
29 .post(Uri.parse(params.url(url)),
30 headers: {
31 'Content-Type': 'application/json',
36 - if (url.contains("trongrid"))
37 - 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
38 - if (url.contains("nownodes"))
39 - 'api-key': secrets.tronNowNodesApiKey,
32 + if (url.contains("trongrid")) 'TRON-PRO-API-KEY': secrets.tronGridApiKey,
33 + if (url.contains("nownodes")) 'api-key': secrets.tronNowNodesApiKey,
34 },
35 body: params.toRequestBody())
36 .timeout(timeout ?? defaultRequestTimeout);
cw_tron/lib/tron_wallet.dart
+12 -13
@@ -257,7 +257,7 @@ abstract class TronWalletBase
257 nativeTxEstimatedFee = Money.fromInt(nativeFee, currency);
258
259 final trc20Fee = await _getTrc20TxFee();
260 - trc20EstimatedFee = Money.fromInt(trc20Fee, currency);
260 + trc20EstimatedFee = Money.fromInt(trc20Fee, currency);
261
262 log('Native Estimated Fee: $nativeTxEstimatedFee');
263 log('TRC20 Estimated Fee: $trc20EstimatedFee');
@@ -325,8 +325,8 @@ abstract class TronWalletBase
325 var totalAmount = Money.zero(transactionCurrency);
326 var shouldSendAll = false;
327 if (hasMultiDestination) {
328 - // Tron does not have multi Destination right now
329 - throw TronTransactionCreationException(transactionCurrency);
328 + // Tron does not have multi Destination right now
329 + throw TronTransactionCreationException(transactionCurrency);
330 } else {
331 final output = outputs.first;
332
@@ -401,11 +401,13 @@ abstract class TronWalletBase
401 '';
402
403 final decimals = (await _client.getTokenDetail(
404 - contract,
405 - "decimals",
406 - ownerAddress,
407 - tokenAddress,
408 - ) as BigInt?)?.toInt() ?? txCurrency.decimals;
404 + contract,
405 + "decimals",
406 + ownerAddress,
407 + tokenAddress,
408 + ) as BigInt?)
409 + ?.toInt() ??
410 + txCurrency.decimals;
411
412 txCurrency = CryptoCurrency(name: tokenSymbol, title: tokenSymbol, decimals: decimals);
413 }
@@ -577,11 +579,8 @@ abstract class TronWalletBase
579 await tronTokensBox.put(newToken.contractAddress, newToken);
580
581 if (newToken.enabled) {
580 - balance[newToken] = await _client.fetchTronTokenBalances(
581 - _tronAddress,
582 - newToken.contractAddress,
583 - currency: token
584 - );
582 + balance[newToken] = await _client
583 + .fetchTronTokenBalances(_tronAddress, newToken.contractAddress, currency: token);
584 } else {
585 balance.remove(newToken);
586 }
cw_wownero/lib/api/account_list.dart
+3 -4
@@ -13,7 +13,6 @@ wownero.WalletListener getWlptr() {
13 return _wlptr!;
14 }
15
16 -
16 wownero.SubaddressAccount? subaddressAccount;
17
18 bool isUpdating = false;
@@ -69,6 +68,6 @@ Future<void> addAccount({required String label}) async {
68 }
69
70 Future<void> setLabelForAccount({required int accountIndex, required String label}) async {
72 - _setLabelForAccount({'accountIndex': accountIndex, 'label': label});
73 - await store();
74 -}
\ No newline at end of file
71 + _setLabelForAccount({'accountIndex': accountIndex, 'label': label});
72 + await store();
73 +}
cw_wownero/lib/api/exceptions/connection_to_node_exception.dart
+1 -1
@@ -2,4 +2,4 @@ class ConnectionToNodeException implements Exception {
2 ConnectionToNodeException({required this.message});
3
4 final String message;
5 -}
\ No newline at end of file
5 +}
cw_wownero/lib/api/exceptions/creation_transaction_exception.dart
+2 -2
@@ -1,8 +1,8 @@
1 class CreationTransactionException implements Exception {
2 CreationTransactionException({required this.message});
3 -
3 +
4 final String message;
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_wownero/lib/api/exceptions/setup_wallet_exception.dart
+2 -2
@@ -1,8 +1,8 @@
1 class SetupWalletException implements Exception {
2 SetupWalletException({required this.message});
3 -
3 +
4 final String message;
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_wownero/lib/api/exceptions/wallet_creation_exception.dart
+1 -1
@@ -5,4 +5,4 @@ class WalletCreationException implements Exception {
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_wownero/lib/api/exceptions/wallet_opening_exception.dart
+1 -1
@@ -5,4 +5,4 @@ class WalletOpeningException implements Exception {
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart
+2 -2
@@ -1,8 +1,8 @@
1 class WalletRestoreFromKeysException implements Exception {
2 WalletRestoreFromKeysException({required this.message});
3 -
3 +
4 final String message;
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_wownero/lib/api/exceptions/wallet_restore_from_seed_exception.dart
+2 -2
@@ -1,5 +1,5 @@
1 class WalletRestoreFromSeedException implements Exception {
2 WalletRestoreFromSeedException({required this.message});
3 -
3 +
4 final String message;
5 -}
\ No newline at end of file
5 +}
cw_wownero/lib/api/structs/account_row.dart
+1 -1
@@ -4,7 +4,7 @@ import 'package:ffi/ffi.dart';
4 class AccountRow extends Struct {
5 @Int64()
6 external int id;
7 -
7 +
8 external Pointer<Utf8> label;
9
10 String getLabel() => label.toDartString();
cw_wownero/lib/api/structs/pending_transaction.dart
+8 -9
@@ -1,12 +1,11 @@
1 -
1 class PendingTransactionDescription {
3 - PendingTransactionDescription({
4 - required this.amount,
5 - required this.fee,
6 - required this.hash,
7 - required this.hex,
8 - required this.txKey,
9 - required this.pointerAddress});
2 + PendingTransactionDescription(
3 + {required this.amount,
4 + required this.fee,
5 + required this.hash,
6 + required this.hex,
7 + required this.txKey,
8 + required this.pointerAddress});
9
10 final int amount;
11 final int fee;
@@ -14,4 +13,4 @@ class PendingTransactionDescription {
13 final String hex;
14 final String txKey;
15 final int pointerAddress;
17 -}
\ No newline at end of file
16 +}
cw_wownero/lib/api/structs/subaddress_row.dart
+3 -3
@@ -4,12 +4,12 @@ import 'package:ffi/ffi.dart';
4 class SubaddressRow extends Struct {
5 @Int64()
6 external int id;
7 -
7 +
8 external Pointer<Utf8> address;
9 -
9 +
10 external Pointer<Utf8> label;
11
12 String getLabel() => label.toDartString();
13 String getAddress() => address.toDartString();
14 int getId() => id;
15 -}
\ No newline at end of file
15 +}
cw_wownero/lib/api/subaddress_list.dart
+15 -13
@@ -38,7 +38,8 @@ class Subaddress {
38 );
39 final int addressIndex;
40 final int accountIndex;
41 - String get label => wownero.Wallet_getSubaddressLabel(wptr!, accountIndex: accountIndex, addressIndex: addressIndex);
41 + String get label => wownero.Wallet_getSubaddressLabel(wptr!,
42 + accountIndex: accountIndex, addressIndex: addressIndex);
43 final int txCount;
44 final int received;
45 }
@@ -68,7 +69,10 @@ List<Subaddress> getAllSubaddresses() {
69 final subaddrs = wownero.TransactionInfo_subaddrIndex(tx).split(",");
70 final account = wownero.TransactionInfo_subaddrAccount(tx);
71 newttDetails.add(TinyTransactionDetails(
71 - address: List.generate(subaddrs.length, (index) => getAddress(accountIndex: account, addressIndex: int.tryParse(subaddrs[index])??0)),
72 + address: List.generate(
73 + subaddrs.length,
74 + (index) => getAddress(
75 + accountIndex: account, addressIndex: int.tryParse(subaddrs[index]) ?? 0)),
76 amount: wownero.TransactionInfo_amount(tx),
77 ));
78 }
@@ -79,7 +83,7 @@ List<Subaddress> getAllSubaddresses() {
83 final list = List.generate(size, (index) {
84 final ttDetailsLocal = ttDetails.where((element) {
85 final address = getAddress(
82 - accountIndex: subaddress!.accountIndex,
86 + accountIndex: subaddress!.accountIndex,
87 addressIndex: index,
88 );
89 if (address == element.address) return true;
@@ -97,7 +101,8 @@ List<Subaddress> getAllSubaddresses() {
101 );
102 }).reversed.toList();
103 if (list.isEmpty) {
100 - list.add(Subaddress(addressIndex: 0, accountIndex: subaddress!.accountIndex, txCount: 0, received: 0));
104 + list.add(Subaddress(
105 + addressIndex: 0, accountIndex: subaddress!.accountIndex, txCount: 0, received: 0));
106 }
107 return list;
108 }
@@ -113,7 +118,8 @@ int numSubaddresses(int subaccountIndex) {
118
119 void setLabelForSubaddressSync(
120 {required int accountIndex, required int addressIndex, required String label}) {
116 - wownero.Wallet_setSubaddressLabel(wptr!, accountIndex: accountIndex, addressIndex: addressIndex, label: label);
121 + wownero.Wallet_setSubaddressLabel(wptr!,
122 + accountIndex: accountIndex, addressIndex: addressIndex, label: label);
123 }
124
125 void _addSubaddress(Map<String, dynamic> args) {
@@ -128,8 +134,7 @@ void _setLabelForSubaddress(Map<String, dynamic> args) {
134 final accountIndex = args['accountIndex'] as int;
135 final addressIndex = args['addressIndex'] as int;
136
131 - setLabelForSubaddressSync(
132 - accountIndex: accountIndex, addressIndex: addressIndex, label: label);
137 + setLabelForSubaddressSync(accountIndex: accountIndex, addressIndex: addressIndex, label: label);
138 }
139
140 Future<void> addSubaddress({required int accountIndex, required String label}) async {
@@ -138,11 +143,8 @@ Future<void> addSubaddress({required int accountIndex, required String label}) a
143 }
144
145 Future<void> setLabelForSubaddress(
141 - {required int accountIndex, required int addressIndex, required String label}) async {
142 - _setLabelForSubaddress({
143 - 'accountIndex': accountIndex,
144 - 'addressIndex': addressIndex,
145 - 'label': label
146 - });
146 + {required int accountIndex, required int addressIndex, required String label}) async {
147 + _setLabelForSubaddress(
148 + {'accountIndex': accountIndex, 'addressIndex': addressIndex, 'label': label});
149 await store();
150 }
cw_wownero/lib/api/transaction_history.dart
+72 -66
@@ -43,33 +43,36 @@ Future<List<Transaction>> getAllTransactions() async {
43 await txHistoryMutex.acquire();
44 txhistory ??= wownero.Wallet_history(wptr!);
45 int size = countOfTransactions();
46 - final list = List.generate(size, (index) => Transaction(txInfo: wownero.TransactionHistory_transaction(txhistory!, index: index)));
46 + final list = List.generate(
47 + size,
48 + (index) =>
49 + Transaction(txInfo: wownero.TransactionHistory_transaction(txhistory!, index: index)));
50 txHistoryMutex.release();
48 -
51 +
52 final accts = wownero.Wallet_numSubaddressAccounts(wptr!);
50 - for (var i = 0; i < accts; i++) {
53 + for (var i = 0; i < accts; i++) {
54 final fullBalance = wownero.Wallet_balance(wptr!, accountIndex: i);
55 final availBalance = wownero.Wallet_unlockedBalance(wptr!, accountIndex: i);
56 if (fullBalance > availBalance) {
54 - if (list.where((element) => element.accountIndex == i && element.isConfirmed == false).isEmpty) {
55 - dummyTxs.add(
56 - Transaction.dummy(
57 - displayLabel: "",
58 - description: "",
59 - fee: 0,
60 - confirmations: 0,
61 - blockheight: 0,
62 - accountIndex: i,
63 - addressIndex: 0,
64 - addressIndexList: [0],
65 - paymentId: "",
66 - amount: fullBalance - availBalance,
67 - isSpend: false,
68 - hash: "pending",
69 - key: "pending",
70 - txInfo: Pointer.fromAddress(0),
71 - )..timeStamp = DateTime.now()
72 - );
57 + if (list
58 + .where((element) => element.accountIndex == i && element.isConfirmed == false)
59 + .isEmpty) {
60 + dummyTxs.add(Transaction.dummy(
61 + displayLabel: "",
62 + description: "",
63 + fee: 0,
64 + confirmations: 0,
65 + blockheight: 0,
66 + accountIndex: i,
67 + addressIndex: 0,
68 + addressIndexList: [0],
69 + paymentId: "",
70 + amount: fullBalance - availBalance,
71 + isSpend: false,
72 + hash: "pending",
73 + key: "pending",
74 + txInfo: Pointer.fromAddress(0),
75 + )..timeStamp = DateTime.now());
76 }
77 }
78 }
@@ -89,13 +92,13 @@ Future<PendingTransactionDescription> createTransactionSync(
92 String? amount,
93 int accountIndex = 0,
94 List<String> preferredInputs = const []}) async {
92 -
95 final amt = amount == null ? 0 : wownero.Wallet_amountFromString(amount);
94 -
95 - final address_ = address.toNativeUtf8();
96 +
97 + final address_ = address.toNativeUtf8();
98 final paymentId_ = paymentId.toNativeUtf8();
99 if (preferredInputs.isEmpty) {
98 - throw WowneroTransactionCreationException("No inputs provided, transaction cannot be constructed");
100 + throw WowneroTransactionCreationException(
101 + "No inputs provided, transaction cannot be constructed");
102 }
103 final preferredInputs_ = preferredInputs.join(wownero.defaultSeparatorStr).toNativeUtf8();
104
@@ -105,7 +108,8 @@ Future<PendingTransactionDescription> createTransactionSync(
108 final preferredInputsAddr = preferredInputs_.address;
109 final spaddr = wownero.defaultSeparator.address;
110 final pendingTx = Pointer<Void>.fromAddress(await Isolate.run(() {
108 - final tx = wownero_gen.WowneroC(DynamicLibrary.open(wownero.libPath)).WOWNERO_Wallet_createTransaction(
111 + final tx =
112 + wownero_gen.WowneroC(DynamicLibrary.open(wownero.libPath)).WOWNERO_Wallet_createTransaction(
113 Pointer.fromAddress(waddr),
114 Pointer.fromAddress(addraddr).cast(),
115 Pointer.fromAddress(paymentIdAddr).cast(),
@@ -140,13 +144,13 @@ Future<PendingTransactionDescription> createTransactionSync(
144 final rTxKey = rHash;
145
146 return PendingTransactionDescription(
143 - amount: rAmt,
144 - fee: rFee,
145 - hash: rHash,
146 - hex: '',
147 - txKey: rTxKey,
148 - pointerAddress: pendingTx.address,
149 - );
147 + amount: rAmt,
148 + fee: rFee,
149 + hash: rHash,
150 + hex: '',
151 + txKey: rTxKey,
152 + pointerAddress: pendingTx.address,
153 + );
154 }
155
156 PendingTransactionDescription createTransactionMultDestSync(
@@ -155,7 +159,6 @@ PendingTransactionDescription createTransactionMultDestSync(
159 required int priorityRaw,
160 int accountIndex = 0,
161 List<String> preferredInputs = const []}) {
158 -
162 final txptr = wownero.Wallet_createTransactionMultDest(
163 wptr!,
164 dstAddr: outputs.map((e) => e.address).toList(),
@@ -182,8 +185,8 @@ void commitTransactionFromPointerAddress({required int address}) =>
185 commitTransaction(transactionPointer: wownero.PendingTransaction.fromAddress(address));
186
187 void commitTransaction({required wownero.PendingTransaction transactionPointer}) {
185 -
186 - final txCommit = wownero.PendingTransaction_commit(transactionPointer, filename: '', overwrite: false);
188 + final txCommit =
189 + wownero.PendingTransaction_commit(transactionPointer, filename: '', overwrite: false);
190
191 String? error = (() {
192 final status = wownero.PendingTransaction_status(transactionPointer.cast());
@@ -200,9 +203,8 @@ void commitTransaction({required wownero.PendingTransaction transactionPointer})
203 }
204 return wownero.Wallet_errorString(wptr!);
205 })();
203 -
206 }
205 -
207 +
208 if (error != null) {
209 throw CreationTransactionException(message: error);
210 }
@@ -270,19 +272,20 @@ Future<PendingTransactionDescription> createTransactionMultDest(
272 'preferredInputs': preferredInputs
273 });
274
273 -
275 class Transaction {
276 final String displayLabel;
276 - late final String subaddressLabel = wownero.Wallet_getSubaddressLabel(wptr!, accountIndex: accountIndex, addressIndex: addressIndex);
277 + late final String subaddressLabel = wownero.Wallet_getSubaddressLabel(wptr!,
278 + accountIndex: accountIndex, addressIndex: addressIndex);
279 late final String address = getAddress(
280 accountIndex: accountIndex,
281 addressIndex: addressIndex,
282 );
281 - late final List<String> addressList = List.generate(addressIndexList.length, (index) =>
282 - getAddress(
283 - accountIndex: accountIndex,
284 - addressIndex: addressIndexList[index],
285 - ));
283 + late final List<String> addressList = List.generate(
284 + addressIndexList.length,
285 + (index) => getAddress(
286 + accountIndex: accountIndex,
287 + addressIndex: addressIndexList[index],
288 + ));
289 final String description;
290 final int fee;
291 final int confirmations;
@@ -331,33 +334,36 @@ class Transaction {
334 timeStamp = DateTime.fromMillisecondsSinceEpoch(
335 wownero.TransactionInfo_timestamp(txInfo) * 1000,
336 ),
334 - isSpend = wownero.TransactionInfo_direction(txInfo) ==
335 - wownero.TransactionInfo_Direction.Out,
337 + isSpend =
338 + wownero.TransactionInfo_direction(txInfo) == wownero.TransactionInfo_Direction.Out,
339 amount = wownero.TransactionInfo_amount(txInfo),
340 paymentId = wownero.TransactionInfo_paymentId(txInfo),
341 accountIndex = wownero.TransactionInfo_subaddrAccount(txInfo),
339 - addressIndex = int.tryParse(wownero.TransactionInfo_subaddrIndex(txInfo).split(", ")[0]) ?? 0,
340 - addressIndexList = wownero.TransactionInfo_subaddrIndex(txInfo).split(", ").map((e) => int.tryParse(e) ?? 0).toList(),
342 + addressIndex =
343 + int.tryParse(wownero.TransactionInfo_subaddrIndex(txInfo).split(", ")[0]) ?? 0,
344 + addressIndexList = wownero.TransactionInfo_subaddrIndex(txInfo)
345 + .split(", ")
346 + .map((e) => int.tryParse(e) ?? 0)
347 + .toList(),
348 blockheight = wownero.TransactionInfo_blockHeight(txInfo),
349 confirmations = wownero.TransactionInfo_confirmations(txInfo),
350 fee = wownero.TransactionInfo_fee(txInfo),
351 description = wownero.TransactionInfo_description(txInfo),
352 key = wownero.Wallet_getTxKey(wptr!, txid: wownero.TransactionInfo_hash(txInfo));
353
347 - Transaction.dummy({
348 - required this.displayLabel,
349 - required this.description,
350 - required this.fee,
351 - required this.confirmations,
352 - required this.blockheight,
353 - required this.accountIndex,
354 - required this.addressIndex,
355 - required this.addressIndexList,
356 - required this.paymentId,
357 - required this.amount,
358 - required this.isSpend,
359 - required this.hash,
360 - required this.key,
361 - required this.txInfo
362 - });
354 + Transaction.dummy(
355 + {required this.displayLabel,
356 + required this.description,
357 + required this.fee,
358 + required this.confirmations,
359 + required this.blockheight,
360 + required this.accountIndex,
361 + required this.addressIndex,
362 + required this.addressIndexList,
363 + required this.paymentId,
364 + required this.amount,
365 + required this.isSpend,
366 + required this.hash,
367 + required this.key,
368 + required this.txInfo});
369 }
cw_wownero/lib/api/wallet.dart
+30 -20
@@ -34,8 +34,7 @@ String getFilename() => wownero.Wallet_filename(wptr!);
34
35 String getSeed() {
36 // monero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.seed", value: seed);
37 - final cakepolyseed =
38 - wownero.Wallet_getCacheAttribute(wptr!, key: "cakewallet.seed");
37 + final cakepolyseed = wownero.Wallet_getCacheAttribute(wptr!, key: "cakewallet.seed");
38 final cakepassphrase = getPassphrase();
39
40 final weirdPolyseed = wownero.Wallet_getPolyseed(wptr!, passphrase: cakepassphrase);
@@ -65,11 +64,21 @@ String getSeedLegacy(String? language) {
64 final cakepassphrase = getPassphrase();
65 var legacy = wownero.Wallet_seed(wptr!, seedOffset: cakepassphrase);
66 switch (language) {
68 - case "Chinese (Traditional)": language = "Chinese (simplified)"; break;
69 - case "Chinese (Simplified)": language = "Chinese (simplified)"; break;
70 - case "Korean": language = "English"; break;
71 - case "Czech": language = "English"; break;
72 - case "Japanese": language = "English"; break;
67 + case "Chinese (Traditional)":
68 + language = "Chinese (simplified)";
69 + break;
70 + case "Chinese (Simplified)":
71 + language = "Chinese (simplified)";
72 + break;
73 + case "Korean":
74 + language = "English";
75 + break;
76 + case "Czech":
77 + language = "English";
78 + break;
79 + case "Japanese":
80 + language = "English";
81 + break;
82 }
83 if (wownero.Wallet_status(wptr!) != 0) {
84 wownero.Wallet_setSeedLanguage(wptr!, language: language ?? "English");
@@ -84,6 +93,7 @@ String getSeedLegacy(String? language) {
93 }
94 return legacy;
95 }
96 +
97 Map<int, Map<int, Map<int, String>>> addressCache = {};
98
99 String getPassphrase() {
@@ -91,14 +101,14 @@ String getPassphrase() {
101 }
102
103 String getAddress({int accountIndex = 0, int addressIndex = 1}) {
94 - while (wownero.Wallet_numSubaddresses(wptr!, accountIndex: accountIndex)-1 < addressIndex) {
104 + while (wownero.Wallet_numSubaddresses(wptr!, accountIndex: accountIndex) - 1 < addressIndex) {
105 printV("adding subaddress");
106 wownero.Wallet_addSubaddress(wptr!, accountIndex: accountIndex);
107 }
108 addressCache[wptr!.address] ??= {};
109 addressCache[wptr!.address]![accountIndex] ??= {};
100 - addressCache[wptr!.address]![accountIndex]![addressIndex] ??= wownero.Wallet_address(wptr!,
101 - accountIndex: accountIndex, addressIndex: addressIndex);
110 + addressCache[wptr!.address]![accountIndex]![addressIndex] ??=
111 + wownero.Wallet_address(wptr!, accountIndex: accountIndex, addressIndex: addressIndex);
112 return addressCache[wptr!.address]![accountIndex]![addressIndex]!;
113 }
114
@@ -106,10 +116,12 @@ int getFullBalance({int accountIndex = 0}) {
116 if (wptr == null) return 0;
117 return wownero.Wallet_balance(wptr!, accountIndex: accountIndex);
118 }
119 +
120 int getUnlockedBalance({int accountIndex = 0}) {
121 if (wptr == null) return 0;
122 return wownero.Wallet_unlockedBalance(wptr!, accountIndex: accountIndex);
123 }
124 +
125 int getCurrentHeight() {
126 if (wptr == null) return 0;
127 return wownero.Wallet_blockChainHeight(wptr!);
@@ -181,8 +193,7 @@ Future<bool> connectToNode() async {
193 }
194
195 void setRefreshFromBlockHeight({required int height}) =>
184 - wownero.Wallet_setRefreshFromBlockHeight(wptr!,
185 - refresh_from_block_height: height);
196 + wownero.Wallet_setRefreshFromBlockHeight(wptr!, refresh_from_block_height: height);
197
198 void setRecoveringFromSeed({required bool isRecovery}) =>
199 wownero.Wallet_setRecoveringFromSeed(wptr!, recoveringFromSeed: isRecovery);
@@ -257,8 +268,7 @@ class SyncListener {
268 _cachedBlockchainHeight = 0;
269 _lastKnownBlockHeight = 0;
270 _initialSyncHeight = 0;
260 - _updateSyncInfoTimer ??=
261 - Timer.periodic(Duration(milliseconds: 1200), (_) async {
271 + _updateSyncInfoTimer ??= Timer.periodic(Duration(milliseconds: 1200), (_) async {
272 if (isNewTransactionExist()) {
273 onNewTransaction();
274 }
@@ -297,8 +307,8 @@ class SyncListener {
307 void stop() => _updateSyncInfoTimer?.cancel();
308 }
309
300 -SyncListener setListeners(void Function(int, int, double) onNewBlock,
301 - void Function() onNewTransaction) {
310 +SyncListener setListeners(
311 + void Function(int, int, double) onNewBlock, void Function() onNewTransaction) {
312 final listener = SyncListener(onNewBlock, onNewTransaction);
313 // setListenerNative();
314 return listener;
@@ -360,8 +370,7 @@ String getSubaddressLabel(int accountIndex, int addressIndex) {
370 accountIndex: accountIndex, addressIndex: addressIndex);
371 }
372
363 -Future setTrustedDaemon(bool trusted) async =>
364 - wownero.Wallet_setTrustedDaemon(wptr!, arg: trusted);
373 +Future setTrustedDaemon(bool trusted) async => wownero.Wallet_setTrustedDaemon(wptr!, arg: trusted);
374
375 Future<bool> trustedDaemon() async => wownero.Wallet_trustedDaemon(wptr!);
376
@@ -370,7 +379,8 @@ String signMessage(String message, {String address = ""}) {
379 }
380
381 bool verifyMessage(String message, String address, String signature) {
373 - return wownero.Wallet_verifySignedMessage(wptr!, message: message, address: address, signature: signature);
382 + return wownero.Wallet_verifySignedMessage(wptr!,
383 + message: message, address: address, signature: signature);
384 }
385
376 -Map<String, List<int>> debugCallLength() => wownero.debugCallLength;
\ No newline at end of file
386 +Map<String, List<int>> debugCallLength() => wownero.debugCallLength;
cw_wownero/lib/api/wallet_manager.dart
+39 -44
@@ -34,15 +34,18 @@ void checkIfMoneroCIsFine() {
34 final dartCsExp = wownero.wallet2_api_c_exp_sha256;
35
36 if (cppCsCpp != dartCsCpp) {
37 - throw MoneroCException("monero_c and monero.dart cpp wrapper code mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsCpp'\ndart: '$dartCsCpp'");
37 + throw MoneroCException(
38 + "monero_c and monero.dart cpp wrapper code mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsCpp'\ndart: '$dartCsCpp'");
39 }
40
41 if (cppCsH != dartCsH) {
41 - throw MoneroCException("monero_c and monero.dart cpp wrapper header mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsH'\ndart: '$dartCsH'");
42 + throw MoneroCException(
43 + "monero_c and monero.dart cpp wrapper header mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsH'\ndart: '$dartCsH'");
44 }
45
46 if (cppCsExp != dartCsExp && (Platform.isIOS || Platform.isMacOS)) {
45 - throw MoneroCException("monero_c and monero.dart wrapper export list mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsExp'\ndart: '$dartCsExp'");
47 + throw MoneroCException(
48 + "monero_c and monero.dart wrapper export list mismatch.\nLogic errors can occur.\nRefusing to run in release mode.\ncpp: '$cppCsExp'\ndart: '$dartCsExp'");
49 }
50 }
51
@@ -133,10 +136,10 @@ void restoreWalletFromSeedSync(
136 }
137
138 wptr = newWptr;
136 -
139 +
140 wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase);
141 wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.seed", value: seed);
139 -
142 +
143 openedWalletsByPath[path] = wptr!;
144
145 store();
@@ -153,29 +156,27 @@ void restoreWalletFromKeysSync(
156 int restoreHeight = 0}) {
157 txhistory = null;
158 var newWptr = (spendKey != "")
156 - ? wownero.WalletManager_createDeterministicWalletFromSpendKey(
157 - wmPtr,
158 - path: path,
159 - password: password,
160 - language: language,
161 - spendKeyString: spendKey,
162 - newWallet: true, // TODO(mrcyjanek): safe to remove
163 - restoreHeight: restoreHeight)
164 - : wownero.WalletManager_createWalletFromKeys(
165 - wmPtr,
166 - path: path,
167 - password: password,
168 - restoreHeight: restoreHeight,
169 - addressString: address,
170 - viewKeyString: viewKey,
171 - spendKeyString: spendKey,
172 - nettype: 0,
173 - );
159 + ? wownero.WalletManager_createDeterministicWalletFromSpendKey(wmPtr,
160 + path: path,
161 + password: password,
162 + language: language,
163 + spendKeyString: spendKey,
164 + newWallet: true, // TODO(mrcyjanek): safe to remove
165 + restoreHeight: restoreHeight)
166 + : wownero.WalletManager_createWalletFromKeys(
167 + wmPtr,
168 + path: path,
169 + password: password,
170 + restoreHeight: restoreHeight,
171 + addressString: address,
172 + viewKeyString: viewKey,
173 + spendKeyString: spendKey,
174 + nettype: 0,
175 + );
176
177 final status = wownero.Wallet_status(newWptr);
178 if (status != 0) {
177 - throw WalletRestoreFromKeysException(
178 - message: wownero.Wallet_errorString(newWptr));
179 + throw WalletRestoreFromKeysException(message: wownero.Wallet_errorString(newWptr));
180 }
181 // CW-712 - Try to restore deterministic wallet first, if the view key doesn't
182 // match the view key provided
@@ -184,7 +185,7 @@ void restoreWalletFromKeysSync(
185 if (viewKey != viewKeyRestored && viewKey != "") {
186 wownero.WalletManager_closeWallet(wmPtr, newWptr, false);
187 File(path).deleteSync();
187 - File(path+".keys").deleteSync();
188 + File(path + ".keys").deleteSync();
189 newWptr = wownero.WalletManager_createWalletFromKeys(
190 wmPtr,
191 path: path,
@@ -197,8 +198,7 @@ void restoreWalletFromKeysSync(
198 );
199 final status = wownero.Wallet_status(newWptr);
200 if (status != 0) {
200 - throw WalletRestoreFromKeysException(
201 - message: wownero.Wallet_errorString(newWptr));
201 + throw WalletRestoreFromKeysException(message: wownero.Wallet_errorString(newWptr));
202 }
203 }
204 }
@@ -207,8 +207,6 @@ void restoreWalletFromKeysSync(
207 openedWalletsByPath[path] = wptr!;
208 }
209
210 -
211 -
210 // English only, because normalization.
211 void restoreWalletFromPolyseedWithOffset(
212 {required String path,
@@ -217,7 +215,6 @@ void restoreWalletFromPolyseedWithOffset(
215 required String seedOffset,
216 required String language,
217 int nettype = 0}) {
220 -
218 txhistory = null;
219 final newWptr = wownero.WalletManager_createWalletFromPolyseed(
220 wmPtr,
@@ -332,8 +329,7 @@ String _lastOpenedWallet = "";
329
330 Map<String, wownero.wallet> openedWalletsByPath = {};
331
335 -void loadWallet(
336 - {required String path, required String password, int nettype = 0}) {
332 +void loadWallet({required String path, required String password, int nettype = 0}) {
333 if (openedWalletsByPath[path] != null) {
334 txhistory = null;
335 wptr = openedWalletsByPath[path]!;
@@ -347,8 +343,7 @@ void loadWallet(
343 });
344 }
345 txhistory = null;
350 - final newWptr = wownero.WalletManager_openWallet(wmPtr,
351 - path: path, password: password);
346 + final newWptr = wownero.WalletManager_openWallet(wmPtr, path: path, password: password);
347
348 _lastOpenedWallet = path;
349 final status = wownero.Wallet_status(newWptr);
@@ -379,7 +374,11 @@ void _restoreFromSeed(Map<String, dynamic> args) {
374 final restoreHeight = args['restoreHeight'] as int;
375
376 restoreWalletFromSeedSync(
382 - path: path, password: password, passphrase: passphrase, seed: seed, restoreHeight: restoreHeight);
377 + path: path,
378 + password: password,
379 + passphrase: passphrase,
380 + seed: seed,
381 + restoreHeight: restoreHeight);
382 }
383
384 void _restoreFromKeys(Map<String, dynamic> args) {
@@ -418,19 +417,15 @@ void _restoreFromSpendKey(Map<String, dynamic> args) {
417 spendKey: spendKey);
418 }
419
421 -Future<void> _openWallet(Map<String, String> args) async => loadWallet(
422 - path: args['path'] as String, password: args['password'] as String);
420 +Future<void> _openWallet(Map<String, String> args) async =>
421 + loadWallet(path: args['path'] as String, password: args['password'] as String);
422
423 Future<bool> _isWalletExist(String path) async => isWalletExistSync(path: path);
424
426 -void openWallet(
427 - {required String path,
428 - required String password,
429 - int nettype = 0}) async =>
425 +void openWallet({required String path, required String password, int nettype = 0}) async =>
426 loadWallet(path: path, password: password, nettype: nettype);
427
432 -Future<void> openWalletAsync(Map<String, String> args) async =>
433 - _openWallet(args);
428 +Future<void> openWalletAsync(Map<String, String> args) async => _openWallet(args);
429
430 Future<void> createWallet(
431 {required String path,
cw_wownero/lib/api/wownero_output.dart
+1 -1
@@ -3,4 +3,4 @@ class WowneroOutput {
3
4 final String address;
5 final String amount;
6 -}
\ No newline at end of file
6 +}
cw_wownero/lib/cw_wownero.dart
-1
@@ -1,4 +1,3 @@
1 -
1 import 'cw_wownero_platform_interface.dart';
2
3 class CwWownero {
cw_wownero/lib/exceptions/wownero_transaction_creation_exception.dart
+1 -1
@@ -5,4 +5,4 @@ class WowneroTransactionCreationException implements Exception {
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_wownero/lib/exceptions/wownero_transaction_no_inputs_exception.dart
+2 -1
@@ -4,5 +4,6 @@ class WowneroTransactionNoInputsException implements Exception {
4 int inputsSize;
5
6 @override
7 - String toString() => 'Not enough inputs ($inputsSize) selected. Please select more under Coin Control';
7 + String toString() =>
8 + 'Not enough inputs ($inputsSize) selected. Please select more under Coin Control';
9 }
cw_wownero/lib/mnemonics/chinese_simplified.dart
+1 -1
@@ -1627,4 +1627,4 @@ class ChineseSimplifiedMnemonics {
1627 "浙",
1628 "貌"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_wownero/lib/mnemonics/dutch.dart
+1 -1
@@ -1627,4 +1627,4 @@ class DutchMnemonics {
1627 "zwijmel",
1628 "zworen"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_wownero/lib/mnemonics/french.dart
+1629 -1629
@@ -1,1630 +1,1630 @@
1 class FrenchMnemonics {
2 - static const words = [
3 - "abandon",
4 - "abattre",
5 - "aboi",
6 - "abolir",
7 - "aborder",
8 - "abri",
9 - "absence",
10 - "absolu",
11 - "abuser",
12 - "acacia",
13 - "acajou",
14 - "accent",
15 - "accord",
16 - "accrocher",
17 - "accuser",
18 - "acerbe",
19 - "achat",
20 - "acheter",
21 - "acide",
22 - "acier",
23 - "acquis",
24 - "acte",
25 - "action",
26 - "adage",
27 - "adepte",
28 - "adieu",
29 - "admettre",
30 - "admis",
31 - "adorer",
32 - "adresser",
33 - "aduler",
34 - "affaire",
35 - "affirmer",
36 - "afin",
37 - "agacer",
38 - "agent",
39 - "agir",
40 - "agiter",
41 - "agonie",
42 - "agrafe",
43 - "agrume",
44 - "aider",
45 - "aigle",
46 - "aigre",
47 - "aile",
48 - "ailleurs",
49 - "aimant",
50 - "aimer",
51 - "ainsi",
52 - "aise",
53 - "ajouter",
54 - "alarme",
55 - "album",
56 - "alcool",
57 - "alerte",
58 - "algue",
59 - "alibi",
60 - "aller",
61 - "allumer",
62 - "alors",
63 - "amande",
64 - "amener",
65 - "amie",
66 - "amorcer",
67 - "amour",
68 - "ample",
69 - "amuser",
70 - "ananas",
71 - "ancien",
72 - "anglais",
73 - "angoisse",
74 - "animal",
75 - "anneau",
76 - "annoncer",
77 - "apercevoir",
78 - "apparence",
79 - "appel",
80 - "apporter",
81 - "apprendre",
82 - "appuyer",
83 - "arbre",
84 - "arcade",
85 - "arceau",
86 - "arche",
87 - "ardeur",
88 - "argent",
89 - "argile",
90 - "aride",
91 - "arme",
92 - "armure",
93 - "arracher",
94 - "arriver",
95 - "article",
96 - "asile",
97 - "aspect",
98 - "assaut",
99 - "assez",
100 - "assister",
101 - "assurer",
102 - "astre",
103 - "astuce",
104 - "atlas",
105 - "atroce",
106 - "attacher",
107 - "attente",
108 - "attirer",
109 - "aube",
110 - "aucun",
111 - "audace",
112 - "auparavant",
113 - "auquel",
114 - "aurore",
115 - "aussi",
116 - "autant",
117 - "auteur",
118 - "autoroute",
119 - "autre",
120 - "aval",
121 - "avant",
122 - "avec",
123 - "avenir",
124 - "averse",
125 - "aveu",
126 - "avide",
127 - "avion",
128 - "avis",
129 - "avoir",
130 - "avouer",
131 - "avril",
132 - "azote",
133 - "azur",
134 - "badge",
135 - "bagage",
136 - "bague",
137 - "bain",
138 - "baisser",
139 - "balai",
140 - "balcon",
141 - "balise",
142 - "balle",
143 - "bambou",
144 - "banane",
145 - "banc",
146 - "bandage",
147 - "banjo",
148 - "banlieue",
149 - "bannir",
150 - "banque",
151 - "baobab",
152 - "barbe",
153 - "barque",
154 - "barrer",
155 - "bassine",
156 - "bataille",
157 - "bateau",
158 - "battre",
159 - "baver",
160 - "bavoir",
161 - "bazar",
162 - "beau",
163 - "beige",
164 - "berger",
165 - "besoin",
166 - "beurre",
167 - "biais",
168 - "biceps",
169 - "bidule",
170 - "bien",
171 - "bijou",
172 - "bilan",
173 - "billet",
174 - "blanc",
175 - "blason",
176 - "bleu",
177 - "bloc",
178 - "blond",
179 - "bocal",
180 - "boire",
181 - "boiserie",
182 - "boiter",
183 - "bonbon",
184 - "bondir",
185 - "bonheur",
186 - "bordure",
187 - "borgne",
188 - "borner",
189 - "bosse",
190 - "bouche",
191 - "bouder",
192 - "bouger",
193 - "boule",
194 - "bourse",
195 - "bout",
196 - "boxe",
197 - "brader",
198 - "braise",
199 - "branche",
200 - "braquer",
201 - "bras",
202 - "brave",
203 - "brebis",
204 - "brevet",
205 - "brider",
206 - "briller",
207 - "brin",
208 - "brique",
209 - "briser",
210 - "broche",
211 - "broder",
212 - "bronze",
213 - "brosser",
214 - "brouter",
215 - "bruit",
216 - "brute",
217 - "budget",
218 - "buffet",
219 - "bulle",
220 - "bureau",
221 - "buriner",
222 - "buste",
223 - "buter",
224 - "butiner",
225 - "cabas",
226 - "cabinet",
227 - "cabri",
228 - "cacao",
229 - "cacher",
230 - "cadeau",
231 - "cadre",
232 - "cage",
233 - "caisse",
234 - "caler",
235 - "calme",
236 - "camarade",
237 - "camion",
238 - "campagne",
239 - "canal",
240 - "canif",
241 - "capable",
242 - "capot",
243 - "carat",
244 - "caresser",
245 - "carie",
246 - "carpe",
247 - "cartel",
248 - "casier",
249 - "casque",
250 - "casserole",
251 - "cause",
252 - "cavale",
253 - "cave",
254 - "ceci",
255 - "cela",
256 - "celui",
257 - "cendre",
258 - "cent",
259 - "cependant",
260 - "cercle",
261 - "cerise",
262 - "cerner",
263 - "certes",
264 - "cerveau",
265 - "cesser",
266 - "chacun",
267 - "chair",
268 - "chaleur",
269 - "chamois",
270 - "chanson",
271 - "chaque",
272 - "charge",
273 - "chasse",
274 - "chat",
275 - "chaud",
276 - "chef",
277 - "chemin",
278 - "cheveu",
279 - "chez",
280 - "chicane",
281 - "chien",
282 - "chiffre",
283 - "chiner",
284 - "chiot",
285 - "chlore",
286 - "choc",
287 - "choix",
288 - "chose",
289 - "chou",
290 - "chute",
291 - "cibler",
292 - "cidre",
293 - "ciel",
294 - "cigale",
295 - "cinq",
296 - "cintre",
297 - "cirage",
298 - "cirque",
299 - "ciseau",
300 - "citation",
301 - "citer",
302 - "citron",
303 - "civet",
304 - "clairon",
305 - "clan",
306 - "classe",
307 - "clavier",
308 - "clef",
309 - "climat",
310 - "cloche",
311 - "cloner",
312 - "clore",
313 - "clos",
314 - "clou",
315 - "club",
316 - "cobra",
317 - "cocon",
318 - "coiffer",
319 - "coin",
320 - "colline",
321 - "colon",
322 - "combat",
323 - "comme",
324 - "compte",
325 - "conclure",
326 - "conduire",
327 - "confier",
328 - "connu",
329 - "conseil",
330 - "contre",
331 - "convenir",
332 - "copier",
333 - "cordial",
334 - "cornet",
335 - "corps",
336 - "cosmos",
337 - "coton",
338 - "couche",
339 - "coude",
340 - "couler",
341 - "coupure",
342 - "cour",
343 - "couteau",
344 - "couvrir",
345 - "crabe",
346 - "crainte",
347 - "crampe",
348 - "cran",
349 - "creuser",
350 - "crever",
351 - "crier",
352 - "crime",
353 - "crin",
354 - "crise",
355 - "crochet",
356 - "croix",
357 - "cruel",
358 - "cuisine",
359 - "cuite",
360 - "culot",
361 - "culte",
362 - "cumul",
363 - "cure",
364 - "curieux",
365 - "cuve",
366 - "dame",
367 - "danger",
368 - "dans",
369 - "davantage",
370 - "debout",
371 - "dedans",
372 - "dehors",
373 - "delta",
374 - "demain",
375 - "demeurer",
376 - "demi",
377 - "dense",
378 - "dent",
379 - "depuis",
380 - "dernier",
381 - "descendre",
382 - "dessus",
383 - "destin",
384 - "dette",
385 - "deuil",
386 - "deux",
387 - "devant",
388 - "devenir",
389 - "devin",
390 - "devoir",
391 - "dicton",
392 - "dieu",
393 - "difficile",
394 - "digestion",
395 - "digue",
396 - "diluer",
397 - "dimanche",
398 - "dinde",
399 - "diode",
400 - "dire",
401 - "diriger",
402 - "discours",
403 - "disposer",
404 - "distance",
405 - "divan",
406 - "divers",
407 - "docile",
408 - "docteur",
409 - "dodu",
410 - "dogme",
411 - "doigt",
412 - "dominer",
413 - "donation",
414 - "donjon",
415 - "donner",
416 - "dopage",
417 - "dorer",
418 - "dormir",
419 - "doseur",
420 - "douane",
421 - "double",
422 - "douche",
423 - "douleur",
424 - "doute",
425 - "doux",
426 - "douzaine",
427 - "draguer",
428 - "drame",
429 - "drap",
430 - "dresser",
431 - "droit",
432 - "duel",
433 - "dune",
434 - "duper",
435 - "durant",
436 - "durcir",
437 - "durer",
438 - "eaux",
439 - "effacer",
440 - "effet",
441 - "effort",
442 - "effrayant",
443 - "elle",
444 - "embrasser",
445 - "emmener",
446 - "emparer",
447 - "empire",
448 - "employer",
449 - "emporter",
450 - "enclos",
451 - "encore",
452 - "endive",
453 - "endormir",
454 - "endroit",
455 - "enduit",
456 - "enfant",
457 - "enfermer",
458 - "enfin",
459 - "enfler",
460 - "enfoncer",
461 - "enfuir",
462 - "engager",
463 - "engin",
464 - "enjeu",
465 - "enlever",
466 - "ennemi",
467 - "ennui",
468 - "ensemble",
469 - "ensuite",
470 - "entamer",
471 - "entendre",
472 - "entier",
473 - "entourer",
474 - "entre",
475 - "envelopper",
476 - "envie",
477 - "envoyer",
478 - "erreur",
479 - "escalier",
480 - "espace",
481 - "espoir",
482 - "esprit",
483 - "essai",
484 - "essor",
485 - "essuyer",
486 - "estimer",
487 - "exact",
488 - "examiner",
489 - "excuse",
490 - "exemple",
491 - "exiger",
492 - "exil",
493 - "exister",
494 - "exode",
495 - "expliquer",
496 - "exposer",
497 - "exprimer",
498 - "extase",
499 - "fable",
500 - "facette",
501 - "facile",
502 - "fade",
503 - "faible",
504 - "faim",
505 - "faire",
506 - "fait",
507 - "falloir",
508 - "famille",
509 - "faner",
510 - "farce",
511 - "farine",
512 - "fatigue",
513 - "faucon",
514 - "faune",
515 - "faute",
516 - "faux",
517 - "faveur",
518 - "favori",
519 - "faxer",
520 - "feinter",
521 - "femme",
522 - "fendre",
523 - "fente",
524 - "ferme",
525 - "festin",
526 - "feuille",
527 - "feutre",
528 - "fiable",
529 - "fibre",
530 - "ficher",
531 - "fier",
532 - "figer",
533 - "figure",
534 - "filet",
535 - "fille",
536 - "filmer",
537 - "fils",
538 - "filtre",
539 - "final",
540 - "finesse",
541 - "finir",
542 - "fiole",
543 - "firme",
544 - "fixe",
545 - "flacon",
546 - "flair",
547 - "flamme",
548 - "flan",
549 - "flaque",
550 - "fleur",
551 - "flocon",
552 - "flore",
553 - "flot",
554 - "flou",
555 - "fluide",
556 - "fluor",
557 - "flux",
558 - "focus",
559 - "foin",
560 - "foire",
561 - "foison",
562 - "folie",
563 - "fonction",
564 - "fondre",
565 - "fonte",
566 - "force",
567 - "forer",
568 - "forger",
569 - "forme",
570 - "fort",
571 - "fosse",
572 - "fouet",
573 - "fouine",
574 - "foule",
575 - "four",
576 - "foyer",
577 - "frais",
578 - "franc",
579 - "frapper",
580 - "freiner",
581 - "frimer",
582 - "friser",
583 - "frite",
584 - "froid",
585 - "froncer",
586 - "fruit",
587 - "fugue",
588 - "fuir",
589 - "fuite",
590 - "fumer",
591 - "fureur",
592 - "furieux",
593 - "fuser",
594 - "fusil",
595 - "futile",
596 - "futur",
597 - "gagner",
598 - "gain",
599 - "gala",
600 - "galet",
601 - "galop",
602 - "gamme",
603 - "gant",
604 - "garage",
605 - "garde",
606 - "garer",
607 - "gauche",
608 - "gaufre",
609 - "gaule",
610 - "gaver",
611 - "gazon",
612 - "geler",
613 - "genou",
614 - "genre",
615 - "gens",
616 - "gercer",
617 - "germer",
618 - "geste",
619 - "gibier",
620 - "gicler",
621 - "gilet",
622 - "girafe",
623 - "givre",
624 - "glace",
625 - "glisser",
626 - "globe",
627 - "gloire",
628 - "gluant",
629 - "gober",
630 - "golf",
631 - "gommer",
632 - "gorge",
633 - "gosier",
634 - "goutte",
635 - "grain",
636 - "gramme",
637 - "grand",
638 - "gras",
639 - "grave",
640 - "gredin",
641 - "griffure",
642 - "griller",
643 - "gris",
644 - "gronder",
645 - "gros",
646 - "grotte",
647 - "groupe",
648 - "grue",
649 - "guerrier",
650 - "guetter",
651 - "guider",
652 - "guise",
653 - "habiter",
654 - "hache",
655 - "haie",
656 - "haine",
657 - "halte",
658 - "hamac",
659 - "hanche",
660 - "hangar",
661 - "hanter",
662 - "haras",
663 - "hareng",
664 - "harpe",
665 - "hasard",
666 - "hausse",
667 - "haut",
668 - "havre",
669 - "herbe",
670 - "heure",
671 - "hibou",
672 - "hier",
673 - "histoire",
674 - "hiver",
675 - "hochet",
676 - "homme",
677 - "honneur",
678 - "honte",
679 - "horde",
680 - "horizon",
681 - "hormone",
682 - "houle",
683 - "housse",
684 - "hublot",
685 - "huile",
686 - "huit",
687 - "humain",
688 - "humble",
689 - "humide",
690 - "humour",
691 - "hurler",
692 - "idole",
693 - "igloo",
694 - "ignorer",
695 - "illusion",
696 - "image",
697 - "immense",
698 - "immobile",
699 - "imposer",
700 - "impression",
701 - "incapable",
702 - "inconnu",
703 - "index",
704 - "indiquer",
705 - "infime",
706 - "injure",
707 - "inox",
708 - "inspirer",
709 - "instant",
710 - "intention",
711 - "intime",
712 - "inutile",
713 - "inventer",
714 - "inviter",
715 - "iode",
716 - "iris",
717 - "issue",
718 - "ivre",
719 - "jade",
720 - "jadis",
721 - "jamais",
722 - "jambe",
723 - "janvier",
724 - "jardin",
725 - "jauge",
726 - "jaunisse",
727 - "jeter",
728 - "jeton",
729 - "jeudi",
730 - "jeune",
731 - "joie",
732 - "joindre",
733 - "joli",
734 - "joueur",
735 - "journal",
736 - "judo",
737 - "juge",
738 - "juillet",
739 - "juin",
740 - "jument",
741 - "jungle",
742 - "jupe",
743 - "jupon",
744 - "jurer",
745 - "juron",
746 - "jury",
747 - "jusque",
748 - "juste",
749 - "kayak",
750 - "ketchup",
751 - "kilo",
752 - "kiwi",
753 - "koala",
754 - "label",
755 - "lacet",
756 - "lacune",
757 - "laine",
758 - "laisse",
759 - "lait",
760 - "lame",
761 - "lancer",
762 - "lande",
763 - "laque",
764 - "lard",
765 - "largeur",
766 - "larme",
767 - "larve",
768 - "lasso",
769 - "laver",
770 - "lendemain",
771 - "lentement",
772 - "lequel",
773 - "lettre",
774 - "leur",
775 - "lever",
776 - "levure",
777 - "liane",
778 - "libre",
779 - "lien",
780 - "lier",
781 - "lieutenant",
782 - "ligne",
783 - "ligoter",
784 - "liguer",
785 - "limace",
786 - "limer",
787 - "limite",
788 - "lingot",
789 - "lion",
790 - "lire",
791 - "lisser",
792 - "litre",
793 - "livre",
794 - "lobe",
795 - "local",
796 - "logis",
797 - "loin",
798 - "loisir",
799 - "long",
800 - "loque",
801 - "lors",
802 - "lotus",
803 - "louer",
804 - "loup",
805 - "lourd",
806 - "louve",
807 - "loyer",
808 - "lubie",
809 - "lucide",
810 - "lueur",
811 - "luge",
812 - "luire",
813 - "lundi",
814 - "lune",
815 - "lustre",
816 - "lutin",
817 - "lutte",
818 - "luxe",
819 - "machine",
820 - "madame",
821 - "magie",
822 - "magnifique",
823 - "magot",
824 - "maigre",
825 - "main",
826 - "mairie",
827 - "maison",
828 - "malade",
829 - "malheur",
830 - "malin",
831 - "manche",
832 - "manger",
833 - "manier",
834 - "manoir",
835 - "manquer",
836 - "marche",
837 - "mardi",
838 - "marge",
839 - "mariage",
840 - "marquer",
841 - "mars",
842 - "masque",
843 - "masse",
844 - "matin",
845 - "mauvais",
846 - "meilleur",
847 - "melon",
848 - "membre",
849 - "menacer",
850 - "mener",
851 - "mensonge",
852 - "mentir",
853 - "menu",
854 - "merci",
855 - "merlu",
856 - "mesure",
857 - "mettre",
858 - "meuble",
859 - "meunier",
860 - "meute",
861 - "miche",
862 - "micro",
863 - "midi",
864 - "miel",
865 - "miette",
866 - "mieux",
867 - "milieu",
868 - "mille",
869 - "mimer",
870 - "mince",
871 - "mineur",
872 - "ministre",
873 - "minute",
874 - "mirage",
875 - "miroir",
876 - "miser",
877 - "mite",
878 - "mixte",
879 - "mobile",
880 - "mode",
881 - "module",
882 - "moins",
883 - "mois",
884 - "moment",
885 - "momie",
886 - "monde",
887 - "monsieur",
888 - "monter",
889 - "moquer",
890 - "moral",
891 - "morceau",
892 - "mordre",
893 - "morose",
894 - "morse",
895 - "mortier",
896 - "morue",
897 - "motif",
898 - "motte",
899 - "moudre",
900 - "moule",
901 - "mourir",
902 - "mousse",
903 - "mouton",
904 - "mouvement",
905 - "moyen",
906 - "muer",
907 - "muette",
908 - "mugir",
909 - "muguet",
910 - "mulot",
911 - "multiple",
912 - "munir",
913 - "muret",
914 - "muse",
915 - "musique",
916 - "muter",
917 - "nacre",
918 - "nager",
919 - "nain",
920 - "naissance",
921 - "narine",
922 - "narrer",
923 - "naseau",
924 - "nasse",
925 - "nation",
926 - "nature",
927 - "naval",
928 - "navet",
929 - "naviguer",
930 - "navrer",
931 - "neige",
932 - "nerf",
933 - "nerveux",
934 - "neuf",
935 - "neutre",
936 - "neuve",
937 - "neveu",
938 - "niche",
939 - "nier",
940 - "niveau",
941 - "noble",
942 - "noce",
943 - "nocif",
944 - "noir",
945 - "nomade",
946 - "nombre",
947 - "nommer",
948 - "nord",
949 - "norme",
950 - "notaire",
951 - "notice",
952 - "notre",
953 - "nouer",
954 - "nougat",
955 - "nourrir",
956 - "nous",
957 - "nouveau",
958 - "novice",
959 - "noyade",
960 - "noyer",
961 - "nuage",
962 - "nuance",
963 - "nuire",
964 - "nuit",
965 - "nulle",
966 - "nuque",
967 - "oasis",
968 - "objet",
969 - "obliger",
970 - "obscur",
971 - "observer",
972 - "obtenir",
973 - "obus",
974 - "occasion",
975 - "occuper",
976 - "ocre",
977 - "octet",
978 - "odeur",
979 - "odorat",
980 - "offense",
981 - "officier",
982 - "offrir",
983 - "ogive",
984 - "oiseau",
985 - "olive",
986 - "ombre",
987 - "onctueux",
988 - "onduler",
989 - "ongle",
990 - "onze",
991 - "opter",
992 - "option",
993 - "orageux",
994 - "oral",
995 - "orange",
996 - "orbite",
997 - "ordinaire",
998 - "ordre",
999 - "oreille",
1000 - "organe",
1001 - "orgie",
1002 - "orgueil",
1003 - "orient",
1004 - "origan",
1005 - "orner",
1006 - "orteil",
1007 - "ortie",
1008 - "oser",
1009 - "osselet",
1010 - "otage",
1011 - "otarie",
1012 - "ouate",
1013 - "oublier",
1014 - "ouest",
1015 - "ours",
1016 - "outil",
1017 - "outre",
1018 - "ouvert",
1019 - "ouvrir",
1020 - "ovale",
1021 - "ozone",
1022 - "pacte",
1023 - "page",
1024 - "paille",
1025 - "pain",
1026 - "paire",
1027 - "paix",
1028 - "palace",
1029 - "palissade",
1030 - "palmier",
1031 - "palpiter",
1032 - "panda",
1033 - "panneau",
1034 - "papa",
1035 - "papier",
1036 - "paquet",
1037 - "parc",
1038 - "pardi",
1039 - "parfois",
1040 - "parler",
1041 - "parmi",
1042 - "parole",
1043 - "partir",
1044 - "parvenir",
1045 - "passer",
1046 - "pastel",
1047 - "patin",
1048 - "patron",
1049 - "paume",
1050 - "pause",
1051 - "pauvre",
1052 - "paver",
1053 - "pavot",
1054 - "payer",
1055 - "pays",
1056 - "peau",
1057 - "peigne",
1058 - "peinture",
1059 - "pelage",
1060 - "pelote",
1061 - "pencher",
1062 - "pendre",
1063 - "penser",
1064 - "pente",
1065 - "percer",
1066 - "perdu",
1067 - "perle",
1068 - "permettre",
1069 - "personne",
1070 - "perte",
1071 - "peser",
1072 - "pesticide",
1073 - "petit",
1074 - "peuple",
1075 - "peur",
1076 - "phase",
1077 - "photo",
1078 - "phrase",
1079 - "piano",
1080 - "pied",
1081 - "pierre",
1082 - "pieu",
1083 - "pile",
1084 - "pilier",
1085 - "pilote",
1086 - "pilule",
1087 - "piment",
1088 - "pincer",
1089 - "pinson",
1090 - "pinte",
1091 - "pion",
1092 - "piquer",
1093 - "pirate",
1094 - "pire",
1095 - "piste",
1096 - "piton",
1097 - "pitre",
1098 - "pivot",
1099 - "pizza",
1100 - "placer",
1101 - "plage",
1102 - "plaire",
1103 - "plan",
1104 - "plaque",
1105 - "plat",
1106 - "plein",
1107 - "pleurer",
1108 - "pliage",
1109 - "plier",
1110 - "plonger",
1111 - "plot",
1112 - "pluie",
1113 - "plume",
1114 - "plus",
1115 - "pneu",
1116 - "poche",
1117 - "podium",
1118 - "poids",
1119 - "poil",
1120 - "point",
1121 - "poire",
1122 - "poison",
1123 - "poitrine",
1124 - "poivre",
1125 - "police",
1126 - "pollen",
1127 - "pomme",
1128 - "pompier",
1129 - "poncer",
1130 - "pondre",
1131 - "pont",
1132 - "portion",
1133 - "poser",
1134 - "position",
1135 - "possible",
1136 - "poste",
1137 - "potage",
1138 - "potin",
1139 - "pouce",
1140 - "poudre",
1141 - "poulet",
1142 - "poumon",
1143 - "poupe",
1144 - "pour",
1145 - "pousser",
1146 - "poutre",
1147 - "pouvoir",
1148 - "prairie",
1149 - "premier",
1150 - "prendre",
1151 - "presque",
1152 - "preuve",
1153 - "prier",
1154 - "primeur",
1155 - "prince",
1156 - "prison",
1157 - "priver",
1158 - "prix",
1159 - "prochain",
1160 - "produire",
1161 - "profond",
1162 - "proie",
1163 - "projet",
1164 - "promener",
1165 - "prononcer",
1166 - "propre",
1167 - "prose",
1168 - "prouver",
1169 - "prune",
1170 - "public",
1171 - "puce",
1172 - "pudeur",
1173 - "puiser",
1174 - "pull",
1175 - "pulpe",
1176 - "puma",
1177 - "punir",
1178 - "purge",
1179 - "putois",
1180 - "quand",
1181 - "quartier",
1182 - "quasi",
1183 - "quatre",
1184 - "quel",
1185 - "question",
1186 - "queue",
1187 - "quiche",
1188 - "quille",
1189 - "quinze",
1190 - "quitter",
1191 - "quoi",
1192 - "rabais",
1193 - "raboter",
1194 - "race",
1195 - "racheter",
1196 - "racine",
1197 - "racler",
1198 - "raconter",
1199 - "radar",
1200 - "radio",
1201 - "rafale",
1202 - "rage",
1203 - "ragot",
1204 - "raideur",
1205 - "raie",
1206 - "rail",
1207 - "raison",
1208 - "ramasser",
1209 - "ramener",
1210 - "rampe",
1211 - "rance",
1212 - "rang",
1213 - "rapace",
1214 - "rapide",
1215 - "rapport",
1216 - "rarement",
1217 - "rasage",
1218 - "raser",
1219 - "rasoir",
1220 - "rassurer",
1221 - "rater",
1222 - "ratio",
1223 - "rature",
1224 - "ravage",
1225 - "ravir",
1226 - "rayer",
1227 - "rayon",
1228 - "rebond",
1229 - "recevoir",
1230 - "recherche",
1231 - "record",
1232 - "reculer",
1233 - "redevenir",
1234 - "refuser",
1235 - "regard",
1236 - "regretter",
1237 - "rein",
1238 - "rejeter",
1239 - "rejoindre",
1240 - "relation",
1241 - "relever",
1242 - "religion",
1243 - "remarquer",
1244 - "remettre",
1245 - "remise",
1246 - "remonter",
1247 - "remplir",
1248 - "remuer",
1249 - "rencontre",
1250 - "rendre",
1251 - "renier",
1252 - "renoncer",
1253 - "rentrer",
1254 - "renverser",
1255 - "repas",
1256 - "repli",
1257 - "reposer",
1258 - "reproche",
1259 - "requin",
1260 - "respect",
1261 - "ressembler",
1262 - "reste",
1263 - "retard",
1264 - "retenir",
1265 - "retirer",
1266 - "retour",
1267 - "retrouver",
1268 - "revenir",
1269 - "revoir",
1270 - "revue",
1271 - "rhume",
1272 - "ricaner",
1273 - "riche",
1274 - "rideau",
1275 - "ridicule",
1276 - "rien",
1277 - "rigide",
1278 - "rincer",
1279 - "rire",
1280 - "risquer",
1281 - "rituel",
1282 - "rivage",
1283 - "rive",
1284 - "robe",
1285 - "robot",
1286 - "robuste",
1287 - "rocade",
1288 - "roche",
1289 - "rodeur",
1290 - "rogner",
1291 - "roman",
1292 - "rompre",
1293 - "ronce",
1294 - "rondeur",
1295 - "ronger",
1296 - "roque",
1297 - "rose",
1298 - "rosir",
1299 - "rotation",
1300 - "rotule",
1301 - "roue",
1302 - "rouge",
1303 - "rouler",
1304 - "route",
1305 - "ruban",
1306 - "rubis",
1307 - "ruche",
1308 - "rude",
1309 - "ruelle",
1310 - "ruer",
1311 - "rugby",
1312 - "rugir",
1313 - "ruine",
1314 - "rumeur",
1315 - "rural",
1316 - "ruse",
1317 - "rustre",
1318 - "sable",
1319 - "sabot",
1320 - "sabre",
1321 - "sacre",
1322 - "sage",
1323 - "saint",
1324 - "saisir",
1325 - "salade",
1326 - "salive",
1327 - "salle",
1328 - "salon",
1329 - "salto",
1330 - "salut",
1331 - "salve",
1332 - "samba",
1333 - "sandale",
1334 - "sanguin",
1335 - "sapin",
1336 - "sarcasme",
1337 - "satisfaire",
1338 - "sauce",
1339 - "sauf",
1340 - "sauge",
1341 - "saule",
1342 - "sauna",
1343 - "sauter",
1344 - "sauver",
1345 - "savoir",
1346 - "science",
1347 - "scoop",
1348 - "score",
1349 - "second",
1350 - "secret",
1351 - "secte",
1352 - "seigneur",
1353 - "sein",
1354 - "seize",
1355 - "selle",
1356 - "selon",
1357 - "semaine",
1358 - "sembler",
1359 - "semer",
1360 - "semis",
1361 - "sensuel",
1362 - "sentir",
1363 - "sept",
1364 - "serpe",
1365 - "serrer",
1366 - "sertir",
1367 - "service",
1368 - "seuil",
1369 - "seulement",
1370 - "short",
1371 - "sien",
1372 - "sigle",
1373 - "signal",
1374 - "silence",
1375 - "silo",
1376 - "simple",
1377 - "singe",
1378 - "sinon",
1379 - "sinus",
1380 - "sioux",
1381 - "sirop",
1382 - "site",
1383 - "situation",
1384 - "skier",
1385 - "snob",
1386 - "sobre",
1387 - "social",
1388 - "socle",
1389 - "sodium",
1390 - "soigner",
1391 - "soir",
1392 - "soixante",
1393 - "soja",
1394 - "solaire",
1395 - "soldat",
1396 - "soleil",
1397 - "solide",
1398 - "solo",
1399 - "solvant",
1400 - "sombre",
1401 - "somme",
1402 - "somnoler",
1403 - "sondage",
1404 - "songeur",
1405 - "sonner",
1406 - "sorte",
1407 - "sosie",
1408 - "sottise",
1409 - "souci",
1410 - "soudain",
1411 - "souffrir",
1412 - "souhaiter",
1413 - "soulever",
1414 - "soumettre",
1415 - "soupe",
1416 - "sourd",
1417 - "soustraire",
1418 - "soutenir",
1419 - "souvent",
1420 - "soyeux",
1421 - "spectacle",
1422 - "sport",
1423 - "stade",
1424 - "stagiaire",
1425 - "stand",
1426 - "star",
1427 - "statue",
1428 - "stock",
1429 - "stop",
1430 - "store",
1431 - "style",
1432 - "suave",
1433 - "subir",
1434 - "sucre",
1435 - "suer",
1436 - "suffire",
1437 - "suie",
1438 - "suite",
1439 - "suivre",
1440 - "sujet",
1441 - "sulfite",
1442 - "supposer",
1443 - "surf",
1444 - "surprendre",
1445 - "surtout",
1446 - "surveiller",
1447 - "tabac",
1448 - "table",
1449 - "tabou",
1450 - "tache",
1451 - "tacler",
1452 - "tacot",
1453 - "tact",
1454 - "taie",
1455 - "taille",
1456 - "taire",
1457 - "talon",
1458 - "talus",
1459 - "tandis",
1460 - "tango",
1461 - "tanin",
1462 - "tant",
1463 - "taper",
1464 - "tapis",
1465 - "tard",
1466 - "tarif",
1467 - "tarot",
1468 - "tarte",
1469 - "tasse",
1470 - "taureau",
1471 - "taux",
1472 - "taverne",
1473 - "taxer",
1474 - "taxi",
1475 - "tellement",
1476 - "temple",
1477 - "tendre",
1478 - "tenir",
1479 - "tenter",
1480 - "tenu",
1481 - "terme",
1482 - "ternir",
1483 - "terre",
1484 - "test",
1485 - "texte",
1486 - "thym",
1487 - "tibia",
1488 - "tiers",
1489 - "tige",
1490 - "tipi",
1491 - "tique",
1492 - "tirer",
1493 - "tissu",
1494 - "titre",
1495 - "toast",
1496 - "toge",
1497 - "toile",
1498 - "toiser",
1499 - "toiture",
1500 - "tomber",
1501 - "tome",
1502 - "tonne",
1503 - "tonte",
1504 - "toque",
1505 - "torse",
1506 - "tortue",
1507 - "totem",
1508 - "toucher",
1509 - "toujours",
1510 - "tour",
1511 - "tousser",
1512 - "tout",
1513 - "toux",
1514 - "trace",
1515 - "train",
1516 - "trame",
1517 - "tranquille",
1518 - "travail",
1519 - "trembler",
1520 - "trente",
1521 - "tribu",
1522 - "trier",
1523 - "trio",
1524 - "tripe",
1525 - "triste",
1526 - "troc",
1527 - "trois",
1528 - "tromper",
1529 - "tronc",
1530 - "trop",
1531 - "trotter",
1532 - "trouer",
1533 - "truc",
1534 - "truite",
1535 - "tuba",
1536 - "tuer",
1537 - "tuile",
1538 - "turbo",
1539 - "tutu",
1540 - "tuyau",
1541 - "type",
1542 - "union",
1543 - "unique",
1544 - "unir",
1545 - "unisson",
1546 - "untel",
1547 - "urne",
1548 - "usage",
1549 - "user",
1550 - "usiner",
1551 - "usure",
1552 - "utile",
1553 - "vache",
1554 - "vague",
1555 - "vaincre",
1556 - "valeur",
1557 - "valoir",
1558 - "valser",
1559 - "valve",
1560 - "vampire",
1561 - "vaseux",
1562 - "vaste",
1563 - "veau",
1564 - "veille",
1565 - "veine",
1566 - "velours",
1567 - "velu",
1568 - "vendre",
1569 - "venir",
1570 - "vent",
1571 - "venue",
1572 - "verbe",
1573 - "verdict",
1574 - "version",
1575 - "vertige",
1576 - "verve",
1577 - "veste",
1578 - "veto",
1579 - "vexer",
1580 - "vice",
1581 - "victime",
1582 - "vide",
1583 - "vieil",
1584 - "vieux",
1585 - "vigie",
1586 - "vigne",
1587 - "ville",
1588 - "vingt",
1589 - "violent",
1590 - "virer",
1591 - "virus",
1592 - "visage",
1593 - "viser",
1594 - "visite",
1595 - "visuel",
1596 - "vitamine",
1597 - "vitrine",
1598 - "vivant",
1599 - "vivre",
1600 - "vocal",
1601 - "vodka",
1602 - "vogue",
1603 - "voici",
1604 - "voile",
1605 - "voir",
1606 - "voisin",
1607 - "voiture",
1608 - "volaille",
1609 - "volcan",
1610 - "voler",
1611 - "volt",
1612 - "votant",
1613 - "votre",
1614 - "vouer",
1615 - "vouloir",
1616 - "vous",
1617 - "voyage",
1618 - "voyou",
1619 - "vrac",
1620 - "vrai",
1621 - "yacht",
1622 - "yeti",
1623 - "yeux",
1624 - "yoga",
1625 - "zeste",
1626 - "zinc",
1627 - "zone",
1628 - "zoom"
1629 - ];
1630 -}
\ No newline at end of file
2 + static const words = [
3 + "abandon",
4 + "abattre",
5 + "aboi",
6 + "abolir",
7 + "aborder",
8 + "abri",
9 + "absence",
10 + "absolu",
11 + "abuser",
12 + "acacia",
13 + "acajou",
14 + "accent",
15 + "accord",
16 + "accrocher",
17 + "accuser",
18 + "acerbe",
19 + "achat",
20 + "acheter",
21 + "acide",
22 + "acier",
23 + "acquis",
24 + "acte",
25 + "action",
26 + "adage",
27 + "adepte",
28 + "adieu",
29 + "admettre",
30 + "admis",
31 + "adorer",
32 + "adresser",
33 + "aduler",
34 + "affaire",
35 + "affirmer",
36 + "afin",
37 + "agacer",
38 + "agent",
39 + "agir",
40 + "agiter",
41 + "agonie",
42 + "agrafe",
43 + "agrume",
44 + "aider",
45 + "aigle",
46 + "aigre",
47 + "aile",
48 + "ailleurs",
49 + "aimant",
50 + "aimer",
51 + "ainsi",
52 + "aise",
53 + "ajouter",
54 + "alarme",
55 + "album",
56 + "alcool",
57 + "alerte",
58 + "algue",
59 + "alibi",
60 + "aller",
61 + "allumer",
62 + "alors",
63 + "amande",
64 + "amener",
65 + "amie",
66 + "amorcer",
67 + "amour",
68 + "ample",
69 + "amuser",
70 + "ananas",
71 + "ancien",
72 + "anglais",
73 + "angoisse",
74 + "animal",
75 + "anneau",
76 + "annoncer",
77 + "apercevoir",
78 + "apparence",
79 + "appel",
80 + "apporter",
81 + "apprendre",
82 + "appuyer",
83 + "arbre",
84 + "arcade",
85 + "arceau",
86 + "arche",
87 + "ardeur",
88 + "argent",
89 + "argile",
90 + "aride",
91 + "arme",
92 + "armure",
93 + "arracher",
94 + "arriver",
95 + "article",
96 + "asile",
97 + "aspect",
98 + "assaut",
99 + "assez",
100 + "assister",
101 + "assurer",
102 + "astre",
103 + "astuce",
104 + "atlas",
105 + "atroce",
106 + "attacher",
107 + "attente",
108 + "attirer",
109 + "aube",
110 + "aucun",
111 + "audace",
112 + "auparavant",
113 + "auquel",
114 + "aurore",
115 + "aussi",
116 + "autant",
117 + "auteur",
118 + "autoroute",
119 + "autre",
120 + "aval",
121 + "avant",
122 + "avec",
123 + "avenir",
124 + "averse",
125 + "aveu",
126 + "avide",
127 + "avion",
128 + "avis",
129 + "avoir",
130 + "avouer",
131 + "avril",
132 + "azote",
133 + "azur",
134 + "badge",
135 + "bagage",
136 + "bague",
137 + "bain",
138 + "baisser",
139 + "balai",
140 + "balcon",
141 + "balise",
142 + "balle",
143 + "bambou",
144 + "banane",
145 + "banc",
146 + "bandage",
147 + "banjo",
148 + "banlieue",
149 + "bannir",
150 + "banque",
151 + "baobab",
152 + "barbe",
153 + "barque",
154 + "barrer",
155 + "bassine",
156 + "bataille",
157 + "bateau",
158 + "battre",
159 + "baver",
160 + "bavoir",
161 + "bazar",
162 + "beau",
163 + "beige",
164 + "berger",
165 + "besoin",
166 + "beurre",
167 + "biais",
168 + "biceps",
169 + "bidule",
170 + "bien",
171 + "bijou",
172 + "bilan",
173 + "billet",
174 + "blanc",
175 + "blason",
176 + "bleu",
177 + "bloc",
178 + "blond",
179 + "bocal",
180 + "boire",
181 + "boiserie",
182 + "boiter",
183 + "bonbon",
184 + "bondir",
185 + "bonheur",
186 + "bordure",
187 + "borgne",
188 + "borner",
189 + "bosse",
190 + "bouche",
191 + "bouder",
192 + "bouger",
193 + "boule",
194 + "bourse",
195 + "bout",
196 + "boxe",
197 + "brader",
198 + "braise",
199 + "branche",
200 + "braquer",
201 + "bras",
202 + "brave",
203 + "brebis",
204 + "brevet",
205 + "brider",
206 + "briller",
207 + "brin",
208 + "brique",
209 + "briser",
210 + "broche",
211 + "broder",
212 + "bronze",
213 + "brosser",
214 + "brouter",
215 + "bruit",
216 + "brute",
217 + "budget",
218 + "buffet",
219 + "bulle",
220 + "bureau",
221 + "buriner",
222 + "buste",
223 + "buter",
224 + "butiner",
225 + "cabas",
226 + "cabinet",
227 + "cabri",
228 + "cacao",
229 + "cacher",
230 + "cadeau",
231 + "cadre",
232 + "cage",
233 + "caisse",
234 + "caler",
235 + "calme",
236 + "camarade",
237 + "camion",
238 + "campagne",
239 + "canal",
240 + "canif",
241 + "capable",
242 + "capot",
243 + "carat",
244 + "caresser",
245 + "carie",
246 + "carpe",
247 + "cartel",
248 + "casier",
249 + "casque",
250 + "casserole",
251 + "cause",
252 + "cavale",
253 + "cave",
254 + "ceci",
255 + "cela",
256 + "celui",
257 + "cendre",
258 + "cent",
259 + "cependant",
260 + "cercle",
261 + "cerise",
262 + "cerner",
263 + "certes",
264 + "cerveau",
265 + "cesser",
266 + "chacun",
267 + "chair",
268 + "chaleur",
269 + "chamois",
270 + "chanson",
271 + "chaque",
272 + "charge",
273 + "chasse",
274 + "chat",
275 + "chaud",
276 + "chef",
277 + "chemin",
278 + "cheveu",
279 + "chez",
280 + "chicane",
281 + "chien",
282 + "chiffre",
283 + "chiner",
284 + "chiot",
285 + "chlore",
286 + "choc",
287 + "choix",
288 + "chose",
289 + "chou",
290 + "chute",
291 + "cibler",
292 + "cidre",
293 + "ciel",
294 + "cigale",
295 + "cinq",
296 + "cintre",
297 + "cirage",
298 + "cirque",
299 + "ciseau",
300 + "citation",
301 + "citer",
302 + "citron",
303 + "civet",
304 + "clairon",
305 + "clan",
306 + "classe",
307 + "clavier",
308 + "clef",
309 + "climat",
310 + "cloche",
311 + "cloner",
312 + "clore",
313 + "clos",
314 + "clou",
315 + "club",
316 + "cobra",
317 + "cocon",
318 + "coiffer",
319 + "coin",
320 + "colline",
321 + "colon",
322 + "combat",
323 + "comme",
324 + "compte",
325 + "conclure",
326 + "conduire",
327 + "confier",
328 + "connu",
329 + "conseil",
330 + "contre",
331 + "convenir",
332 + "copier",
333 + "cordial",
334 + "cornet",
335 + "corps",
336 + "cosmos",
337 + "coton",
338 + "couche",
339 + "coude",
340 + "couler",
341 + "coupure",
342 + "cour",
343 + "couteau",
344 + "couvrir",
345 + "crabe",
346 + "crainte",
347 + "crampe",
348 + "cran",
349 + "creuser",
350 + "crever",
351 + "crier",
352 + "crime",
353 + "crin",
354 + "crise",
355 + "crochet",
356 + "croix",
357 + "cruel",
358 + "cuisine",
359 + "cuite",
360 + "culot",
361 + "culte",
362 + "cumul",
363 + "cure",
364 + "curieux",
365 + "cuve",
366 + "dame",
367 + "danger",
368 + "dans",
369 + "davantage",
370 + "debout",
371 + "dedans",
372 + "dehors",
373 + "delta",
374 + "demain",
375 + "demeurer",
376 + "demi",
377 + "dense",
378 + "dent",
379 + "depuis",
380 + "dernier",
381 + "descendre",
382 + "dessus",
383 + "destin",
384 + "dette",
385 + "deuil",
386 + "deux",
387 + "devant",
388 + "devenir",
389 + "devin",
390 + "devoir",
391 + "dicton",
392 + "dieu",
393 + "difficile",
394 + "digestion",
395 + "digue",
396 + "diluer",
397 + "dimanche",
398 + "dinde",
399 + "diode",
400 + "dire",
401 + "diriger",
402 + "discours",
403 + "disposer",
404 + "distance",
405 + "divan",
406 + "divers",
407 + "docile",
408 + "docteur",
409 + "dodu",
410 + "dogme",
411 + "doigt",
412 + "dominer",
413 + "donation",
414 + "donjon",
415 + "donner",
416 + "dopage",
417 + "dorer",
418 + "dormir",
419 + "doseur",
420 + "douane",
421 + "double",
422 + "douche",
423 + "douleur",
424 + "doute",
425 + "doux",
426 + "douzaine",
427 + "draguer",
428 + "drame",
429 + "drap",
430 + "dresser",
431 + "droit",
432 + "duel",
433 + "dune",
434 + "duper",
435 + "durant",
436 + "durcir",
437 + "durer",
438 + "eaux",
439 + "effacer",
440 + "effet",
441 + "effort",
442 + "effrayant",
443 + "elle",
444 + "embrasser",
445 + "emmener",
446 + "emparer",
447 + "empire",
448 + "employer",
449 + "emporter",
450 + "enclos",
451 + "encore",
452 + "endive",
453 + "endormir",
454 + "endroit",
455 + "enduit",
456 + "enfant",
457 + "enfermer",
458 + "enfin",
459 + "enfler",
460 + "enfoncer",
461 + "enfuir",
462 + "engager",
463 + "engin",
464 + "enjeu",
465 + "enlever",
466 + "ennemi",
467 + "ennui",
468 + "ensemble",
469 + "ensuite",
470 + "entamer",
471 + "entendre",
472 + "entier",
473 + "entourer",
474 + "entre",
475 + "envelopper",
476 + "envie",
477 + "envoyer",
478 + "erreur",
479 + "escalier",
480 + "espace",
481 + "espoir",
482 + "esprit",
483 + "essai",
484 + "essor",
485 + "essuyer",
486 + "estimer",
487 + "exact",
488 + "examiner",
489 + "excuse",
490 + "exemple",
491 + "exiger",
492 + "exil",
493 + "exister",
494 + "exode",
495 + "expliquer",
496 + "exposer",
497 + "exprimer",
498 + "extase",
499 + "fable",
500 + "facette",
501 + "facile",
502 + "fade",
503 + "faible",
504 + "faim",
505 + "faire",
506 + "fait",
507 + "falloir",
508 + "famille",
509 + "faner",
510 + "farce",
511 + "farine",
512 + "fatigue",
513 + "faucon",
514 + "faune",
515 + "faute",
516 + "faux",
517 + "faveur",
518 + "favori",
519 + "faxer",
520 + "feinter",
521 + "femme",
522 + "fendre",
523 + "fente",
524 + "ferme",
525 + "festin",
526 + "feuille",
527 + "feutre",
528 + "fiable",
529 + "fibre",
530 + "ficher",
531 + "fier",
532 + "figer",
533 + "figure",
534 + "filet",
535 + "fille",
536 + "filmer",
537 + "fils",
538 + "filtre",
539 + "final",
540 + "finesse",
541 + "finir",
542 + "fiole",
543 + "firme",
544 + "fixe",
545 + "flacon",
546 + "flair",
547 + "flamme",
548 + "flan",
549 + "flaque",
550 + "fleur",
551 + "flocon",
552 + "flore",
553 + "flot",
554 + "flou",
555 + "fluide",
556 + "fluor",
557 + "flux",
558 + "focus",
559 + "foin",
560 + "foire",
561 + "foison",
562 + "folie",
563 + "fonction",
564 + "fondre",
565 + "fonte",
566 + "force",
567 + "forer",
568 + "forger",
569 + "forme",
570 + "fort",
571 + "fosse",
572 + "fouet",
573 + "fouine",
574 + "foule",
575 + "four",
576 + "foyer",
577 + "frais",
578 + "franc",
579 + "frapper",
580 + "freiner",
581 + "frimer",
582 + "friser",
583 + "frite",
584 + "froid",
585 + "froncer",
586 + "fruit",
587 + "fugue",
588 + "fuir",
589 + "fuite",
590 + "fumer",
591 + "fureur",
592 + "furieux",
593 + "fuser",
594 + "fusil",
595 + "futile",
596 + "futur",
597 + "gagner",
598 + "gain",
599 + "gala",
600 + "galet",
601 + "galop",
602 + "gamme",
603 + "gant",
604 + "garage",
605 + "garde",
606 + "garer",
607 + "gauche",
608 + "gaufre",
609 + "gaule",
610 + "gaver",
611 + "gazon",
612 + "geler",
613 + "genou",
614 + "genre",
615 + "gens",
616 + "gercer",
617 + "germer",
618 + "geste",
619 + "gibier",
620 + "gicler",
621 + "gilet",
622 + "girafe",
623 + "givre",
624 + "glace",
625 + "glisser",
626 + "globe",
627 + "gloire",
628 + "gluant",
629 + "gober",
630 + "golf",
631 + "gommer",
632 + "gorge",
633 + "gosier",
634 + "goutte",
635 + "grain",
636 + "gramme",
637 + "grand",
638 + "gras",
639 + "grave",
640 + "gredin",
641 + "griffure",
642 + "griller",
643 + "gris",
644 + "gronder",
645 + "gros",
646 + "grotte",
647 + "groupe",
648 + "grue",
649 + "guerrier",
650 + "guetter",
651 + "guider",
652 + "guise",
653 + "habiter",
654 + "hache",
655 + "haie",
656 + "haine",
657 + "halte",
658 + "hamac",
659 + "hanche",
660 + "hangar",
661 + "hanter",
662 + "haras",
663 + "hareng",
664 + "harpe",
665 + "hasard",
666 + "hausse",
667 + "haut",
668 + "havre",
669 + "herbe",
670 + "heure",
671 + "hibou",
672 + "hier",
673 + "histoire",
674 + "hiver",
675 + "hochet",
676 + "homme",
677 + "honneur",
678 + "honte",
679 + "horde",
680 + "horizon",
681 + "hormone",
682 + "houle",
683 + "housse",
684 + "hublot",
685 + "huile",
686 + "huit",
687 + "humain",
688 + "humble",
689 + "humide",
690 + "humour",
691 + "hurler",
692 + "idole",
693 + "igloo",
694 + "ignorer",
695 + "illusion",
696 + "image",
697 + "immense",
698 + "immobile",
699 + "imposer",
700 + "impression",
701 + "incapable",
702 + "inconnu",
703 + "index",
704 + "indiquer",
705 + "infime",
706 + "injure",
707 + "inox",
708 + "inspirer",
709 + "instant",
710 + "intention",
711 + "intime",
712 + "inutile",
713 + "inventer",
714 + "inviter",
715 + "iode",
716 + "iris",
717 + "issue",
718 + "ivre",
719 + "jade",
720 + "jadis",
721 + "jamais",
722 + "jambe",
723 + "janvier",
724 + "jardin",
725 + "jauge",
726 + "jaunisse",
727 + "jeter",
728 + "jeton",
729 + "jeudi",
730 + "jeune",
731 + "joie",
732 + "joindre",
733 + "joli",
734 + "joueur",
735 + "journal",
736 + "judo",
737 + "juge",
738 + "juillet",
739 + "juin",
740 + "jument",
741 + "jungle",
742 + "jupe",
743 + "jupon",
744 + "jurer",
745 + "juron",
746 + "jury",
747 + "jusque",
748 + "juste",
749 + "kayak",
750 + "ketchup",
751 + "kilo",
752 + "kiwi",
753 + "koala",
754 + "label",
755 + "lacet",
756 + "lacune",
757 + "laine",
758 + "laisse",
759 + "lait",
760 + "lame",
761 + "lancer",
762 + "lande",
763 + "laque",
764 + "lard",
765 + "largeur",
766 + "larme",
767 + "larve",
768 + "lasso",
769 + "laver",
770 + "lendemain",
771 + "lentement",
772 + "lequel",
773 + "lettre",
774 + "leur",
775 + "lever",
776 + "levure",
777 + "liane",
778 + "libre",
779 + "lien",
780 + "lier",
781 + "lieutenant",
782 + "ligne",
783 + "ligoter",
784 + "liguer",
785 + "limace",
786 + "limer",
787 + "limite",
788 + "lingot",
789 + "lion",
790 + "lire",
791 + "lisser",
792 + "litre",
793 + "livre",
794 + "lobe",
795 + "local",
796 + "logis",
797 + "loin",
798 + "loisir",
799 + "long",
800 + "loque",
801 + "lors",
802 + "lotus",
803 + "louer",
804 + "loup",
805 + "lourd",
806 + "louve",
807 + "loyer",
808 + "lubie",
809 + "lucide",
810 + "lueur",
811 + "luge",
812 + "luire",
813 + "lundi",
814 + "lune",
815 + "lustre",
816 + "lutin",
817 + "lutte",
818 + "luxe",
819 + "machine",
820 + "madame",
821 + "magie",
822 + "magnifique",
823 + "magot",
824 + "maigre",
825 + "main",
826 + "mairie",
827 + "maison",
828 + "malade",
829 + "malheur",
830 + "malin",
831 + "manche",
832 + "manger",
833 + "manier",
834 + "manoir",
835 + "manquer",
836 + "marche",
837 + "mardi",
838 + "marge",
839 + "mariage",
840 + "marquer",
841 + "mars",
842 + "masque",
843 + "masse",
844 + "matin",
845 + "mauvais",
846 + "meilleur",
847 + "melon",
848 + "membre",
849 + "menacer",
850 + "mener",
851 + "mensonge",
852 + "mentir",
853 + "menu",
854 + "merci",
855 + "merlu",
856 + "mesure",
857 + "mettre",
858 + "meuble",
859 + "meunier",
860 + "meute",
861 + "miche",
862 + "micro",
863 + "midi",
864 + "miel",
865 + "miette",
866 + "mieux",
867 + "milieu",
868 + "mille",
869 + "mimer",
870 + "mince",
871 + "mineur",
872 + "ministre",
873 + "minute",
874 + "mirage",
875 + "miroir",
876 + "miser",
877 + "mite",
878 + "mixte",
879 + "mobile",
880 + "mode",
881 + "module",
882 + "moins",
883 + "mois",
884 + "moment",
885 + "momie",
886 + "monde",
887 + "monsieur",
888 + "monter",
889 + "moquer",
890 + "moral",
891 + "morceau",
892 + "mordre",
893 + "morose",
894 + "morse",
895 + "mortier",
896 + "morue",
897 + "motif",
898 + "motte",
899 + "moudre",
900 + "moule",
901 + "mourir",
902 + "mousse",
903 + "mouton",
904 + "mouvement",
905 + "moyen",
906 + "muer",
907 + "muette",
908 + "mugir",
909 + "muguet",
910 + "mulot",
911 + "multiple",
912 + "munir",
913 + "muret",
914 + "muse",
915 + "musique",
916 + "muter",
917 + "nacre",
918 + "nager",
919 + "nain",
920 + "naissance",
921 + "narine",
922 + "narrer",
923 + "naseau",
924 + "nasse",
925 + "nation",
926 + "nature",
927 + "naval",
928 + "navet",
929 + "naviguer",
930 + "navrer",
931 + "neige",
932 + "nerf",
933 + "nerveux",
934 + "neuf",
935 + "neutre",
936 + "neuve",
937 + "neveu",
938 + "niche",
939 + "nier",
940 + "niveau",
941 + "noble",
942 + "noce",
943 + "nocif",
944 + "noir",
945 + "nomade",
946 + "nombre",
947 + "nommer",
948 + "nord",
949 + "norme",
950 + "notaire",
951 + "notice",
952 + "notre",
953 + "nouer",
954 + "nougat",
955 + "nourrir",
956 + "nous",
957 + "nouveau",
958 + "novice",
959 + "noyade",
960 + "noyer",
961 + "nuage",
962 + "nuance",
963 + "nuire",
964 + "nuit",
965 + "nulle",
966 + "nuque",
967 + "oasis",
968 + "objet",
969 + "obliger",
970 + "obscur",
971 + "observer",
972 + "obtenir",
973 + "obus",
974 + "occasion",
975 + "occuper",
976 + "ocre",
977 + "octet",
978 + "odeur",
979 + "odorat",
980 + "offense",
981 + "officier",
982 + "offrir",
983 + "ogive",
984 + "oiseau",
985 + "olive",
986 + "ombre",
987 + "onctueux",
988 + "onduler",
989 + "ongle",
990 + "onze",
991 + "opter",
992 + "option",
993 + "orageux",
994 + "oral",
995 + "orange",
996 + "orbite",
997 + "ordinaire",
998 + "ordre",
999 + "oreille",
1000 + "organe",
1001 + "orgie",
1002 + "orgueil",
1003 + "orient",
1004 + "origan",
1005 + "orner",
1006 + "orteil",
1007 + "ortie",
1008 + "oser",
1009 + "osselet",
1010 + "otage",
1011 + "otarie",
1012 + "ouate",
1013 + "oublier",
1014 + "ouest",
1015 + "ours",
1016 + "outil",
1017 + "outre",
1018 + "ouvert",
1019 + "ouvrir",
1020 + "ovale",
1021 + "ozone",
1022 + "pacte",
1023 + "page",
1024 + "paille",
1025 + "pain",
1026 + "paire",
1027 + "paix",
1028 + "palace",
1029 + "palissade",
1030 + "palmier",
1031 + "palpiter",
1032 + "panda",
1033 + "panneau",
1034 + "papa",
1035 + "papier",
1036 + "paquet",
1037 + "parc",
1038 + "pardi",
1039 + "parfois",
1040 + "parler",
1041 + "parmi",
1042 + "parole",
1043 + "partir",
1044 + "parvenir",
1045 + "passer",
1046 + "pastel",
1047 + "patin",
1048 + "patron",
1049 + "paume",
1050 + "pause",
1051 + "pauvre",
1052 + "paver",
1053 + "pavot",
1054 + "payer",
1055 + "pays",
1056 + "peau",
1057 + "peigne",
1058 + "peinture",
1059 + "pelage",
1060 + "pelote",
1061 + "pencher",
1062 + "pendre",
1063 + "penser",
1064 + "pente",
1065 + "percer",
1066 + "perdu",
1067 + "perle",
1068 + "permettre",
1069 + "personne",
1070 + "perte",
1071 + "peser",
1072 + "pesticide",
1073 + "petit",
1074 + "peuple",
1075 + "peur",
1076 + "phase",
1077 + "photo",
1078 + "phrase",
1079 + "piano",
1080 + "pied",
1081 + "pierre",
1082 + "pieu",
1083 + "pile",
1084 + "pilier",
1085 + "pilote",
1086 + "pilule",
1087 + "piment",
1088 + "pincer",
1089 + "pinson",
1090 + "pinte",
1091 + "pion",
1092 + "piquer",
1093 + "pirate",
1094 + "pire",
1095 + "piste",
1096 + "piton",
1097 + "pitre",
1098 + "pivot",
1099 + "pizza",
1100 + "placer",
1101 + "plage",
1102 + "plaire",
1103 + "plan",
1104 + "plaque",
1105 + "plat",
1106 + "plein",
1107 + "pleurer",
1108 + "pliage",
1109 + "plier",
1110 + "plonger",
1111 + "plot",
1112 + "pluie",
1113 + "plume",
1114 + "plus",
1115 + "pneu",
1116 + "poche",
1117 + "podium",
1118 + "poids",
1119 + "poil",
1120 + "point",
1121 + "poire",
1122 + "poison",
1123 + "poitrine",
1124 + "poivre",
1125 + "police",
1126 + "pollen",
1127 + "pomme",
1128 + "pompier",
1129 + "poncer",
1130 + "pondre",
1131 + "pont",
1132 + "portion",
1133 + "poser",
1134 + "position",
1135 + "possible",
1136 + "poste",
1137 + "potage",
1138 + "potin",
1139 + "pouce",
1140 + "poudre",
1141 + "poulet",
1142 + "poumon",
1143 + "poupe",
1144 + "pour",
1145 + "pousser",
1146 + "poutre",
1147 + "pouvoir",
1148 + "prairie",
1149 + "premier",
1150 + "prendre",
1151 + "presque",
1152 + "preuve",
1153 + "prier",
1154 + "primeur",
1155 + "prince",
1156 + "prison",
1157 + "priver",
1158 + "prix",
1159 + "prochain",
1160 + "produire",
1161 + "profond",
1162 + "proie",
1163 + "projet",
1164 + "promener",
1165 + "prononcer",
1166 + "propre",
1167 + "prose",
1168 + "prouver",
1169 + "prune",
1170 + "public",
1171 + "puce",
1172 + "pudeur",
1173 + "puiser",
1174 + "pull",
1175 + "pulpe",
1176 + "puma",
1177 + "punir",
1178 + "purge",
1179 + "putois",
1180 + "quand",
1181 + "quartier",
1182 + "quasi",
1183 + "quatre",
1184 + "quel",
1185 + "question",
1186 + "queue",
1187 + "quiche",
1188 + "quille",
1189 + "quinze",
1190 + "quitter",
1191 + "quoi",
1192 + "rabais",
1193 + "raboter",
1194 + "race",
1195 + "racheter",
1196 + "racine",
1197 + "racler",
1198 + "raconter",
1199 + "radar",
1200 + "radio",
1201 + "rafale",
1202 + "rage",
1203 + "ragot",
1204 + "raideur",
1205 + "raie",
1206 + "rail",
1207 + "raison",
1208 + "ramasser",
1209 + "ramener",
1210 + "rampe",
1211 + "rance",
1212 + "rang",
1213 + "rapace",
1214 + "rapide",
1215 + "rapport",
1216 + "rarement",
1217 + "rasage",
1218 + "raser",
1219 + "rasoir",
1220 + "rassurer",
1221 + "rater",
1222 + "ratio",
1223 + "rature",
1224 + "ravage",
1225 + "ravir",
1226 + "rayer",
1227 + "rayon",
1228 + "rebond",
1229 + "recevoir",
1230 + "recherche",
1231 + "record",
1232 + "reculer",
1233 + "redevenir",
1234 + "refuser",
1235 + "regard",
1236 + "regretter",
1237 + "rein",
1238 + "rejeter",
1239 + "rejoindre",
1240 + "relation",
1241 + "relever",
1242 + "religion",
1243 + "remarquer",
1244 + "remettre",
1245 + "remise",
1246 + "remonter",
1247 + "remplir",
1248 + "remuer",
1249 + "rencontre",
1250 + "rendre",
1251 + "renier",
1252 + "renoncer",
1253 + "rentrer",
1254 + "renverser",
1255 + "repas",
1256 + "repli",
1257 + "reposer",
1258 + "reproche",
1259 + "requin",
1260 + "respect",
1261 + "ressembler",
1262 + "reste",
1263 + "retard",
1264 + "retenir",
1265 + "retirer",
1266 + "retour",
1267 + "retrouver",
1268 + "revenir",
1269 + "revoir",
1270 + "revue",
1271 + "rhume",
1272 + "ricaner",
1273 + "riche",
1274 + "rideau",
1275 + "ridicule",
1276 + "rien",
1277 + "rigide",
1278 + "rincer",
1279 + "rire",
1280 + "risquer",
1281 + "rituel",
1282 + "rivage",
1283 + "rive",
1284 + "robe",
1285 + "robot",
1286 + "robuste",
1287 + "rocade",
1288 + "roche",
1289 + "rodeur",
1290 + "rogner",
1291 + "roman",
1292 + "rompre",
1293 + "ronce",
1294 + "rondeur",
1295 + "ronger",
1296 + "roque",
1297 + "rose",
1298 + "rosir",
1299 + "rotation",
1300 + "rotule",
1301 + "roue",
1302 + "rouge",
1303 + "rouler",
1304 + "route",
1305 + "ruban",
1306 + "rubis",
1307 + "ruche",
1308 + "rude",
1309 + "ruelle",
1310 + "ruer",
1311 + "rugby",
1312 + "rugir",
1313 + "ruine",
1314 + "rumeur",
1315 + "rural",
1316 + "ruse",
1317 + "rustre",
1318 + "sable",
1319 + "sabot",
1320 + "sabre",
1321 + "sacre",
1322 + "sage",
1323 + "saint",
1324 + "saisir",
1325 + "salade",
1326 + "salive",
1327 + "salle",
1328 + "salon",
1329 + "salto",
1330 + "salut",
1331 + "salve",
1332 + "samba",
1333 + "sandale",
1334 + "sanguin",
1335 + "sapin",
1336 + "sarcasme",
1337 + "satisfaire",
1338 + "sauce",
1339 + "sauf",
1340 + "sauge",
1341 + "saule",
1342 + "sauna",
1343 + "sauter",
1344 + "sauver",
1345 + "savoir",
1346 + "science",
1347 + "scoop",
1348 + "score",
1349 + "second",
1350 + "secret",
1351 + "secte",
1352 + "seigneur",
1353 + "sein",
1354 + "seize",
1355 + "selle",
1356 + "selon",
1357 + "semaine",
1358 + "sembler",
1359 + "semer",
1360 + "semis",
1361 + "sensuel",
1362 + "sentir",
1363 + "sept",
1364 + "serpe",
1365 + "serrer",
1366 + "sertir",
1367 + "service",
1368 + "seuil",
1369 + "seulement",
1370 + "short",
1371 + "sien",
1372 + "sigle",
1373 + "signal",
1374 + "silence",
1375 + "silo",
1376 + "simple",
1377 + "singe",
1378 + "sinon",
1379 + "sinus",
1380 + "sioux",
1381 + "sirop",
1382 + "site",
1383 + "situation",
1384 + "skier",
1385 + "snob",
1386 + "sobre",
1387 + "social",
1388 + "socle",
1389 + "sodium",
1390 + "soigner",
1391 + "soir",
1392 + "soixante",
1393 + "soja",
1394 + "solaire",
1395 + "soldat",
1396 + "soleil",
1397 + "solide",
1398 + "solo",
1399 + "solvant",
1400 + "sombre",
1401 + "somme",
1402 + "somnoler",
1403 + "sondage",
1404 + "songeur",
1405 + "sonner",
1406 + "sorte",
1407 + "sosie",
1408 + "sottise",
1409 + "souci",
1410 + "soudain",
1411 + "souffrir",
1412 + "souhaiter",
1413 + "soulever",
1414 + "soumettre",
1415 + "soupe",
1416 + "sourd",
1417 + "soustraire",
1418 + "soutenir",
1419 + "souvent",
1420 + "soyeux",
1421 + "spectacle",
1422 + "sport",
1423 + "stade",
1424 + "stagiaire",
1425 + "stand",
1426 + "star",
1427 + "statue",
1428 + "stock",
1429 + "stop",
1430 + "store",
1431 + "style",
1432 + "suave",
1433 + "subir",
1434 + "sucre",
1435 + "suer",
1436 + "suffire",
1437 + "suie",
1438 + "suite",
1439 + "suivre",
1440 + "sujet",
1441 + "sulfite",
1442 + "supposer",
1443 + "surf",
1444 + "surprendre",
1445 + "surtout",
1446 + "surveiller",
1447 + "tabac",
1448 + "table",
1449 + "tabou",
1450 + "tache",
1451 + "tacler",
1452 + "tacot",
1453 + "tact",
1454 + "taie",
1455 + "taille",
1456 + "taire",
1457 + "talon",
1458 + "talus",
1459 + "tandis",
1460 + "tango",
1461 + "tanin",
1462 + "tant",
1463 + "taper",
1464 + "tapis",
1465 + "tard",
1466 + "tarif",
1467 + "tarot",
1468 + "tarte",
1469 + "tasse",
1470 + "taureau",
1471 + "taux",
1472 + "taverne",
1473 + "taxer",
1474 + "taxi",
1475 + "tellement",
1476 + "temple",
1477 + "tendre",
1478 + "tenir",
1479 + "tenter",
1480 + "tenu",
1481 + "terme",
1482 + "ternir",
1483 + "terre",
1484 + "test",
1485 + "texte",
1486 + "thym",
1487 + "tibia",
1488 + "tiers",
1489 + "tige",
1490 + "tipi",
1491 + "tique",
1492 + "tirer",
1493 + "tissu",
1494 + "titre",
1495 + "toast",
1496 + "toge",
1497 + "toile",
1498 + "toiser",
1499 + "toiture",
1500 + "tomber",
1501 + "tome",
1502 + "tonne",
1503 + "tonte",
1504 + "toque",
1505 + "torse",
1506 + "tortue",
1507 + "totem",
1508 + "toucher",
1509 + "toujours",
1510 + "tour",
1511 + "tousser",
1512 + "tout",
1513 + "toux",
1514 + "trace",
1515 + "train",
1516 + "trame",
1517 + "tranquille",
1518 + "travail",
1519 + "trembler",
1520 + "trente",
1521 + "tribu",
1522 + "trier",
1523 + "trio",
1524 + "tripe",
1525 + "triste",
1526 + "troc",
1527 + "trois",
1528 + "tromper",
1529 + "tronc",
1530 + "trop",
1531 + "trotter",
1532 + "trouer",
1533 + "truc",
1534 + "truite",
1535 + "tuba",
1536 + "tuer",
1537 + "tuile",
1538 + "turbo",
1539 + "tutu",
1540 + "tuyau",
1541 + "type",
1542 + "union",
1543 + "unique",
1544 + "unir",
1545 + "unisson",
1546 + "untel",
1547 + "urne",
1548 + "usage",
1549 + "user",
1550 + "usiner",
1551 + "usure",
1552 + "utile",
1553 + "vache",
1554 + "vague",
1555 + "vaincre",
1556 + "valeur",
1557 + "valoir",
1558 + "valser",
1559 + "valve",
1560 + "vampire",
1561 + "vaseux",
1562 + "vaste",
1563 + "veau",
1564 + "veille",
1565 + "veine",
1566 + "velours",
1567 + "velu",
1568 + "vendre",
1569 + "venir",
1570 + "vent",
1571 + "venue",
1572 + "verbe",
1573 + "verdict",
1574 + "version",
1575 + "vertige",
1576 + "verve",
1577 + "veste",
1578 + "veto",
1579 + "vexer",
1580 + "vice",
1581 + "victime",
1582 + "vide",
1583 + "vieil",
1584 + "vieux",
1585 + "vigie",
1586 + "vigne",
1587 + "ville",
1588 + "vingt",
1589 + "violent",
1590 + "virer",
1591 + "virus",
1592 + "visage",
1593 + "viser",
1594 + "visite",
1595 + "visuel",
1596 + "vitamine",
1597 + "vitrine",
1598 + "vivant",
1599 + "vivre",
1600 + "vocal",
1601 + "vodka",
1602 + "vogue",
1603 + "voici",
1604 + "voile",
1605 + "voir",
1606 + "voisin",
1607 + "voiture",
1608 + "volaille",
1609 + "volcan",
1610 + "voler",
1611 + "volt",
1612 + "votant",
1613 + "votre",
1614 + "vouer",
1615 + "vouloir",
1616 + "vous",
1617 + "voyage",
1618 + "voyou",
1619 + "vrac",
1620 + "vrai",
1621 + "yacht",
1622 + "yeti",
1623 + "yeux",
1624 + "yoga",
1625 + "zeste",
1626 + "zinc",
1627 + "zone",
1628 + "zoom"
1629 + ];
1630 +}
cw_wownero/lib/mnemonics/german.dart
+1 -1
@@ -1627,4 +1627,4 @@ class GermanMnemonics {
1627 "Zweck",
1628 "Zyklop"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_wownero/lib/mnemonics/italian.dart
+1629 -1629
@@ -1,1630 +1,1630 @@
1 class ItalianMnemonics {
2 - static const words = [
3 - "abbinare",
4 - "abbonato",
5 - "abisso",
6 - "abitare",
7 - "abominio",
8 - "accadere",
9 - "accesso",
10 - "acciaio",
11 - "accordo",
12 - "accumulo",
13 - "acido",
14 - "acqua",
15 - "acrobata",
16 - "acustico",
17 - "adattare",
18 - "addetto",
19 - "addio",
20 - "addome",
21 - "adeguato",
22 - "aderire",
23 - "adorare",
24 - "adottare",
25 - "adozione",
26 - "adulto",
27 - "aereo",
28 - "aerobica",
29 - "affare",
30 - "affetto",
31 - "affidare",
32 - "affogato",
33 - "affronto",
34 - "africano",
35 - "afrodite",
36 - "agenzia",
37 - "aggancio",
38 - "aggeggio",
39 - "aggiunta",
40 - "agio",
41 - "agire",
42 - "agitare",
43 - "aglio",
44 - "agnello",
45 - "agosto",
46 - "aiutare",
47 - "albero",
48 - "albo",
49 - "alce",
50 - "alchimia",
51 - "alcool",
52 - "alfabeto",
53 - "algebra",
54 - "alimento",
55 - "allarme",
56 - "alleanza",
57 - "allievo",
58 - "alloggio",
59 - "alluce",
60 - "alpi",
61 - "alterare",
62 - "altro",
63 - "aluminio",
64 - "amante",
65 - "amarezza",
66 - "ambiente",
67 - "ambrosia",
68 - "america",
69 - "amico",
70 - "ammalare",
71 - "ammirare",
72 - "amnesia",
73 - "amnistia",
74 - "amore",
75 - "ampliare",
76 - "amputare",
77 - "analisi",
78 - "anamnesi",
79 - "ananas",
80 - "anarchia",
81 - "anatra",
82 - "anca",
83 - "ancorato",
84 - "andare",
85 - "androide",
86 - "aneddoto",
87 - "anello",
88 - "angelo",
89 - "angolino",
90 - "anguilla",
91 - "anidride",
92 - "anima",
93 - "annegare",
94 - "anno",
95 - "annuncio",
96 - "anomalia",
97 - "antenna",
98 - "anticipo",
99 - "aperto",
100 - "apostolo",
101 - "appalto",
102 - "appello",
103 - "appiglio",
104 - "applauso",
105 - "appoggio",
106 - "appurare",
107 - "aprile",
108 - "aquila",
109 - "arabo",
110 - "arachidi",
111 - "aragosta",
112 - "arancia",
113 - "arbitrio",
114 - "archivio",
115 - "arco",
116 - "argento",
117 - "argilla",
118 - "aria",
119 - "ariete",
120 - "arma",
121 - "armonia",
122 - "aroma",
123 - "arrivare",
124 - "arrosto",
125 - "arsenale",
126 - "arte",
127 - "artiglio",
128 - "asfalto",
129 - "asfissia",
130 - "asino",
131 - "asparagi",
132 - "aspirina",
133 - "assalire",
134 - "assegno",
135 - "assolto",
136 - "assurdo",
137 - "asta",
138 - "astratto",
139 - "atlante",
140 - "atletica",
141 - "atomo",
142 - "atropina",
143 - "attacco",
144 - "attesa",
145 - "attico",
146 - "atto",
147 - "attrarre",
148 - "auguri",
149 - "aula",
150 - "aumento",
151 - "aurora",
152 - "auspicio",
153 - "autista",
154 - "auto",
155 - "autunno",
156 - "avanzare",
157 - "avarizia",
158 - "avere",
159 - "aviatore",
160 - "avido",
161 - "avorio",
162 - "avvenire",
163 - "avviso",
164 - "avvocato",
165 - "azienda",
166 - "azione",
167 - "azzardo",
168 - "azzurro",
169 - "babbuino",
170 - "bacio",
171 - "badante",
172 - "baffi",
173 - "bagaglio",
174 - "bagliore",
175 - "bagno",
176 - "balcone",
177 - "balena",
178 - "ballare",
179 - "balordo",
180 - "balsamo",
181 - "bambola",
182 - "bancomat",
183 - "banda",
184 - "barato",
185 - "barba",
186 - "barista",
187 - "barriera",
188 - "basette",
189 - "basilico",
190 - "bassista",
191 - "bastare",
192 - "battello",
193 - "bavaglio",
194 - "beccare",
195 - "beduino",
196 - "bellezza",
197 - "bene",
198 - "benzina",
199 - "berretto",
200 - "bestia",
201 - "bevitore",
202 - "bianco",
203 - "bibbia",
204 - "biberon",
205 - "bibita",
206 - "bici",
207 - "bidone",
208 - "bilancia",
209 - "biliardo",
210 - "binario",
211 - "binocolo",
212 - "biologia",
213 - "biondina",
214 - "biopsia",
215 - "biossido",
216 - "birbante",
217 - "birra",
218 - "biscotto",
219 - "bisogno",
220 - "bistecca",
221 - "bivio",
222 - "blindare",
223 - "bloccare",
224 - "bocca",
225 - "bollire",
226 - "bombola",
227 - "bonifico",
228 - "borghese",
229 - "borsa",
230 - "bottino",
231 - "botulino",
232 - "braccio",
233 - "bradipo",
234 - "branco",
235 - "bravo",
236 - "bresaola",
237 - "bretelle",
238 - "brevetto",
239 - "briciola",
240 - "brigante",
241 - "brillare",
242 - "brindare",
243 - "brivido",
244 - "broccoli",
245 - "brontolo",
246 - "bruciare",
247 - "brufolo",
248 - "bucare",
249 - "buddista",
250 - "budino",
251 - "bufera",
252 - "buffo",
253 - "bugiardo",
254 - "buio",
255 - "buono",
256 - "burrone",
257 - "bussola",
258 - "bustina",
259 - "buttare",
260 - "cabernet",
261 - "cabina",
262 - "cacao",
263 - "cacciare",
264 - "cactus",
265 - "cadavere",
266 - "caffe",
267 - "calamari",
268 - "calcio",
269 - "caldaia",
270 - "calmare",
271 - "calunnia",
272 - "calvario",
273 - "calzone",
274 - "cambiare",
275 - "camera",
276 - "camion",
277 - "cammello",
278 - "campana",
279 - "canarino",
280 - "cancello",
281 - "candore",
282 - "cane",
283 - "canguro",
284 - "cannone",
285 - "canoa",
286 - "cantare",
287 - "canzone",
288 - "caos",
289 - "capanna",
290 - "capello",
291 - "capire",
292 - "capo",
293 - "capperi",
294 - "capra",
295 - "capsula",
296 - "caraffa",
297 - "carbone",
298 - "carciofo",
299 - "cardigan",
300 - "carenza",
301 - "caricare",
302 - "carota",
303 - "carrello",
304 - "carta",
305 - "casa",
306 - "cascare",
307 - "caserma",
308 - "cashmere",
309 - "casino",
310 - "cassetta",
311 - "castello",
312 - "catalogo",
313 - "catena",
314 - "catorcio",
315 - "cattivo",
316 - "causa",
317 - "cauzione",
318 - "cavallo",
319 - "caverna",
320 - "caviglia",
321 - "cavo",
322 - "cazzotto",
323 - "celibato",
324 - "cemento",
325 - "cenare",
326 - "centrale",
327 - "ceramica",
328 - "cercare",
329 - "ceretta",
330 - "cerniera",
331 - "certezza",
332 - "cervello",
333 - "cessione",
334 - "cestino",
335 - "cetriolo",
336 - "chiave",
337 - "chiedere",
338 - "chilo",
339 - "chimera",
340 - "chiodo",
341 - "chirurgo",
342 - "chitarra",
343 - "chiudere",
344 - "ciabatta",
345 - "ciao",
346 - "cibo",
347 - "ciccia",
348 - "cicerone",
349 - "ciclone",
350 - "cicogna",
351 - "cielo",
352 - "cifra",
353 - "cigno",
354 - "ciliegia",
355 - "cimitero",
356 - "cinema",
357 - "cinque",
358 - "cintura",
359 - "ciondolo",
360 - "ciotola",
361 - "cipolla",
362 - "cippato",
363 - "circuito",
364 - "cisterna",
365 - "citofono",
366 - "ciuccio",
367 - "civetta",
368 - "civico",
369 - "clausola",
370 - "cliente",
371 - "clima",
372 - "clinica",
373 - "cobra",
374 - "coccole",
375 - "cocktail",
376 - "cocomero",
377 - "codice",
378 - "coesione",
379 - "cogliere",
380 - "cognome",
381 - "colla",
382 - "colomba",
383 - "colpire",
384 - "coltello",
385 - "comando",
386 - "comitato",
387 - "commedia",
388 - "comodino",
389 - "compagna",
390 - "comune",
391 - "concerto",
392 - "condotto",
393 - "conforto",
394 - "congiura",
395 - "coniglio",
396 - "consegna",
397 - "conto",
398 - "convegno",
399 - "coperta",
400 - "copia",
401 - "coprire",
402 - "corazza",
403 - "corda",
404 - "corleone",
405 - "cornice",
406 - "corona",
407 - "corpo",
408 - "corrente",
409 - "corsa",
410 - "cortesia",
411 - "corvo",
412 - "coso",
413 - "costume",
414 - "cotone",
415 - "cottura",
416 - "cozza",
417 - "crampo",
418 - "cratere",
419 - "cravatta",
420 - "creare",
421 - "credere",
422 - "crema",
423 - "crescere",
424 - "crimine",
425 - "criterio",
426 - "croce",
427 - "crollare",
428 - "cronaca",
429 - "crostata",
430 - "croupier",
431 - "cubetto",
432 - "cucciolo",
433 - "cucina",
434 - "cultura",
435 - "cuoco",
436 - "cuore",
437 - "cupido",
438 - "cupola",
439 - "cura",
440 - "curva",
441 - "cuscino",
442 - "custode",
443 - "danzare",
444 - "data",
445 - "decennio",
446 - "decidere",
447 - "decollo",
448 - "dedicare",
449 - "dedurre",
450 - "definire",
451 - "delegare",
452 - "delfino",
453 - "delitto",
454 - "demone",
455 - "dentista",
456 - "denuncia",
457 - "deposito",
458 - "derivare",
459 - "deserto",
460 - "designer",
461 - "destino",
462 - "detonare",
463 - "dettagli",
464 - "diagnosi",
465 - "dialogo",
466 - "diamante",
467 - "diario",
468 - "diavolo",
469 - "dicembre",
470 - "difesa",
471 - "digerire",
472 - "digitare",
473 - "diluvio",
474 - "dinamica",
475 - "dipinto",
476 - "diploma",
477 - "diramare",
478 - "dire",
479 - "dirigere",
480 - "dirupo",
481 - "discesa",
482 - "disdetta",
483 - "disegno",
484 - "disporre",
485 - "dissenso",
486 - "distacco",
487 - "dito",
488 - "ditta",
489 - "diva",
490 - "divenire",
491 - "dividere",
492 - "divorare",
493 - "docente",
494 - "dolcetto",
495 - "dolore",
496 - "domatore",
497 - "domenica",
498 - "dominare",
499 - "donatore",
500 - "donna",
501 - "dorato",
502 - "dormire",
503 - "dorso",
504 - "dosaggio",
505 - "dottore",
506 - "dovere",
507 - "download",
508 - "dragone",
509 - "dramma",
510 - "dubbio",
511 - "dubitare",
512 - "duetto",
513 - "durata",
514 - "ebbrezza",
515 - "eccesso",
516 - "eccitare",
517 - "eclissi",
518 - "economia",
519 - "edera",
520 - "edificio",
521 - "editore",
522 - "edizione",
523 - "educare",
524 - "effetto",
525 - "egitto",
526 - "egiziano",
527 - "elastico",
528 - "elefante",
529 - "eleggere",
530 - "elemento",
531 - "elenco",
532 - "elezione",
533 - "elmetto",
534 - "elogio",
535 - "embrione",
536 - "emergere",
537 - "emettere",
538 - "eminenza",
539 - "emisfero",
540 - "emozione",
541 - "empatia",
542 - "energia",
543 - "enfasi",
544 - "enigma",
545 - "entrare",
546 - "enzima",
547 - "epidemia",
548 - "epilogo",
549 - "episodio",
550 - "epoca",
551 - "equivoco",
552 - "erba",
553 - "erede",
554 - "eroe",
555 - "erotico",
556 - "errore",
557 - "eruzione",
558 - "esaltare",
559 - "esame",
560 - "esaudire",
561 - "eseguire",
562 - "esempio",
563 - "esigere",
564 - "esistere",
565 - "esito",
566 - "esperto",
567 - "espresso",
568 - "essere",
569 - "estasi",
570 - "esterno",
571 - "estrarre",
572 - "eterno",
573 - "etica",
574 - "euforico",
575 - "europa",
576 - "evacuare",
577 - "evasione",
578 - "evento",
579 - "evidenza",
580 - "evitare",
581 - "evolvere",
582 - "fabbrica",
583 - "facciata",
584 - "fagiano",
585 - "fagotto",
586 - "falco",
587 - "fame",
588 - "famiglia",
589 - "fanale",
590 - "fango",
591 - "fantasia",
592 - "farfalla",
593 - "farmacia",
594 - "faro",
595 - "fase",
596 - "fastidio",
597 - "faticare",
598 - "fatto",
599 - "favola",
600 - "febbre",
601 - "femmina",
602 - "femore",
603 - "fenomeno",
604 - "fermata",
605 - "feromoni",
606 - "ferrari",
607 - "fessura",
608 - "festa",
609 - "fiaba",
610 - "fiamma",
611 - "fianco",
612 - "fiat",
613 - "fibbia",
614 - "fidare",
615 - "fieno",
616 - "figa",
617 - "figlio",
618 - "figura",
619 - "filetto",
620 - "filmato",
621 - "filosofo",
622 - "filtrare",
623 - "finanza",
624 - "finestra",
625 - "fingere",
626 - "finire",
627 - "finta",
628 - "finzione",
629 - "fiocco",
630 - "fioraio",
631 - "firewall",
632 - "firmare",
633 - "fisico",
634 - "fissare",
635 - "fittizio",
636 - "fiume",
637 - "flacone",
638 - "flagello",
639 - "flirtare",
640 - "flusso",
641 - "focaccia",
642 - "foglio",
643 - "fognario",
644 - "follia",
645 - "fonderia",
646 - "fontana",
647 - "forbici",
648 - "forcella",
649 - "foresta",
650 - "forgiare",
651 - "formare",
652 - "fornace",
653 - "foro",
654 - "fortuna",
655 - "forzare",
656 - "fosforo",
657 - "fotoni",
658 - "fracasso",
659 - "fragola",
660 - "frantumi",
661 - "fratello",
662 - "frazione",
663 - "freccia",
664 - "freddo",
665 - "frenare",
666 - "fresco",
667 - "friggere",
668 - "frittata",
669 - "frivolo",
670 - "frizione",
671 - "fronte",
672 - "frullato",
673 - "frumento",
674 - "frusta",
675 - "frutto",
676 - "fucile",
677 - "fuggire",
678 - "fulmine",
679 - "fumare",
680 - "funzione",
681 - "fuoco",
682 - "furbizia",
683 - "furgone",
684 - "furia",
685 - "furore",
686 - "fusibile",
687 - "fuso",
688 - "futuro",
689 - "gabbiano",
690 - "galassia",
691 - "gallina",
692 - "gamba",
693 - "gancio",
694 - "garanzia",
695 - "garofano",
696 - "gasolio",
697 - "gatto",
698 - "gazebo",
699 - "gazzetta",
700 - "gelato",
701 - "gemelli",
702 - "generare",
703 - "genitori",
704 - "gennaio",
705 - "geologia",
706 - "germania",
707 - "gestire",
708 - "gettare",
709 - "ghepardo",
710 - "ghiaccio",
711 - "giaccone",
712 - "giaguaro",
713 - "giallo",
714 - "giappone",
715 - "giardino",
716 - "gigante",
717 - "gioco",
718 - "gioiello",
719 - "giorno",
720 - "giovane",
721 - "giraffa",
722 - "giudizio",
723 - "giurare",
724 - "giusto",
725 - "globo",
726 - "gloria",
727 - "glucosio",
728 - "gnocca",
729 - "gocciola",
730 - "godere",
731 - "gomito",
732 - "gomma",
733 - "gonfiare",
734 - "gorilla",
735 - "governo",
736 - "gradire",
737 - "graffiti",
738 - "granchio",
739 - "grappolo",
740 - "grasso",
741 - "grattare",
742 - "gridare",
743 - "grissino",
744 - "grondaia",
745 - "grugnito",
746 - "gruppo",
747 - "guadagno",
748 - "guaio",
749 - "guancia",
750 - "guardare",
751 - "gufo",
752 - "guidare",
753 - "guscio",
754 - "gusto",
755 - "icona",
756 - "idea",
757 - "identico",
758 - "idolo",
759 - "idoneo",
760 - "idrante",
761 - "idrogeno",
762 - "igiene",
763 - "ignoto",
764 - "imbarco",
765 - "immagine",
766 - "immobile",
767 - "imparare",
768 - "impedire",
769 - "impianto",
770 - "importo",
771 - "impresa",
772 - "impulso",
773 - "incanto",
774 - "incendio",
775 - "incidere",
776 - "incontro",
777 - "incrocia",
778 - "incubo",
779 - "indagare",
780 - "indice",
781 - "indotto",
782 - "infanzia",
783 - "inferno",
784 - "infinito",
785 - "infranto",
786 - "ingerire",
787 - "inglese",
788 - "ingoiare",
789 - "ingresso",
790 - "iniziare",
791 - "innesco",
792 - "insalata",
793 - "inserire",
794 - "insicuro",
795 - "insonnia",
796 - "insulto",
797 - "interno",
798 - "introiti",
799 - "invasori",
800 - "inverno",
801 - "invito",
802 - "invocare",
803 - "ipnosi",
804 - "ipocrita",
805 - "ipotesi",
806 - "ironia",
807 - "irrigare",
808 - "iscritto",
809 - "isola",
810 - "ispirare",
811 - "isterico",
812 - "istinto",
813 - "istruire",
814 - "italiano",
815 - "jazz",
816 - "labbra",
817 - "labrador",
818 - "ladro",
819 - "lago",
820 - "lamento",
821 - "lampone",
822 - "lancetta",
823 - "lanterna",
824 - "lapide",
825 - "larva",
826 - "lasagne",
827 - "lasciare",
828 - "lastra",
829 - "latte",
830 - "laurea",
831 - "lavagna",
832 - "lavorare",
833 - "leccare",
834 - "legare",
835 - "leggere",
836 - "lenzuolo",
837 - "leone",
838 - "lepre",
839 - "letargo",
840 - "lettera",
841 - "levare",
842 - "levitare",
843 - "lezione",
844 - "liberare",
845 - "libidine",
846 - "libro",
847 - "licenza",
848 - "lievito",
849 - "limite",
850 - "lince",
851 - "lingua",
852 - "liquore",
853 - "lire",
854 - "listino",
855 - "litigare",
856 - "litro",
857 - "locale",
858 - "lottare",
859 - "lucciola",
860 - "lucidare",
861 - "luglio",
862 - "luna",
863 - "macchina",
864 - "madama",
865 - "madre",
866 - "maestro",
867 - "maggio",
868 - "magico",
869 - "maglione",
870 - "magnolia",
871 - "mago",
872 - "maialino",
873 - "maionese",
874 - "malattia",
875 - "male",
876 - "malloppo",
877 - "mancare",
878 - "mandorla",
879 - "mangiare",
880 - "manico",
881 - "manopola",
882 - "mansarda",
883 - "mantello",
884 - "manubrio",
885 - "manzo",
886 - "mappa",
887 - "mare",
888 - "margine",
889 - "marinaio",
890 - "marmotta",
891 - "marocco",
892 - "martello",
893 - "marzo",
894 - "maschera",
895 - "matrice",
896 - "maturare",
897 - "mazzetta",
898 - "meandri",
899 - "medaglia",
900 - "medico",
901 - "medusa",
902 - "megafono",
903 - "melone",
904 - "membrana",
905 - "menta",
906 - "mercato",
907 - "meritare",
908 - "merluzzo",
909 - "mese",
910 - "mestiere",
911 - "metafora",
912 - "meteo",
913 - "metodo",
914 - "mettere",
915 - "miele",
916 - "miglio",
917 - "miliardo",
918 - "mimetica",
919 - "minatore",
920 - "minuto",
921 - "miracolo",
922 - "mirtillo",
923 - "missile",
924 - "mistero",
925 - "misura",
926 - "mito",
927 - "mobile",
928 - "moda",
929 - "moderare",
930 - "moglie",
931 - "molecola",
932 - "molle",
933 - "momento",
934 - "moneta",
935 - "mongolia",
936 - "monologo",
937 - "montagna",
938 - "morale",
939 - "morbillo",
940 - "mordere",
941 - "mosaico",
942 - "mosca",
943 - "mostro",
944 - "motivare",
945 - "moto",
946 - "mulino",
947 - "mulo",
948 - "muovere",
949 - "muraglia",
950 - "muscolo",
951 - "museo",
952 - "musica",
953 - "mutande",
954 - "nascere",
955 - "nastro",
956 - "natale",
957 - "natura",
958 - "nave",
959 - "navigare",
960 - "negare",
961 - "negozio",
962 - "nemico",
963 - "nero",
964 - "nervo",
965 - "nessuno",
966 - "nettare",
967 - "neutroni",
968 - "neve",
969 - "nevicare",
970 - "nicotina",
971 - "nido",
972 - "nipote",
973 - "nocciola",
974 - "noleggio",
975 - "nome",
976 - "nonno",
977 - "norvegia",
978 - "notare",
979 - "notizia",
980 - "nove",
981 - "nucleo",
982 - "nuda",
983 - "nuotare",
984 - "nutrire",
985 - "obbligo",
986 - "occhio",
987 - "occupare",
988 - "oceano",
989 - "odissea",
990 - "odore",
991 - "offerta",
992 - "officina",
993 - "offrire",
994 - "oggetto",
995 - "oggi",
996 - "olfatto",
997 - "olio",
998 - "oliva",
999 - "ombelico",
1000 - "ombrello",
1001 - "omuncolo",
1002 - "ondata",
1003 - "onore",
1004 - "opera",
1005 - "opinione",
1006 - "opuscolo",
1007 - "opzione",
1008 - "orario",
1009 - "orbita",
1010 - "orchidea",
1011 - "ordine",
1012 - "orecchio",
1013 - "orgasmo",
1014 - "orgoglio",
1015 - "origine",
1016 - "orologio",
1017 - "oroscopo",
1018 - "orso",
1019 - "oscurare",
1020 - "ospedale",
1021 - "ospite",
1022 - "ossigeno",
1023 - "ostacolo",
1024 - "ostriche",
1025 - "ottenere",
1026 - "ottimo",
1027 - "ottobre",
1028 - "ovest",
1029 - "pacco",
1030 - "pace",
1031 - "pacifico",
1032 - "padella",
1033 - "pagare",
1034 - "pagina",
1035 - "pagnotta",
1036 - "palazzo",
1037 - "palestra",
1038 - "palpebre",
1039 - "pancetta",
1040 - "panfilo",
1041 - "panino",
1042 - "pannello",
1043 - "panorama",
1044 - "papa",
1045 - "paperino",
1046 - "paradiso",
1047 - "parcella",
1048 - "parente",
1049 - "parlare",
1050 - "parodia",
1051 - "parrucca",
1052 - "partire",
1053 - "passare",
1054 - "pasta",
1055 - "patata",
1056 - "patente",
1057 - "patogeno",
1058 - "patriota",
1059 - "pausa",
1060 - "pazienza",
1061 - "peccare",
1062 - "pecora",
1063 - "pedalare",
1064 - "pelare",
1065 - "pena",
1066 - "pendenza",
1067 - "penisola",
1068 - "pennello",
1069 - "pensare",
1070 - "pentirsi",
1071 - "percorso",
1072 - "perdono",
1073 - "perfetto",
1074 - "perizoma",
1075 - "perla",
1076 - "permesso",
1077 - "persona",
1078 - "pesare",
1079 - "pesce",
1080 - "peso",
1081 - "petardo",
1082 - "petrolio",
1083 - "pezzo",
1084 - "piacere",
1085 - "pianeta",
1086 - "piastra",
1087 - "piatto",
1088 - "piazza",
1089 - "piccolo",
1090 - "piede",
1091 - "piegare",
1092 - "pietra",
1093 - "pigiama",
1094 - "pigliare",
1095 - "pigrizia",
1096 - "pilastro",
1097 - "pilota",
1098 - "pinguino",
1099 - "pioggia",
1100 - "piombo",
1101 - "pionieri",
1102 - "piovra",
1103 - "pipa",
1104 - "pirata",
1105 - "pirolisi",
1106 - "piscina",
1107 - "pisolino",
1108 - "pista",
1109 - "pitone",
1110 - "piumino",
1111 - "pizza",
1112 - "plastica",
1113 - "platino",
1114 - "poesia",
1115 - "poiana",
1116 - "polaroid",
1117 - "polenta",
1118 - "polimero",
1119 - "pollo",
1120 - "polmone",
1121 - "polpetta",
1122 - "poltrona",
1123 - "pomodoro",
1124 - "pompa",
1125 - "popolo",
1126 - "porco",
1127 - "porta",
1128 - "porzione",
1129 - "possesso",
1130 - "postino",
1131 - "potassio",
1132 - "potere",
1133 - "poverino",
1134 - "pranzo",
1135 - "prato",
1136 - "prefisso",
1137 - "prelievo",
1138 - "premio",
1139 - "prendere",
1140 - "prestare",
1141 - "pretesa",
1142 - "prezzo",
1143 - "primario",
1144 - "privacy",
1145 - "problema",
1146 - "processo",
1147 - "prodotto",
1148 - "profeta",
1149 - "progetto",
1150 - "promessa",
1151 - "pronto",
1152 - "proposta",
1153 - "proroga",
1154 - "prossimo",
1155 - "proteina",
1156 - "prova",
1157 - "prudenza",
1158 - "pubblico",
1159 - "pudore",
1160 - "pugilato",
1161 - "pulire",
1162 - "pulsante",
1163 - "puntare",
1164 - "pupazzo",
1165 - "puzzle",
1166 - "quaderno",
1167 - "qualcuno",
1168 - "quarzo",
1169 - "quercia",
1170 - "quintale",
1171 - "rabbia",
1172 - "racconto",
1173 - "radice",
1174 - "raffica",
1175 - "ragazza",
1176 - "ragione",
1177 - "rammento",
1178 - "ramo",
1179 - "rana",
1180 - "randagio",
1181 - "rapace",
1182 - "rapinare",
1183 - "rapporto",
1184 - "rasatura",
1185 - "ravioli",
1186 - "reagire",
1187 - "realista",
1188 - "reattore",
1189 - "reazione",
1190 - "recitare",
1191 - "recluso",
1192 - "record",
1193 - "recupero",
1194 - "redigere",
1195 - "regalare",
1196 - "regina",
1197 - "regola",
1198 - "relatore",
1199 - "reliquia",
1200 - "remare",
1201 - "rendere",
1202 - "reparto",
1203 - "resina",
1204 - "resto",
1205 - "rete",
1206 - "retorica",
1207 - "rettile",
1208 - "revocare",
1209 - "riaprire",
1210 - "ribadire",
1211 - "ribelle",
1212 - "ricambio",
1213 - "ricetta",
1214 - "richiamo",
1215 - "ricordo",
1216 - "ridurre",
1217 - "riempire",
1218 - "riferire",
1219 - "riflesso",
1220 - "righello",
1221 - "rilancio",
1222 - "rilevare",
1223 - "rilievo",
1224 - "rimanere",
1225 - "rimborso",
1226 - "rinforzo",
1227 - "rinuncia",
1228 - "riparo",
1229 - "ripetere",
1230 - "riposare",
1231 - "ripulire",
1232 - "risalita",
1233 - "riscatto",
1234 - "riserva",
1235 - "riso",
1236 - "rispetto",
1237 - "ritaglio",
1238 - "ritmo",
1239 - "ritorno",
1240 - "ritratto",
1241 - "rituale",
1242 - "riunione",
1243 - "riuscire",
1244 - "riva",
1245 - "robotica",
1246 - "rondine",
1247 - "rosa",
1248 - "rospo",
1249 - "rosso",
1250 - "rotonda",
1251 - "rotta",
1252 - "roulotte",
1253 - "rubare",
1254 - "rubrica",
1255 - "ruffiano",
1256 - "rumore",
1257 - "ruota",
1258 - "ruscello",
1259 - "sabbia",
1260 - "sacco",
1261 - "saggio",
1262 - "sale",
1263 - "salire",
1264 - "salmone",
1265 - "salto",
1266 - "salutare",
1267 - "salvia",
1268 - "sangue",
1269 - "sanzioni",
1270 - "sapere",
1271 - "sapienza",
1272 - "sarcasmo",
1273 - "sardine",
1274 - "sartoria",
1275 - "sbalzo",
1276 - "sbarcare",
1277 - "sberla",
1278 - "sborsare",
1279 - "scadenza",
1280 - "scafo",
1281 - "scala",
1282 - "scambio",
1283 - "scappare",
1284 - "scarpa",
1285 - "scatola",
1286 - "scelta",
1287 - "scena",
1288 - "sceriffo",
1289 - "scheggia",
1290 - "schiuma",
1291 - "sciarpa",
1292 - "scienza",
1293 - "scimmia",
1294 - "sciopero",
1295 - "scivolo",
1296 - "sclerare",
1297 - "scolpire",
1298 - "sconto",
1299 - "scopa",
1300 - "scordare",
1301 - "scossa",
1302 - "scrivere",
1303 - "scrupolo",
1304 - "scuderia",
1305 - "scultore",
1306 - "scuola",
1307 - "scusare",
1308 - "sdraiare",
1309 - "secolo",
1310 - "sedativo",
1311 - "sedere",
1312 - "sedia",
1313 - "segare",
1314 - "segreto",
1315 - "seguire",
1316 - "semaforo",
1317 - "seme",
1318 - "senape",
1319 - "seno",
1320 - "sentiero",
1321 - "separare",
1322 - "sepolcro",
1323 - "sequenza",
1324 - "serata",
1325 - "serpente",
1326 - "servizio",
1327 - "sesso",
1328 - "seta",
1329 - "settore",
1330 - "sfamare",
1331 - "sfera",
1332 - "sfidare",
1333 - "sfiorare",
1334 - "sfogare",
1335 - "sgabello",
1336 - "sicuro",
1337 - "siepe",
1338 - "sigaro",
1339 - "silenzio",
1340 - "silicone",
1341 - "simbiosi",
1342 - "simpatia",
1343 - "simulare",
1344 - "sinapsi",
1345 - "sindrome",
1346 - "sinergia",
1347 - "sinonimo",
1348 - "sintonia",
1349 - "sirena",
1350 - "siringa",
1351 - "sistema",
1352 - "sito",
1353 - "smalto",
1354 - "smentire",
1355 - "smontare",
1356 - "soccorso",
1357 - "socio",
1358 - "soffitto",
1359 - "software",
1360 - "soggetto",
1361 - "sogliola",
1362 - "sognare",
1363 - "soldi",
1364 - "sole",
1365 - "sollievo",
1366 - "solo",
1367 - "sommario",
1368 - "sondare",
1369 - "sonno",
1370 - "sorpresa",
1371 - "sorriso",
1372 - "sospiro",
1373 - "sostegno",
1374 - "sovrano",
1375 - "spaccare",
1376 - "spada",
1377 - "spagnolo",
1378 - "spalla",
1379 - "sparire",
1380 - "spavento",
1381 - "spazio",
1382 - "specchio",
1383 - "spedire",
1384 - "spegnere",
1385 - "spendere",
1386 - "speranza",
1387 - "spessore",
1388 - "spezzare",
1389 - "spiaggia",
1390 - "spiccare",
1391 - "spiegare",
1392 - "spiffero",
1393 - "spingere",
1394 - "sponda",
1395 - "sporcare",
1396 - "spostare",
1397 - "spremuta",
1398 - "spugna",
1399 - "spumante",
1400 - "spuntare",
1401 - "squadra",
1402 - "squillo",
1403 - "staccare",
1404 - "stadio",
1405 - "stagione",
1406 - "stallone",
1407 - "stampa",
1408 - "stancare",
1409 - "starnuto",
1410 - "statura",
1411 - "stella",
1412 - "stendere",
1413 - "sterzo",
1414 - "stilista",
1415 - "stimolo",
1416 - "stinco",
1417 - "stiva",
1418 - "stoffa",
1419 - "storia",
1420 - "strada",
1421 - "stregone",
1422 - "striscia",
1423 - "studiare",
1424 - "stufa",
1425 - "stupendo",
1426 - "subire",
1427 - "successo",
1428 - "sudare",
1429 - "suono",
1430 - "superare",
1431 - "supporto",
1432 - "surfista",
1433 - "sussurro",
1434 - "svelto",
1435 - "svenire",
1436 - "sviluppo",
1437 - "svolta",
1438 - "svuotare",
1439 - "tabacco",
1440 - "tabella",
1441 - "tabu",
1442 - "tacchino",
1443 - "tacere",
1444 - "taglio",
1445 - "talento",
1446 - "tangente",
1447 - "tappeto",
1448 - "tartufo",
1449 - "tassello",
1450 - "tastiera",
1451 - "tavolo",
1452 - "tazza",
1453 - "teatro",
1454 - "tedesco",
1455 - "telaio",
1456 - "telefono",
1457 - "tema",
1458 - "temere",
1459 - "tempo",
1460 - "tendenza",
1461 - "tenebre",
1462 - "tensione",
1463 - "tentare",
1464 - "teologia",
1465 - "teorema",
1466 - "termica",
1467 - "terrazzo",
1468 - "teschio",
1469 - "tesi",
1470 - "tesoro",
1471 - "tessera",
1472 - "testa",
1473 - "thriller",
1474 - "tifoso",
1475 - "tigre",
1476 - "timbrare",
1477 - "timido",
1478 - "tinta",
1479 - "tirare",
1480 - "tisana",
1481 - "titano",
1482 - "titolo",
1483 - "toccare",
1484 - "togliere",
1485 - "topolino",
1486 - "torcia",
1487 - "torrente",
1488 - "tovaglia",
1489 - "traffico",
1490 - "tragitto",
1491 - "training",
1492 - "tramonto",
1493 - "transito",
1494 - "trapezio",
1495 - "trasloco",
1496 - "trattore",
1497 - "trazione",
1498 - "treccia",
1499 - "tregua",
1500 - "treno",
1501 - "triciclo",
1502 - "tridente",
1503 - "trilogia",
1504 - "tromba",
1505 - "troncare",
1506 - "trota",
1507 - "trovare",
1508 - "trucco",
1509 - "tubo",
1510 - "tulipano",
1511 - "tumulto",
1512 - "tunisia",
1513 - "tuono",
1514 - "turista",
1515 - "tuta",
1516 - "tutelare",
1517 - "tutore",
1518 - "ubriaco",
1519 - "uccello",
1520 - "udienza",
1521 - "udito",
1522 - "uffa",
1523 - "umanoide",
1524 - "umore",
1525 - "unghia",
1526 - "unguento",
1527 - "unicorno",
1528 - "unione",
1529 - "universo",
1530 - "uomo",
1531 - "uragano",
1532 - "uranio",
1533 - "urlare",
1534 - "uscire",
1535 - "utente",
1536 - "utilizzo",
1537 - "vacanza",
1538 - "vacca",
1539 - "vaglio",
1540 - "vagonata",
1541 - "valle",
1542 - "valore",
1543 - "valutare",
1544 - "valvola",
1545 - "vampiro",
1546 - "vaniglia",
1547 - "vanto",
1548 - "vapore",
1549 - "variante",
1550 - "vasca",
1551 - "vaselina",
1552 - "vassoio",
1553 - "vedere",
1554 - "vegetale",
1555 - "veglia",
1556 - "veicolo",
1557 - "vela",
1558 - "veleno",
1559 - "velivolo",
1560 - "velluto",
1561 - "vendere",
1562 - "venerare",
1563 - "venire",
1564 - "vento",
1565 - "veranda",
1566 - "verbo",
1567 - "verdura",
1568 - "vergine",
1569 - "verifica",
1570 - "vernice",
1571 - "vero",
1572 - "verruca",
1573 - "versare",
1574 - "vertebra",
1575 - "vescica",
1576 - "vespaio",
1577 - "vestito",
1578 - "vesuvio",
1579 - "veterano",
1580 - "vetro",
1581 - "vetta",
1582 - "viadotto",
1583 - "viaggio",
1584 - "vibrare",
1585 - "vicenda",
1586 - "vichingo",
1587 - "vietare",
1588 - "vigilare",
1589 - "vigneto",
1590 - "villa",
1591 - "vincere",
1592 - "violino",
1593 - "vipera",
1594 - "virgola",
1595 - "virtuoso",
1596 - "visita",
1597 - "vita",
1598 - "vitello",
1599 - "vittima",
1600 - "vivavoce",
1601 - "vivere",
1602 - "viziato",
1603 - "voglia",
1604 - "volare",
1605 - "volpe",
1606 - "volto",
1607 - "volume",
1608 - "vongole",
1609 - "voragine",
1610 - "vortice",
1611 - "votare",
1612 - "vulcano",
1613 - "vuotare",
1614 - "zabaione",
1615 - "zaffiro",
1616 - "zainetto",
1617 - "zampa",
1618 - "zanzara",
1619 - "zattera",
1620 - "zavorra",
1621 - "zenzero",
1622 - "zero",
1623 - "zingaro",
1624 - "zittire",
1625 - "zoccolo",
1626 - "zolfo",
1627 - "zombie",
1628 - "zucchero"
1629 - ];
1630 -}
\ No newline at end of file
2 + static const words = [
3 + "abbinare",
4 + "abbonato",
5 + "abisso",
6 + "abitare",
7 + "abominio",
8 + "accadere",
9 + "accesso",
10 + "acciaio",
11 + "accordo",
12 + "accumulo",
13 + "acido",
14 + "acqua",
15 + "acrobata",
16 + "acustico",
17 + "adattare",
18 + "addetto",
19 + "addio",
20 + "addome",
21 + "adeguato",
22 + "aderire",
23 + "adorare",
24 + "adottare",
25 + "adozione",
26 + "adulto",
27 + "aereo",
28 + "aerobica",
29 + "affare",
30 + "affetto",
31 + "affidare",
32 + "affogato",
33 + "affronto",
34 + "africano",
35 + "afrodite",
36 + "agenzia",
37 + "aggancio",
38 + "aggeggio",
39 + "aggiunta",
40 + "agio",
41 + "agire",
42 + "agitare",
43 + "aglio",
44 + "agnello",
45 + "agosto",
46 + "aiutare",
47 + "albero",
48 + "albo",
49 + "alce",
50 + "alchimia",
51 + "alcool",
52 + "alfabeto",
53 + "algebra",
54 + "alimento",
55 + "allarme",
56 + "alleanza",
57 + "allievo",
58 + "alloggio",
59 + "alluce",
60 + "alpi",
61 + "alterare",
62 + "altro",
63 + "aluminio",
64 + "amante",
65 + "amarezza",
66 + "ambiente",
67 + "ambrosia",
68 + "america",
69 + "amico",
70 + "ammalare",
71 + "ammirare",
72 + "amnesia",
73 + "amnistia",
74 + "amore",
75 + "ampliare",
76 + "amputare",
77 + "analisi",
78 + "anamnesi",
79 + "ananas",
80 + "anarchia",
81 + "anatra",
82 + "anca",
83 + "ancorato",
84 + "andare",
85 + "androide",
86 + "aneddoto",
87 + "anello",
88 + "angelo",
89 + "angolino",
90 + "anguilla",
91 + "anidride",
92 + "anima",
93 + "annegare",
94 + "anno",
95 + "annuncio",
96 + "anomalia",
97 + "antenna",
98 + "anticipo",
99 + "aperto",
100 + "apostolo",
101 + "appalto",
102 + "appello",
103 + "appiglio",
104 + "applauso",
105 + "appoggio",
106 + "appurare",
107 + "aprile",
108 + "aquila",
109 + "arabo",
110 + "arachidi",
111 + "aragosta",
112 + "arancia",
113 + "arbitrio",
114 + "archivio",
115 + "arco",
116 + "argento",
117 + "argilla",
118 + "aria",
119 + "ariete",
120 + "arma",
121 + "armonia",
122 + "aroma",
123 + "arrivare",
124 + "arrosto",
125 + "arsenale",
126 + "arte",
127 + "artiglio",
128 + "asfalto",
129 + "asfissia",
130 + "asino",
131 + "asparagi",
132 + "aspirina",
133 + "assalire",
134 + "assegno",
135 + "assolto",
136 + "assurdo",
137 + "asta",
138 + "astratto",
139 + "atlante",
140 + "atletica",
141 + "atomo",
142 + "atropina",
143 + "attacco",
144 + "attesa",
145 + "attico",
146 + "atto",
147 + "attrarre",
148 + "auguri",
149 + "aula",
150 + "aumento",
151 + "aurora",
152 + "auspicio",
153 + "autista",
154 + "auto",
155 + "autunno",
156 + "avanzare",
157 + "avarizia",
158 + "avere",
159 + "aviatore",
160 + "avido",
161 + "avorio",
162 + "avvenire",
163 + "avviso",
164 + "avvocato",
165 + "azienda",
166 + "azione",
167 + "azzardo",
168 + "azzurro",
169 + "babbuino",
170 + "bacio",
171 + "badante",
172 + "baffi",
173 + "bagaglio",
174 + "bagliore",
175 + "bagno",
176 + "balcone",
177 + "balena",
178 + "ballare",
179 + "balordo",
180 + "balsamo",
181 + "bambola",
182 + "bancomat",
183 + "banda",
184 + "barato",
185 + "barba",
186 + "barista",
187 + "barriera",
188 + "basette",
189 + "basilico",
190 + "bassista",
191 + "bastare",
192 + "battello",
193 + "bavaglio",
194 + "beccare",
195 + "beduino",
196 + "bellezza",
197 + "bene",
198 + "benzina",
199 + "berretto",
200 + "bestia",
201 + "bevitore",
202 + "bianco",
203 + "bibbia",
204 + "biberon",
205 + "bibita",
206 + "bici",
207 + "bidone",
208 + "bilancia",
209 + "biliardo",
210 + "binario",
211 + "binocolo",
212 + "biologia",
213 + "biondina",
214 + "biopsia",
215 + "biossido",
216 + "birbante",
217 + "birra",
218 + "biscotto",
219 + "bisogno",
220 + "bistecca",
221 + "bivio",
222 + "blindare",
223 + "bloccare",
224 + "bocca",
225 + "bollire",
226 + "bombola",
227 + "bonifico",
228 + "borghese",
229 + "borsa",
230 + "bottino",
231 + "botulino",
232 + "braccio",
233 + "bradipo",
234 + "branco",
235 + "bravo",
236 + "bresaola",
237 + "bretelle",
238 + "brevetto",
239 + "briciola",
240 + "brigante",
241 + "brillare",
242 + "brindare",
243 + "brivido",
244 + "broccoli",
245 + "brontolo",
246 + "bruciare",
247 + "brufolo",
248 + "bucare",
249 + "buddista",
250 + "budino",
251 + "bufera",
252 + "buffo",
253 + "bugiardo",
254 + "buio",
255 + "buono",
256 + "burrone",
257 + "bussola",
258 + "bustina",
259 + "buttare",
260 + "cabernet",
261 + "cabina",
262 + "cacao",
263 + "cacciare",
264 + "cactus",
265 + "cadavere",
266 + "caffe",
267 + "calamari",
268 + "calcio",
269 + "caldaia",
270 + "calmare",
271 + "calunnia",
272 + "calvario",
273 + "calzone",
274 + "cambiare",
275 + "camera",
276 + "camion",
277 + "cammello",
278 + "campana",
279 + "canarino",
280 + "cancello",
281 + "candore",
282 + "cane",
283 + "canguro",
284 + "cannone",
285 + "canoa",
286 + "cantare",
287 + "canzone",
288 + "caos",
289 + "capanna",
290 + "capello",
291 + "capire",
292 + "capo",
293 + "capperi",
294 + "capra",
295 + "capsula",
296 + "caraffa",
297 + "carbone",
298 + "carciofo",
299 + "cardigan",
300 + "carenza",
301 + "caricare",
302 + "carota",
303 + "carrello",
304 + "carta",
305 + "casa",
306 + "cascare",
307 + "caserma",
308 + "cashmere",
309 + "casino",
310 + "cassetta",
311 + "castello",
312 + "catalogo",
313 + "catena",
314 + "catorcio",
315 + "cattivo",
316 + "causa",
317 + "cauzione",
318 + "cavallo",
319 + "caverna",
320 + "caviglia",
321 + "cavo",
322 + "cazzotto",
323 + "celibato",
324 + "cemento",
325 + "cenare",
326 + "centrale",
327 + "ceramica",
328 + "cercare",
329 + "ceretta",
330 + "cerniera",
331 + "certezza",
332 + "cervello",
333 + "cessione",
334 + "cestino",
335 + "cetriolo",
336 + "chiave",
337 + "chiedere",
338 + "chilo",
339 + "chimera",
340 + "chiodo",
341 + "chirurgo",
342 + "chitarra",
343 + "chiudere",
344 + "ciabatta",
345 + "ciao",
346 + "cibo",
347 + "ciccia",
348 + "cicerone",
349 + "ciclone",
350 + "cicogna",
351 + "cielo",
352 + "cifra",
353 + "cigno",
354 + "ciliegia",
355 + "cimitero",
356 + "cinema",
357 + "cinque",
358 + "cintura",
359 + "ciondolo",
360 + "ciotola",
361 + "cipolla",
362 + "cippato",
363 + "circuito",
364 + "cisterna",
365 + "citofono",
366 + "ciuccio",
367 + "civetta",
368 + "civico",
369 + "clausola",
370 + "cliente",
371 + "clima",
372 + "clinica",
373 + "cobra",
374 + "coccole",
375 + "cocktail",
376 + "cocomero",
377 + "codice",
378 + "coesione",
379 + "cogliere",
380 + "cognome",
381 + "colla",
382 + "colomba",
383 + "colpire",
384 + "coltello",
385 + "comando",
386 + "comitato",
387 + "commedia",
388 + "comodino",
389 + "compagna",
390 + "comune",
391 + "concerto",
392 + "condotto",
393 + "conforto",
394 + "congiura",
395 + "coniglio",
396 + "consegna",
397 + "conto",
398 + "convegno",
399 + "coperta",
400 + "copia",
401 + "coprire",
402 + "corazza",
403 + "corda",
404 + "corleone",
405 + "cornice",
406 + "corona",
407 + "corpo",
408 + "corrente",
409 + "corsa",
410 + "cortesia",
411 + "corvo",
412 + "coso",
413 + "costume",
414 + "cotone",
415 + "cottura",
416 + "cozza",
417 + "crampo",
418 + "cratere",
419 + "cravatta",
420 + "creare",
421 + "credere",
422 + "crema",
423 + "crescere",
424 + "crimine",
425 + "criterio",
426 + "croce",
427 + "crollare",
428 + "cronaca",
429 + "crostata",
430 + "croupier",
431 + "cubetto",
432 + "cucciolo",
433 + "cucina",
434 + "cultura",
435 + "cuoco",
436 + "cuore",
437 + "cupido",
438 + "cupola",
439 + "cura",
440 + "curva",
441 + "cuscino",
442 + "custode",
443 + "danzare",
444 + "data",
445 + "decennio",
446 + "decidere",
447 + "decollo",
448 + "dedicare",
449 + "dedurre",
450 + "definire",
451 + "delegare",
452 + "delfino",
453 + "delitto",
454 + "demone",
455 + "dentista",
456 + "denuncia",
457 + "deposito",
458 + "derivare",
459 + "deserto",
460 + "designer",
461 + "destino",
462 + "detonare",
463 + "dettagli",
464 + "diagnosi",
465 + "dialogo",
466 + "diamante",
467 + "diario",
468 + "diavolo",
469 + "dicembre",
470 + "difesa",
471 + "digerire",
472 + "digitare",
473 + "diluvio",
474 + "dinamica",
475 + "dipinto",
476 + "diploma",
477 + "diramare",
478 + "dire",
479 + "dirigere",
480 + "dirupo",
481 + "discesa",
482 + "disdetta",
483 + "disegno",
484 + "disporre",
485 + "dissenso",
486 + "distacco",
487 + "dito",
488 + "ditta",
489 + "diva",
490 + "divenire",
491 + "dividere",
492 + "divorare",
493 + "docente",
494 + "dolcetto",
495 + "dolore",
496 + "domatore",
497 + "domenica",
498 + "dominare",
499 + "donatore",
500 + "donna",
501 + "dorato",
502 + "dormire",
503 + "dorso",
504 + "dosaggio",
505 + "dottore",
506 + "dovere",
507 + "download",
508 + "dragone",
509 + "dramma",
510 + "dubbio",
511 + "dubitare",
512 + "duetto",
513 + "durata",
514 + "ebbrezza",
515 + "eccesso",
516 + "eccitare",
517 + "eclissi",
518 + "economia",
519 + "edera",
520 + "edificio",
521 + "editore",
522 + "edizione",
523 + "educare",
524 + "effetto",
525 + "egitto",
526 + "egiziano",
527 + "elastico",
528 + "elefante",
529 + "eleggere",
530 + "elemento",
531 + "elenco",
532 + "elezione",
533 + "elmetto",
534 + "elogio",
535 + "embrione",
536 + "emergere",
537 + "emettere",
538 + "eminenza",
539 + "emisfero",
540 + "emozione",
541 + "empatia",
542 + "energia",
543 + "enfasi",
544 + "enigma",
545 + "entrare",
546 + "enzima",
547 + "epidemia",
548 + "epilogo",
549 + "episodio",
550 + "epoca",
551 + "equivoco",
552 + "erba",
553 + "erede",
554 + "eroe",
555 + "erotico",
556 + "errore",
557 + "eruzione",
558 + "esaltare",
559 + "esame",
560 + "esaudire",
561 + "eseguire",
562 + "esempio",
563 + "esigere",
564 + "esistere",
565 + "esito",
566 + "esperto",
567 + "espresso",
568 + "essere",
569 + "estasi",
570 + "esterno",
571 + "estrarre",
572 + "eterno",
573 + "etica",
574 + "euforico",
575 + "europa",
576 + "evacuare",
577 + "evasione",
578 + "evento",
579 + "evidenza",
580 + "evitare",
581 + "evolvere",
582 + "fabbrica",
583 + "facciata",
584 + "fagiano",
585 + "fagotto",
586 + "falco",
587 + "fame",
588 + "famiglia",
589 + "fanale",
590 + "fango",
591 + "fantasia",
592 + "farfalla",
593 + "farmacia",
594 + "faro",
595 + "fase",
596 + "fastidio",
597 + "faticare",
598 + "fatto",
599 + "favola",
600 + "febbre",
601 + "femmina",
602 + "femore",
603 + "fenomeno",
604 + "fermata",
605 + "feromoni",
606 + "ferrari",
607 + "fessura",
608 + "festa",
609 + "fiaba",
610 + "fiamma",
611 + "fianco",
612 + "fiat",
613 + "fibbia",
614 + "fidare",
615 + "fieno",
616 + "figa",
617 + "figlio",
618 + "figura",
619 + "filetto",
620 + "filmato",
621 + "filosofo",
622 + "filtrare",
623 + "finanza",
624 + "finestra",
625 + "fingere",
626 + "finire",
627 + "finta",
628 + "finzione",
629 + "fiocco",
630 + "fioraio",
631 + "firewall",
632 + "firmare",
633 + "fisico",
634 + "fissare",
635 + "fittizio",
636 + "fiume",
637 + "flacone",
638 + "flagello",
639 + "flirtare",
640 + "flusso",
641 + "focaccia",
642 + "foglio",
643 + "fognario",
644 + "follia",
645 + "fonderia",
646 + "fontana",
647 + "forbici",
648 + "forcella",
649 + "foresta",
650 + "forgiare",
651 + "formare",
652 + "fornace",
653 + "foro",
654 + "fortuna",
655 + "forzare",
656 + "fosforo",
657 + "fotoni",
658 + "fracasso",
659 + "fragola",
660 + "frantumi",
661 + "fratello",
662 + "frazione",
663 + "freccia",
664 + "freddo",
665 + "frenare",
666 + "fresco",
667 + "friggere",
668 + "frittata",
669 + "frivolo",
670 + "frizione",
671 + "fronte",
672 + "frullato",
673 + "frumento",
674 + "frusta",
675 + "frutto",
676 + "fucile",
677 + "fuggire",
678 + "fulmine",
679 + "fumare",
680 + "funzione",
681 + "fuoco",
682 + "furbizia",
683 + "furgone",
684 + "furia",
685 + "furore",
686 + "fusibile",
687 + "fuso",
688 + "futuro",
689 + "gabbiano",
690 + "galassia",
691 + "gallina",
692 + "gamba",
693 + "gancio",
694 + "garanzia",
695 + "garofano",
696 + "gasolio",
697 + "gatto",
698 + "gazebo",
699 + "gazzetta",
700 + "gelato",
701 + "gemelli",
702 + "generare",
703 + "genitori",
704 + "gennaio",
705 + "geologia",
706 + "germania",
707 + "gestire",
708 + "gettare",
709 + "ghepardo",
710 + "ghiaccio",
711 + "giaccone",
712 + "giaguaro",
713 + "giallo",
714 + "giappone",
715 + "giardino",
716 + "gigante",
717 + "gioco",
718 + "gioiello",
719 + "giorno",
720 + "giovane",
721 + "giraffa",
722 + "giudizio",
723 + "giurare",
724 + "giusto",
725 + "globo",
726 + "gloria",
727 + "glucosio",
728 + "gnocca",
729 + "gocciola",
730 + "godere",
731 + "gomito",
732 + "gomma",
733 + "gonfiare",
734 + "gorilla",
735 + "governo",
736 + "gradire",
737 + "graffiti",
738 + "granchio",
739 + "grappolo",
740 + "grasso",
741 + "grattare",
742 + "gridare",
743 + "grissino",
744 + "grondaia",
745 + "grugnito",
746 + "gruppo",
747 + "guadagno",
748 + "guaio",
749 + "guancia",
750 + "guardare",
751 + "gufo",
752 + "guidare",
753 + "guscio",
754 + "gusto",
755 + "icona",
756 + "idea",
757 + "identico",
758 + "idolo",
759 + "idoneo",
760 + "idrante",
761 + "idrogeno",
762 + "igiene",
763 + "ignoto",
764 + "imbarco",
765 + "immagine",
766 + "immobile",
767 + "imparare",
768 + "impedire",
769 + "impianto",
770 + "importo",
771 + "impresa",
772 + "impulso",
773 + "incanto",
774 + "incendio",
775 + "incidere",
776 + "incontro",
777 + "incrocia",
778 + "incubo",
779 + "indagare",
780 + "indice",
781 + "indotto",
782 + "infanzia",
783 + "inferno",
784 + "infinito",
785 + "infranto",
786 + "ingerire",
787 + "inglese",
788 + "ingoiare",
789 + "ingresso",
790 + "iniziare",
791 + "innesco",
792 + "insalata",
793 + "inserire",
794 + "insicuro",
795 + "insonnia",
796 + "insulto",
797 + "interno",
798 + "introiti",
799 + "invasori",
800 + "inverno",
801 + "invito",
802 + "invocare",
803 + "ipnosi",
804 + "ipocrita",
805 + "ipotesi",
806 + "ironia",
807 + "irrigare",
808 + "iscritto",
809 + "isola",
810 + "ispirare",
811 + "isterico",
812 + "istinto",
813 + "istruire",
814 + "italiano",
815 + "jazz",
816 + "labbra",
817 + "labrador",
818 + "ladro",
819 + "lago",
820 + "lamento",
821 + "lampone",
822 + "lancetta",
823 + "lanterna",
824 + "lapide",
825 + "larva",
826 + "lasagne",
827 + "lasciare",
828 + "lastra",
829 + "latte",
830 + "laurea",
831 + "lavagna",
832 + "lavorare",
833 + "leccare",
834 + "legare",
835 + "leggere",
836 + "lenzuolo",
837 + "leone",
838 + "lepre",
839 + "letargo",
840 + "lettera",
841 + "levare",
842 + "levitare",
843 + "lezione",
844 + "liberare",
845 + "libidine",
846 + "libro",
847 + "licenza",
848 + "lievito",
849 + "limite",
850 + "lince",
851 + "lingua",
852 + "liquore",
853 + "lire",
854 + "listino",
855 + "litigare",
856 + "litro",
857 + "locale",
858 + "lottare",
859 + "lucciola",
860 + "lucidare",
861 + "luglio",
862 + "luna",
863 + "macchina",
864 + "madama",
865 + "madre",
866 + "maestro",
867 + "maggio",
868 + "magico",
869 + "maglione",
870 + "magnolia",
871 + "mago",
872 + "maialino",
873 + "maionese",
874 + "malattia",
875 + "male",
876 + "malloppo",
877 + "mancare",
878 + "mandorla",
879 + "mangiare",
880 + "manico",
881 + "manopola",
882 + "mansarda",
883 + "mantello",
884 + "manubrio",
885 + "manzo",
886 + "mappa",
887 + "mare",
888 + "margine",
889 + "marinaio",
890 + "marmotta",
891 + "marocco",
892 + "martello",
893 + "marzo",
894 + "maschera",
895 + "matrice",
896 + "maturare",
897 + "mazzetta",
898 + "meandri",
899 + "medaglia",
900 + "medico",
901 + "medusa",
902 + "megafono",
903 + "melone",
904 + "membrana",
905 + "menta",
906 + "mercato",
907 + "meritare",
908 + "merluzzo",
909 + "mese",
910 + "mestiere",
911 + "metafora",
912 + "meteo",
913 + "metodo",
914 + "mettere",
915 + "miele",
916 + "miglio",
917 + "miliardo",
918 + "mimetica",
919 + "minatore",
920 + "minuto",
921 + "miracolo",
922 + "mirtillo",
923 + "missile",
924 + "mistero",
925 + "misura",
926 + "mito",
927 + "mobile",
928 + "moda",
929 + "moderare",
930 + "moglie",
931 + "molecola",
932 + "molle",
933 + "momento",
934 + "moneta",
935 + "mongolia",
936 + "monologo",
937 + "montagna",
938 + "morale",
939 + "morbillo",
940 + "mordere",
941 + "mosaico",
942 + "mosca",
943 + "mostro",
944 + "motivare",
945 + "moto",
946 + "mulino",
947 + "mulo",
948 + "muovere",
949 + "muraglia",
950 + "muscolo",
951 + "museo",
952 + "musica",
953 + "mutande",
954 + "nascere",
955 + "nastro",
956 + "natale",
957 + "natura",
958 + "nave",
959 + "navigare",
960 + "negare",
961 + "negozio",
962 + "nemico",
963 + "nero",
964 + "nervo",
965 + "nessuno",
966 + "nettare",
967 + "neutroni",
968 + "neve",
969 + "nevicare",
970 + "nicotina",
971 + "nido",
972 + "nipote",
973 + "nocciola",
974 + "noleggio",
975 + "nome",
976 + "nonno",
977 + "norvegia",
978 + "notare",
979 + "notizia",
980 + "nove",
981 + "nucleo",
982 + "nuda",
983 + "nuotare",
984 + "nutrire",
985 + "obbligo",
986 + "occhio",
987 + "occupare",
988 + "oceano",
989 + "odissea",
990 + "odore",
991 + "offerta",
992 + "officina",
993 + "offrire",
994 + "oggetto",
995 + "oggi",
996 + "olfatto",
997 + "olio",
998 + "oliva",
999 + "ombelico",
1000 + "ombrello",
1001 + "omuncolo",
1002 + "ondata",
1003 + "onore",
1004 + "opera",
1005 + "opinione",
1006 + "opuscolo",
1007 + "opzione",
1008 + "orario",
1009 + "orbita",
1010 + "orchidea",
1011 + "ordine",
1012 + "orecchio",
1013 + "orgasmo",
1014 + "orgoglio",
1015 + "origine",
1016 + "orologio",
1017 + "oroscopo",
1018 + "orso",
1019 + "oscurare",
1020 + "ospedale",
1021 + "ospite",
1022 + "ossigeno",
1023 + "ostacolo",
1024 + "ostriche",
1025 + "ottenere",
1026 + "ottimo",
1027 + "ottobre",
1028 + "ovest",
1029 + "pacco",
1030 + "pace",
1031 + "pacifico",
1032 + "padella",
1033 + "pagare",
1034 + "pagina",
1035 + "pagnotta",
1036 + "palazzo",
1037 + "palestra",
1038 + "palpebre",
1039 + "pancetta",
1040 + "panfilo",
1041 + "panino",
1042 + "pannello",
1043 + "panorama",
1044 + "papa",
1045 + "paperino",
1046 + "paradiso",
1047 + "parcella",
1048 + "parente",
1049 + "parlare",
1050 + "parodia",
1051 + "parrucca",
1052 + "partire",
1053 + "passare",
1054 + "pasta",
1055 + "patata",
1056 + "patente",
1057 + "patogeno",
1058 + "patriota",
1059 + "pausa",
1060 + "pazienza",
1061 + "peccare",
1062 + "pecora",
1063 + "pedalare",
1064 + "pelare",
1065 + "pena",
1066 + "pendenza",
1067 + "penisola",
1068 + "pennello",
1069 + "pensare",
1070 + "pentirsi",
1071 + "percorso",
1072 + "perdono",
1073 + "perfetto",
1074 + "perizoma",
1075 + "perla",
1076 + "permesso",
1077 + "persona",
1078 + "pesare",
1079 + "pesce",
1080 + "peso",
1081 + "petardo",
1082 + "petrolio",
1083 + "pezzo",
1084 + "piacere",
1085 + "pianeta",
1086 + "piastra",
1087 + "piatto",
1088 + "piazza",
1089 + "piccolo",
1090 + "piede",
1091 + "piegare",
1092 + "pietra",
1093 + "pigiama",
1094 + "pigliare",
1095 + "pigrizia",
1096 + "pilastro",
1097 + "pilota",
1098 + "pinguino",
1099 + "pioggia",
1100 + "piombo",
1101 + "pionieri",
1102 + "piovra",
1103 + "pipa",
1104 + "pirata",
1105 + "pirolisi",
1106 + "piscina",
1107 + "pisolino",
1108 + "pista",
1109 + "pitone",
1110 + "piumino",
1111 + "pizza",
1112 + "plastica",
1113 + "platino",
1114 + "poesia",
1115 + "poiana",
1116 + "polaroid",
1117 + "polenta",
1118 + "polimero",
1119 + "pollo",
1120 + "polmone",
1121 + "polpetta",
1122 + "poltrona",
1123 + "pomodoro",
1124 + "pompa",
1125 + "popolo",
1126 + "porco",
1127 + "porta",
1128 + "porzione",
1129 + "possesso",
1130 + "postino",
1131 + "potassio",
1132 + "potere",
1133 + "poverino",
1134 + "pranzo",
1135 + "prato",
1136 + "prefisso",
1137 + "prelievo",
1138 + "premio",
1139 + "prendere",
1140 + "prestare",
1141 + "pretesa",
1142 + "prezzo",
1143 + "primario",
1144 + "privacy",
1145 + "problema",
1146 + "processo",
1147 + "prodotto",
1148 + "profeta",
1149 + "progetto",
1150 + "promessa",
1151 + "pronto",
1152 + "proposta",
1153 + "proroga",
1154 + "prossimo",
1155 + "proteina",
1156 + "prova",
1157 + "prudenza",
1158 + "pubblico",
1159 + "pudore",
1160 + "pugilato",
1161 + "pulire",
1162 + "pulsante",
1163 + "puntare",
1164 + "pupazzo",
1165 + "puzzle",
1166 + "quaderno",
1167 + "qualcuno",
1168 + "quarzo",
1169 + "quercia",
1170 + "quintale",
1171 + "rabbia",
1172 + "racconto",
1173 + "radice",
1174 + "raffica",
1175 + "ragazza",
1176 + "ragione",
1177 + "rammento",
1178 + "ramo",
1179 + "rana",
1180 + "randagio",
1181 + "rapace",
1182 + "rapinare",
1183 + "rapporto",
1184 + "rasatura",
1185 + "ravioli",
1186 + "reagire",
1187 + "realista",
1188 + "reattore",
1189 + "reazione",
1190 + "recitare",
1191 + "recluso",
1192 + "record",
1193 + "recupero",
1194 + "redigere",
1195 + "regalare",
1196 + "regina",
1197 + "regola",
1198 + "relatore",
1199 + "reliquia",
1200 + "remare",
1201 + "rendere",
1202 + "reparto",
1203 + "resina",
1204 + "resto",
1205 + "rete",
1206 + "retorica",
1207 + "rettile",
1208 + "revocare",
1209 + "riaprire",
1210 + "ribadire",
1211 + "ribelle",
1212 + "ricambio",
1213 + "ricetta",
1214 + "richiamo",
1215 + "ricordo",
1216 + "ridurre",
1217 + "riempire",
1218 + "riferire",
1219 + "riflesso",
1220 + "righello",
1221 + "rilancio",
1222 + "rilevare",
1223 + "rilievo",
1224 + "rimanere",
1225 + "rimborso",
1226 + "rinforzo",
1227 + "rinuncia",
1228 + "riparo",
1229 + "ripetere",
1230 + "riposare",
1231 + "ripulire",
1232 + "risalita",
1233 + "riscatto",
1234 + "riserva",
1235 + "riso",
1236 + "rispetto",
1237 + "ritaglio",
1238 + "ritmo",
1239 + "ritorno",
1240 + "ritratto",
1241 + "rituale",
1242 + "riunione",
1243 + "riuscire",
1244 + "riva",
1245 + "robotica",
1246 + "rondine",
1247 + "rosa",
1248 + "rospo",
1249 + "rosso",
1250 + "rotonda",
1251 + "rotta",
1252 + "roulotte",
1253 + "rubare",
1254 + "rubrica",
1255 + "ruffiano",
1256 + "rumore",
1257 + "ruota",
1258 + "ruscello",
1259 + "sabbia",
1260 + "sacco",
1261 + "saggio",
1262 + "sale",
1263 + "salire",
1264 + "salmone",
1265 + "salto",
1266 + "salutare",
1267 + "salvia",
1268 + "sangue",
1269 + "sanzioni",
1270 + "sapere",
1271 + "sapienza",
1272 + "sarcasmo",
1273 + "sardine",
1274 + "sartoria",
1275 + "sbalzo",
1276 + "sbarcare",
1277 + "sberla",
1278 + "sborsare",
1279 + "scadenza",
1280 + "scafo",
1281 + "scala",
1282 + "scambio",
1283 + "scappare",
1284 + "scarpa",
1285 + "scatola",
1286 + "scelta",
1287 + "scena",
1288 + "sceriffo",
1289 + "scheggia",
1290 + "schiuma",
1291 + "sciarpa",
1292 + "scienza",
1293 + "scimmia",
1294 + "sciopero",
1295 + "scivolo",
1296 + "sclerare",
1297 + "scolpire",
1298 + "sconto",
1299 + "scopa",
1300 + "scordare",
1301 + "scossa",
1302 + "scrivere",
1303 + "scrupolo",
1304 + "scuderia",
1305 + "scultore",
1306 + "scuola",
1307 + "scusare",
1308 + "sdraiare",
1309 + "secolo",
1310 + "sedativo",
1311 + "sedere",
1312 + "sedia",
1313 + "segare",
1314 + "segreto",
1315 + "seguire",
1316 + "semaforo",
1317 + "seme",
1318 + "senape",
1319 + "seno",
1320 + "sentiero",
1321 + "separare",
1322 + "sepolcro",
1323 + "sequenza",
1324 + "serata",
1325 + "serpente",
1326 + "servizio",
1327 + "sesso",
1328 + "seta",
1329 + "settore",
1330 + "sfamare",
1331 + "sfera",
1332 + "sfidare",
1333 + "sfiorare",
1334 + "sfogare",
1335 + "sgabello",
1336 + "sicuro",
1337 + "siepe",
1338 + "sigaro",
1339 + "silenzio",
1340 + "silicone",
1341 + "simbiosi",
1342 + "simpatia",
1343 + "simulare",
1344 + "sinapsi",
1345 + "sindrome",
1346 + "sinergia",
1347 + "sinonimo",
1348 + "sintonia",
1349 + "sirena",
1350 + "siringa",
1351 + "sistema",
1352 + "sito",
1353 + "smalto",
1354 + "smentire",
1355 + "smontare",
1356 + "soccorso",
1357 + "socio",
1358 + "soffitto",
1359 + "software",
1360 + "soggetto",
1361 + "sogliola",
1362 + "sognare",
1363 + "soldi",
1364 + "sole",
1365 + "sollievo",
1366 + "solo",
1367 + "sommario",
1368 + "sondare",
1369 + "sonno",
1370 + "sorpresa",
1371 + "sorriso",
1372 + "sospiro",
1373 + "sostegno",
1374 + "sovrano",
1375 + "spaccare",
1376 + "spada",
1377 + "spagnolo",
1378 + "spalla",
1379 + "sparire",
1380 + "spavento",
1381 + "spazio",
1382 + "specchio",
1383 + "spedire",
1384 + "spegnere",
1385 + "spendere",
1386 + "speranza",
1387 + "spessore",
1388 + "spezzare",
1389 + "spiaggia",
1390 + "spiccare",
1391 + "spiegare",
1392 + "spiffero",
1393 + "spingere",
1394 + "sponda",
1395 + "sporcare",
1396 + "spostare",
1397 + "spremuta",
1398 + "spugna",
1399 + "spumante",
1400 + "spuntare",
1401 + "squadra",
1402 + "squillo",
1403 + "staccare",
1404 + "stadio",
1405 + "stagione",
1406 + "stallone",
1407 + "stampa",
1408 + "stancare",
1409 + "starnuto",
1410 + "statura",
1411 + "stella",
1412 + "stendere",
1413 + "sterzo",
1414 + "stilista",
1415 + "stimolo",
1416 + "stinco",
1417 + "stiva",
1418 + "stoffa",
1419 + "storia",
1420 + "strada",
1421 + "stregone",
1422 + "striscia",
1423 + "studiare",
1424 + "stufa",
1425 + "stupendo",
1426 + "subire",
1427 + "successo",
1428 + "sudare",
1429 + "suono",
1430 + "superare",
1431 + "supporto",
1432 + "surfista",
1433 + "sussurro",
1434 + "svelto",
1435 + "svenire",
1436 + "sviluppo",
1437 + "svolta",
1438 + "svuotare",
1439 + "tabacco",
1440 + "tabella",
1441 + "tabu",
1442 + "tacchino",
1443 + "tacere",
1444 + "taglio",
1445 + "talento",
1446 + "tangente",
1447 + "tappeto",
1448 + "tartufo",
1449 + "tassello",
1450 + "tastiera",
1451 + "tavolo",
1452 + "tazza",
1453 + "teatro",
1454 + "tedesco",
1455 + "telaio",
1456 + "telefono",
1457 + "tema",
1458 + "temere",
1459 + "tempo",
1460 + "tendenza",
1461 + "tenebre",
1462 + "tensione",
1463 + "tentare",
1464 + "teologia",
1465 + "teorema",
1466 + "termica",
1467 + "terrazzo",
1468 + "teschio",
1469 + "tesi",
1470 + "tesoro",
1471 + "tessera",
1472 + "testa",
1473 + "thriller",
1474 + "tifoso",
1475 + "tigre",
1476 + "timbrare",
1477 + "timido",
1478 + "tinta",
1479 + "tirare",
1480 + "tisana",
1481 + "titano",
1482 + "titolo",
1483 + "toccare",
1484 + "togliere",
1485 + "topolino",
1486 + "torcia",
1487 + "torrente",
1488 + "tovaglia",
1489 + "traffico",
1490 + "tragitto",
1491 + "training",
1492 + "tramonto",
1493 + "transito",
1494 + "trapezio",
1495 + "trasloco",
1496 + "trattore",
1497 + "trazione",
1498 + "treccia",
1499 + "tregua",
1500 + "treno",
1501 + "triciclo",
1502 + "tridente",
1503 + "trilogia",
1504 + "tromba",
1505 + "troncare",
1506 + "trota",
1507 + "trovare",
1508 + "trucco",
1509 + "tubo",
1510 + "tulipano",
1511 + "tumulto",
1512 + "tunisia",
1513 + "tuono",
1514 + "turista",
1515 + "tuta",
1516 + "tutelare",
1517 + "tutore",
1518 + "ubriaco",
1519 + "uccello",
1520 + "udienza",
1521 + "udito",
1522 + "uffa",
1523 + "umanoide",
1524 + "umore",
1525 + "unghia",
1526 + "unguento",
1527 + "unicorno",
1528 + "unione",
1529 + "universo",
1530 + "uomo",
1531 + "uragano",
1532 + "uranio",
1533 + "urlare",
1534 + "uscire",
1535 + "utente",
1536 + "utilizzo",
1537 + "vacanza",
1538 + "vacca",
1539 + "vaglio",
1540 + "vagonata",
1541 + "valle",
1542 + "valore",
1543 + "valutare",
1544 + "valvola",
1545 + "vampiro",
1546 + "vaniglia",
1547 + "vanto",
1548 + "vapore",
1549 + "variante",
1550 + "vasca",
1551 + "vaselina",
1552 + "vassoio",
1553 + "vedere",
1554 + "vegetale",
1555 + "veglia",
1556 + "veicolo",
1557 + "vela",
1558 + "veleno",
1559 + "velivolo",
1560 + "velluto",
1561 + "vendere",
1562 + "venerare",
1563 + "venire",
1564 + "vento",
1565 + "veranda",
1566 + "verbo",
1567 + "verdura",
1568 + "vergine",
1569 + "verifica",
1570 + "vernice",
1571 + "vero",
1572 + "verruca",
1573 + "versare",
1574 + "vertebra",
1575 + "vescica",
1576 + "vespaio",
1577 + "vestito",
1578 + "vesuvio",
1579 + "veterano",
1580 + "vetro",
1581 + "vetta",
1582 + "viadotto",
1583 + "viaggio",
1584 + "vibrare",
1585 + "vicenda",
1586 + "vichingo",
1587 + "vietare",
1588 + "vigilare",
1589 + "vigneto",
1590 + "villa",
1591 + "vincere",
1592 + "violino",
1593 + "vipera",
1594 + "virgola",
1595 + "virtuoso",
1596 + "visita",
1597 + "vita",
1598 + "vitello",
1599 + "vittima",
1600 + "vivavoce",
1601 + "vivere",
1602 + "viziato",
1603 + "voglia",
1604 + "volare",
1605 + "volpe",
1606 + "volto",
1607 + "volume",
1608 + "vongole",
1609 + "voragine",
1610 + "vortice",
1611 + "votare",
1612 + "vulcano",
1613 + "vuotare",
1614 + "zabaione",
1615 + "zaffiro",
1616 + "zainetto",
1617 + "zampa",
1618 + "zanzara",
1619 + "zattera",
1620 + "zavorra",
1621 + "zenzero",
1622 + "zero",
1623 + "zingaro",
1624 + "zittire",
1625 + "zoccolo",
1626 + "zolfo",
1627 + "zombie",
1628 + "zucchero"
1629 + ];
1630 +}
cw_wownero/lib/mnemonics/japanese.dart
+1 -1
@@ -1627,4 +1627,4 @@ class JapaneseMnemonics {
1627 "びじゅつかん",
1628 "ひしょ"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_wownero/lib/mnemonics/portuguese.dart
+1 -1
@@ -1627,4 +1627,4 @@ class PortugueseMnemonics {
1627 "zenite",
1628 "zumbi"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_wownero/lib/mnemonics/russian.dart
+1 -1
@@ -1627,4 +1627,4 @@ class RussianMnemonics {
1627 "ячейка",
1628 "ящик"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_wownero/lib/mnemonics/spanish.dart
+1 -1
@@ -1627,4 +1627,4 @@ class SpanishMnemonics {
1627 "ritmo",
1628 "rito"
1629 ];
1630 -}
\ No newline at end of file
1630 +}
cw_wownero/lib/mywownero.dart
+3 -6
@@ -31,12 +31,9 @@ String mnemonicDecode(String seed) {
31 wlist.removeLast();
32
33 for (var i = 0; i < wlist.length; i += 3) {
34 - final w1 =
35 - tructWords(englistWordSet).indexOf(wlist[i].substring(0, prefixLength));
36 - final w2 = tructWords(englistWordSet)
37 - .indexOf(wlist[i + 1].substring(0, prefixLength));
38 - final w3 = tructWords(englistWordSet)
39 - .indexOf(wlist[i + 2].substring(0, prefixLength));
34 + final w1 = tructWords(englistWordSet).indexOf(wlist[i].substring(0, prefixLength));
35 + final w2 = tructWords(englistWordSet).indexOf(wlist[i + 1].substring(0, prefixLength));
36 + final w3 = tructWords(englistWordSet).indexOf(wlist[i + 2].substring(0, prefixLength));
37
38 if (w1 == -1 || w2 == -1 || w3 == -1) {
39 printV("invalid word in mnemonic");
cw_wownero/lib/pending_wownero_transaction.dart
+1 -1
@@ -48,7 +48,7 @@ class PendingWowneroTransaction with PendingTransaction {
48 rethrow;
49 }
50 }
51 -
51 +
52 @override
53 Future<Map<String, String>> commitUR() {
54 throw UnimplementedError();
cw_wownero/lib/wownero_subaddress_list.dart
+20 -27
@@ -56,14 +56,13 @@ abstract class WowneroSubaddressListBase with Store {
56 final address = s.address;
57 final label = s.label;
58 final id = s.addressIndex;
59 - final hasDefaultAddressName =
60 - label.toLowerCase() == 'Primary account'.toLowerCase() ||
61 - label.toLowerCase() == 'Untitled account'.toLowerCase();
59 + final hasDefaultAddressName = label.toLowerCase() == 'Primary account'.toLowerCase() ||
60 + label.toLowerCase() == 'Untitled account'.toLowerCase();
61 final isPrimaryAddress = id == 0 && hasDefaultAddressName;
62 return Subaddress(
63 id: id,
64 address: address,
66 - balance: (s.received/1e12).toStringAsFixed(6),
65 + balance: (s.received / 1e12).toStringAsFixed(6),
66 txCount: s.txCount,
67 label: isPrimaryAddress
68 ? 'Primary address'
@@ -139,33 +138,27 @@ abstract class WowneroSubaddressListBase with Store {
138 }
139 }
140
142 - return allAddresses
143 - .map((s) {
144 - final id = s.addressIndex;
145 - final address = s.address;
146 - final label = s.label;
147 - return Subaddress(
148 - id: id,
149 - address: address,
150 - balance: (s.received/1e12).toStringAsFixed(6),
151 - txCount: s.txCount,
152 - label: id == 0 &&
153 - label.toLowerCase() == 'Primary account'.toLowerCase()
154 - ? 'Primary address'
155 - : label);
156 - })
157 - .toList();
141 + return allAddresses.map((s) {
142 + final id = s.addressIndex;
143 + final address = s.address;
144 + final label = s.label;
145 + return Subaddress(
146 + id: id,
147 + address: address,
148 + balance: (s.received / 1e12).toStringAsFixed(6),
149 + txCount: s.txCount,
150 + label: id == 0 && label.toLowerCase() == 'Primary account'.toLowerCase()
151 + ? 'Primary address'
152 + : label);
153 + }).toList();
154 }
155
156 Future<bool> _newSubaddress({required int accountIndex, required String label}) async {
157 await subaddress_list.addSubaddress(accountIndex: accountIndex, label: label);
158
163 - return subaddress_list
164 - .getAllSubaddresses()
165 - .where((s) {
166 - final address = s.address;
167 - return !_usedAddresses.contains(address);
168 - })
169 - .isNotEmpty;
159 + return subaddress_list.getAllSubaddresses().where((s) {
160 + final address = s.address;
161 + return !_usedAddresses.contains(address);
162 + }).isNotEmpty;
163 }
164 }
cw_wownero/lib/wownero_transaction_history.dart
+4 -7
@@ -5,11 +5,10 @@ import 'package:cw_wownero/wownero_transaction_info.dart';
5
6 part 'wownero_transaction_history.g.dart';
7
8 -class WowneroTransactionHistory = WowneroTransactionHistoryBase
9 - with _$WowneroTransactionHistory;
8 +class WowneroTransactionHistory = WowneroTransactionHistoryBase with _$WowneroTransactionHistory;
9
11 -abstract class WowneroTransactionHistoryBase
12 - extends TransactionHistoryBase<WowneroTransactionInfo> with Store {
10 +abstract class WowneroTransactionHistoryBase extends TransactionHistoryBase<WowneroTransactionInfo>
11 + with Store {
12 WowneroTransactionHistoryBase() {
13 transactions = ObservableMap<String, WowneroTransactionInfo>();
14 }
@@ -18,11 +17,9 @@ abstract class WowneroTransactionHistoryBase
17 Future<void> save() async {}
18
19 @override
21 - void addOne(WowneroTransactionInfo transaction) =>
22 - transactions[transaction.id] = transaction;
20 + void addOne(WowneroTransactionInfo transaction) => transactions[transaction.id] = transaction;
21
22 @override
23 void addMany(Map<String, WowneroTransactionInfo> transactions) =>
24 this.transactions.addAll(transactions);
27 -
25 }
cw_wownero/lib/wownero_transaction_info.dart
+3 -4
@@ -8,10 +8,9 @@ import 'package:cw_core/format_amount.dart';
8 import 'package:cw_wownero/api/transaction_history.dart';
9
10 class WowneroTransactionInfo extends TransactionInfo {
11 - WowneroTransactionInfo(this.txHash, this.height, this.direction, this.date,
12 - this.isPending, this.amount, this.accountIndex, this.addressIndex, this.fee,
13 - this.confirmations) :
14 - id = "${txHash}_${amount}_${accountIndex}_${addressIndex}";
11 + WowneroTransactionInfo(this.txHash, this.height, this.direction, this.date, this.isPending,
12 + this.amount, this.accountIndex, this.addressIndex, this.fee, this.confirmations)
13 + : id = "${txHash}_${amount}_${accountIndex}_${addressIndex}";
14
15 WowneroTransactionInfo.fromMap(Map<String, Object?> map)
16 : id = "${map['hash']}_${map['amount']}_${map['accountIndex']}_${map['addressIndex']}",
cw_wownero/lib/wownero_wallet.dart
+7 -5
@@ -54,7 +54,10 @@ abstract class WowneroWalletBase
54 extends WalletBase<WowneroBalance, WowneroTransactionHistory, WowneroTransactionInfo>
55 with Store {
56 WowneroWalletBase(
57 - {required WalletInfo walletInfo, required DerivationInfo derivationInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo, required String password})
57 + {required WalletInfo walletInfo,
58 + required DerivationInfo derivationInfo,
59 + required Box<UnspentCoinsInfo> unspentCoinsInfo,
60 + required String password})
61 : balance = ObservableMap<CryptoCurrency, WowneroBalance>.of({
62 CryptoCurrency.wow: WowneroBalance(
63 fullBalance:
@@ -144,8 +147,8 @@ abstract class WowneroWalletBase
147 passphrase: wownero_wallet.getPassphrase());
148
149 int? get restoreHeight =>
147 - transactionHistory.transactions.values.firstOrNull?.height ?? wownero.Wallet_getRefreshFromBlockHeight(wptr!);
148 -
150 + transactionHistory.transactions.values.firstOrNull?.height ??
151 + wownero.Wallet_getRefreshFromBlockHeight(wptr!);
152
153 wownero_wallet.SyncListener? _listener;
154 ReactionDisposer? _onAccountChangeReaction;
@@ -635,8 +638,7 @@ abstract class WowneroWalletBase
638 wownero_wallet.getSubaddressLabel(accountIndex, addressIndex);
639
640 Future<List<WowneroTransactionInfo>> _getAllTransactionsOfAccount(int? accountIndex) async =>
638 - (await transaction_history
639 - .getAllTransactions())
641 + (await transaction_history.getAllTransactions())
642 .map(
643 (row) => WowneroTransactionInfo(
644 row.hash,
cw_wownero/lib/wownero_wallet_addresses.dart
+14 -10
@@ -34,25 +34,26 @@ abstract class WowneroWalletAddressesBase extends WalletAddresses with Store {
34
35 @override
36 String get latestAddress {
37 - var addressIndex = subaddress_list.numSubaddresses(account?.id??0) - 1;
38 - var address = getAddress(accountIndex: account?.id??0, addressIndex: addressIndex);
37 + var addressIndex = subaddress_list.numSubaddresses(account?.id ?? 0) - 1;
38 + var address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
39 while (hiddenAddresses.contains(address)) {
40 addressIndex++;
41 - address = getAddress(accountIndex: account?.id??0, addressIndex: addressIndex);
41 + address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
42 }
43 return address;
44 }
45
46 @override
47 String get addressForExchange {
48 - var addressIndex = subaddress_list.numSubaddresses(account?.id??0) - 1;
49 - var address = getAddress(accountIndex: account?.id??0, addressIndex: addressIndex);
48 + var addressIndex = subaddress_list.numSubaddresses(account?.id ?? 0) - 1;
49 + var address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
50 while (hiddenAddresses.contains(address) || manualAddresses.contains(address)) {
51 addressIndex++;
52 - address = getAddress(accountIndex: account?.id??0, addressIndex: addressIndex);
52 + address = getAddress(accountIndex: account?.id ?? 0, addressIndex: addressIndex);
53 }
54 return address;
55 }
56 +
57 @observable
58 Account? account;
59
@@ -69,7 +70,9 @@ abstract class WowneroWalletAddressesBase extends WalletAddresses with Store {
70 @override
71 Future<void> init() async {
72 accountList.update();
72 - account = accountList.accounts.isEmpty ? Account(id: 0, label: "Primary address") : accountList.accounts.first;
73 + account = accountList.accounts.isEmpty
74 + ? Account(id: 0, label: "Primary address")
75 + : accountList.accounts.first;
76 updateSubaddressList(accountIndex: account?.id ?? 0);
77 await updateAddressesInBox();
78 }
@@ -143,7 +146,9 @@ abstract class WowneroWalletAddressesBase extends WalletAddresses with Store {
146 accountIndex: accountIndex,
147 defaultLabel: defaultLabel,
148 usedAddresses: usedAddresses.toList());
146 - subaddress = (subaddressList.subaddresses.isEmpty) ? Subaddress(id: 0, address: address, label: defaultLabel, balance: '0', txCount: 0) : subaddressList.subaddresses.last;
149 + subaddress = (subaddressList.subaddresses.isEmpty)
150 + ? Subaddress(id: 0, address: address, label: defaultLabel, balance: '0', txCount: 0)
151 + : subaddressList.subaddresses.last;
152 address = subaddress!.address;
153 }
154
@@ -152,6 +157,5 @@ abstract class WowneroWalletAddressesBase extends WalletAddresses with Store {
157 addressInfos[account?.id ?? 0]?.any((it) => it.address == address) ?? false;
158
159 @override
155 - PaymentURI getPaymentUri(String amount) =>
156 - WowneroURI(address: address, amount: amount);
160 + PaymentURI getPaymentUri(String amount) => WowneroURI(address: address, amount: amount);
161 }
cw_wownero/lib/wownero_wallet_service.dart
+54 -22
@@ -23,7 +23,11 @@ import 'package:monero/wownero.dart' as wownero;
23
24 class WowneroNewWalletCredentials extends WalletCredentials {
25 WowneroNewWalletCredentials(
26 - {required String name, required this.language, required this.isPolyseed, this.passphrase, String? password})
26 + {required String name,
27 + required this.language,
28 + required this.isPolyseed,
29 + this.passphrase,
30 + String? password})
31 : super(name: name, password: password);
32
33 final String language;
@@ -33,7 +37,11 @@ class WowneroNewWalletCredentials extends WalletCredentials {
37
38 class WowneroRestoreWalletFromSeedCredentials extends WalletCredentials {
39 WowneroRestoreWalletFromSeedCredentials(
36 - {required String name, required this.mnemonic, required this.passphrase, int height = 0, String? password})
40 + {required String name,
41 + required this.mnemonic,
42 + required this.passphrase,
43 + int height = 0,
44 + String? password})
45 : super(name: name, password: password, height: height);
46
47 final String mnemonic;
@@ -97,9 +105,15 @@ class WowneroWalletService extends WalletService<
105 }
106
107 await wownero_wallet_manager.createWallet(
100 - path: path, password: credentials.password!, language: credentials.language, passphrase: credentials.passphrase??'');
108 + path: path,
109 + password: credentials.password!,
110 + language: credentials.language,
111 + passphrase: credentials.passphrase ?? '');
112 final wallet = WowneroWallet(
102 - walletInfo: credentials.walletInfo!, derivationInfo: await credentials.walletInfo!.getDerivationInfo(), unspentCoinsInfo: unspentCoinsInfoSource, password: credentials.password!);
113 + walletInfo: credentials.walletInfo!,
114 + derivationInfo: await credentials.walletInfo!.getDerivationInfo(),
115 + unspentCoinsInfo: unspentCoinsInfoSource,
116 + password: credentials.password!);
117 await wallet.init();
118
119 return wallet;
@@ -138,7 +152,11 @@ class WowneroWalletService extends WalletService<
152 throw Exception('Wallet not found');
153 }
154
141 - wallet = WowneroWallet(walletInfo: walletInfo, derivationInfo: await walletInfo.getDerivationInfo(), unspentCoinsInfo: unspentCoinsInfoSource, password: password);
155 + wallet = WowneroWallet(
156 + walletInfo: walletInfo,
157 + derivationInfo: await walletInfo.getDerivationInfo(),
158 + unspentCoinsInfo: unspentCoinsInfoSource,
159 + password: password);
160 throw WalletDeprecationException(seed: wallet.seed, curr: wallet.currency);
161
162 final isValid = wallet.walletAddresses.validate();
@@ -224,7 +242,11 @@ class WowneroWalletService extends WalletService<
242 if (currentWalletInfo == null) {
243 throw Exception('Wallet not found');
244 }
227 - final currentWallet = WowneroWallet(walletInfo: currentWalletInfo, derivationInfo: await currentWalletInfo.getDerivationInfo(), unspentCoinsInfo: unspentCoinsInfoSource, password: password);
245 + final currentWallet = WowneroWallet(
246 + walletInfo: currentWalletInfo,
247 + derivationInfo: await currentWalletInfo.getDerivationInfo(),
248 + unspentCoinsInfo: unspentCoinsInfoSource,
249 + password: password);
250
251 await currentWallet.renameWalletFiles(newName);
252
@@ -249,7 +271,10 @@ class WowneroWalletService extends WalletService<
271 viewKey: credentials.viewKey,
272 spendKey: credentials.spendKey);
273 final wallet = WowneroWallet(
252 - walletInfo: credentials.walletInfo!, derivationInfo: await credentials.walletInfo!.getDerivationInfo(), unspentCoinsInfo: unspentCoinsInfoSource, password: credentials.password!);
274 + walletInfo: credentials.walletInfo!,
275 + derivationInfo: await credentials.walletInfo!.getDerivationInfo(),
276 + unspentCoinsInfo: unspentCoinsInfoSource,
277 + password: credentials.password!);
278 await wallet.init();
279
280 return wallet;
@@ -283,7 +308,10 @@ class WowneroWalletService extends WalletService<
308 seed: credentials.mnemonic,
309 restoreHeight: credentials.height!);
310 final wallet = WowneroWallet(
286 - walletInfo: credentials.walletInfo!, derivationInfo: await credentials.walletInfo!.getDerivationInfo(), unspentCoinsInfo: unspentCoinsInfoSource, password: credentials.password!);
311 + walletInfo: credentials.walletInfo!,
312 + derivationInfo: await credentials.walletInfo!.getDerivationInfo(),
313 + unspentCoinsInfo: unspentCoinsInfoSource,
314 + password: credentials.password!);
315 await wallet.init();
316
317 return wallet;
@@ -303,7 +331,8 @@ class WowneroWalletService extends WalletService<
331 final polyseed = Polyseed.decode(credentials.mnemonic, lang, polyseedCoin);
332
333 return _restoreFromPolyseed(
306 - path, credentials.password!, polyseed, credentials.walletInfo!, lang, passphrase: credentials.passphrase);
334 + path, credentials.password!, polyseed, credentials.walletInfo!, lang,
335 + passphrase: credentials.passphrase);
336 } catch (e) {
337 // TODO: Implement Exception for wallet list service.
338 printV('WowneroWalletsManager Error: $e');
@@ -313,20 +342,19 @@ class WowneroWalletService extends WalletService<
342
343 Future<WowneroWallet> _restoreFromPolyseed(
344 String path, String password, Polyseed polyseed, WalletInfo walletInfo, PolyseedLang lang,
316 - {PolyseedCoin coin = PolyseedCoin.POLYSEED_WOWNERO, int? overrideHeight, String? passphrase}) async {
317 -
318 -
319 - if (polyseed.isEncrypted == false &&
320 - (passphrase??'') != "") {
345 + {PolyseedCoin coin = PolyseedCoin.POLYSEED_WOWNERO,
346 + int? overrideHeight,
347 + String? passphrase}) async {
348 + if (polyseed.isEncrypted == false && (passphrase ?? '') != "") {
349 // Fallback to the different passphrase offset method, when a passphrase
350 // was provided but the polyseed is not encrypted.
351 wownero_wallet_manager.restoreWalletFromPolyseedWithOffset(
324 - path: path,
325 - password: password,
326 - seed: polyseed.encode(lang, coin),
327 - seedOffset: passphrase??'',
328 - language: "English");
329 -
352 + path: path,
353 + password: password,
354 + seed: polyseed.encode(lang, coin),
355 + seedOffset: passphrase ?? '',
356 + language: "English");
357 +
358 final wallet = WowneroWallet(
359 walletInfo: walletInfo,
360 derivationInfo: await walletInfo.getDerivationInfo(),
@@ -357,9 +385,13 @@ class WowneroWalletService extends WalletService<
385 spendKey: spendKey);
386
387 wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.seed", value: seed);
360 - wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase??'');
388 + wownero.Wallet_setCacheAttribute(wptr!, key: "cakewallet.passphrase", value: passphrase ?? '');
389
362 - final wallet = WowneroWallet(walletInfo: walletInfo, derivationInfo: await walletInfo.getDerivationInfo(), unspentCoinsInfo: unspentCoinsInfoSource, password: password);
390 + final wallet = WowneroWallet(
391 + walletInfo: walletInfo,
392 + derivationInfo: await walletInfo.getDerivationInfo(),
393 + unspentCoinsInfo: unspentCoinsInfoSource,
394 + password: password);
395 await wallet.init();
396
397 return wallet;
cw_zano/lib/api/consts.dart
+1 -1
@@ -3,4 +3,4 @@ class Consts {
3 static const errorAlreadyExists = 'ALREADY_EXISTS';
4 static const errorWalletWrongId = 'WALLET_WRONG_ID';
5 static const errorBusy = 'BUSY';
6 -}
\ No newline at end of file
6 +}
cw_zano/lib/api/model/asset_id_params.dart
+3 -3
@@ -4,6 +4,6 @@ class AssetIdParams {
4 AssetIdParams({required this.assetId});
5
6 Map<String, dynamic> toJson() => {
7 - 'asset_id': assetId,
8 - };
9 -}
\ No newline at end of file
7 + 'asset_id': assetId,
8 + };
9 +}
cw_zano/lib/api/model/balance.dart
+2 -3
@@ -15,15 +15,14 @@ class Balance {
15 required this.awaitingOut,
16 required this.total,
17 required this.unlocked});
18 -
18 +
19 String get assetId => assetInfo.assetId;
20
21 @override
22 String toString() => '$assetInfo: $total/$unlocked';
23
24 factory Balance.fromJson(Map<String, dynamic> json) => Balance(
25 - assetInfo:
26 - ZanoAsset.fromJson(json['asset_info'] as Map<String, dynamic>? ?? {}),
25 + assetInfo: ZanoAsset.fromJson(json['asset_info'] as Map<String, dynamic>? ?? {}),
26 awaitingIn: ZanoFormatter.bigIntFromDynamic(json['awaiting_in']),
27 awaitingOut: ZanoFormatter.bigIntFromDynamic(json['awaiting_out']),
28 total: ZanoFormatter.bigIntFromDynamic(json['total']),
cw_zano/lib/api/model/create_wallet_result.dart
+3 -4
@@ -30,12 +30,11 @@ class CreateWalletResult {
30 required this.publicSpendKey,
31 required this.publicViewKey});
32
33 - factory CreateWalletResult.fromJson(Map<String, dynamic> json) =>
34 - CreateWalletResult(
33 + factory CreateWalletResult.fromJson(Map<String, dynamic> json) => CreateWalletResult(
34 name: json['name'] as String? ?? '',
35 pass: json['pass'] as String? ?? '',
37 - recentHistory: RecentHistory.fromJson(
38 - json['recent_history'] as Map<String, dynamic>? ?? {}),
36 + recentHistory:
37 + RecentHistory.fromJson(json['recent_history'] as Map<String, dynamic>? ?? {}),
38 recovered: json['recovered'] as bool? ?? false,
39 walletFileSize: json['wallet_file_size'] as int? ?? 0,
40 walletId: json['wallet_id'] as int? ?? 0,
cw_zano/lib/api/model/destination.dart
+6 -7
@@ -1,10 +1,9 @@
1 class Destination {
2 - final BigInt amount; // transferred as string
2 + final BigInt amount; // transferred as string
3 final String address;
4 final String assetId;
5
6 - Destination(
7 - {required this.amount, required this.address, required this.assetId});
6 + Destination({required this.amount, required this.address, required this.assetId});
7
8 factory Destination.fromJson(Map<String, dynamic> json) => Destination(
9 amount: BigInt.parse(json['amount'] as String? ?? '0'),
@@ -13,8 +12,8 @@ class Destination {
12 );
13
14 Map<String, dynamic> toJson() => {
16 - 'amount': amount.toString(),
17 - 'address': address,
18 - 'asset_id': assetId,
19 - };
15 + 'amount': amount.toString(),
16 + 'address': address,
17 + 'asset_id': assetId,
18 + };
19 }
cw_zano/lib/api/model/employed_entries.dart
+11 -8
@@ -6,13 +6,16 @@ class EmployedEntries {
6
7 EmployedEntries({required this.receive, required this.send});
8
9 - factory EmployedEntries.fromJson(Map<String, dynamic> json) =>
10 - EmployedEntries(
11 - receive: json['receive'] == null ? [] : (json['receive'] as List<dynamic>)
12 - .map((e) => Receive.fromJson(e as Map<String, dynamic>))
13 - .toList(),
14 - send: json['spent'] == null ? [] : (json['spent'] as List<dynamic>)
15 - .map((e) => Receive.fromJson(e as Map<String, dynamic>))
16 - .toList(),
9 + factory EmployedEntries.fromJson(Map<String, dynamic> json) => EmployedEntries(
10 + receive: json['receive'] == null
11 + ? []
12 + : (json['receive'] as List<dynamic>)
13 + .map((e) => Receive.fromJson(e as Map<String, dynamic>))
14 + .toList(),
15 + send: json['spent'] == null
16 + ? []
17 + : (json['spent'] as List<dynamic>)
18 + .map((e) => Receive.fromJson(e as Map<String, dynamic>))
19 + .toList(),
20 );
21 }
cw_zano/lib/api/model/get_recent_txs_and_info_params.dart
+8 -7
@@ -3,12 +3,13 @@ class GetRecentTxsAndInfoParams {
3 final int count;
4 final bool updateProvisionInfo;
5
6 - GetRecentTxsAndInfoParams({required this.offset, required this.count, this.updateProvisionInfo = true});
6 + GetRecentTxsAndInfoParams(
7 + {required this.offset, required this.count, this.updateProvisionInfo = true});
8
9 Map<String, dynamic> toJson() => {
9 - 'offset': offset,
10 - 'count': count,
11 - 'update_provision_info': updateProvisionInfo,
12 - 'order': 'FROM_BEGIN_TO_END',
13 - };
14 -}
\ No newline at end of file
10 + 'offset': offset,
11 + 'count': count,
12 + 'update_provision_info': updateProvisionInfo,
13 + 'order': 'FROM_BEGIN_TO_END',
14 + };
15 +}
cw_zano/lib/api/model/get_recent_txs_and_info_result.dart
+7 -4
@@ -5,8 +5,11 @@ class GetRecentTxsAndInfoResult {
5 final int lastItemIndex;
6 final int totalTransfers;
7
8 - GetRecentTxsAndInfoResult({required this.transfers, required this.lastItemIndex, required this.totalTransfers});
9 -
10 - GetRecentTxsAndInfoResult.empty(): this.transfers = [], this.lastItemIndex = 0, this.totalTransfers = 0;
8 + GetRecentTxsAndInfoResult(
9 + {required this.transfers, required this.lastItemIndex, required this.totalTransfers});
10
12 -}
\ No newline at end of file
11 + GetRecentTxsAndInfoResult.empty()
12 + : this.transfers = [],
13 + this.lastItemIndex = 0,
14 + this.totalTransfers = 0;
15 +}
cw_zano/lib/api/model/get_wallet_status_result.dart
+1 -2
@@ -14,8 +14,7 @@ class GetWalletStatusResult {
14 required this.progress,
15 required this.walletState});
16
17 - factory GetWalletStatusResult.fromJson(Map<String, dynamic> json) =>
18 - GetWalletStatusResult(
17 + factory GetWalletStatusResult.fromJson(Map<String, dynamic> json) => GetWalletStatusResult(
18 currentDaemonHeight: json['current_daemon_height'] as int? ?? 0,
19 currentWalletHeight: json['current_wallet_height'] as int? ?? 0,
20 isDaemonConnected: json['is_daemon_connected'] as bool? ?? false,
cw_zano/lib/api/model/recent_history.dart
+6 -6
@@ -6,14 +6,14 @@ class RecentHistory {
6 final int totalHistoryItems;
7
8 RecentHistory(
9 - {required this.history,
10 - required this.lastItemIndex,
11 - required this.totalHistoryItems});
9 + {required this.history, required this.lastItemIndex, required this.totalHistoryItems});
10
11 factory RecentHistory.fromJson(Map<String, dynamic> json) => RecentHistory(
14 - history: json['history'] == null ? null : (json['history'] as List<dynamic>)
15 - .map((e) => Transfer.fromJson(e as Map<String, dynamic>))
16 - .toList(),
12 + history: json['history'] == null
13 + ? null
14 + : (json['history'] as List<dynamic>)
15 + .map((e) => Transfer.fromJson(e as Map<String, dynamic>))
16 + .toList(),
17 lastItemIndex: json['last_item_index'] as int? ?? 0,
18 totalHistoryItems: json['total_history_items'] as int? ?? 0,
19 );
cw_zano/lib/api/model/store_result.dart
+1 -1
@@ -6,4 +6,4 @@ class StoreResult {
6 factory StoreResult.fromJson(Map<String, dynamic> json) => StoreResult(
7 walletFileSize: json['wallet_file_size'] as int? ?? 0,
8 );
9 -}
\ No newline at end of file
9 +}
cw_zano/lib/api/model/subtransfer.dart
+1 -2
@@ -5,8 +5,7 @@ class Subtransfer {
5 final String assetId;
6 final bool isIncome;
7
8 - Subtransfer(
9 - {required this.amount, required this.assetId, required this.isIncome});
8 + Subtransfer({required this.amount, required this.assetId, required this.isIncome});
9
10 factory Subtransfer.fromJson(Map<String, dynamic> json) => Subtransfer(
11 amount: ZanoFormatter.bigIntFromDynamic(json['amount']),
cw_zano/lib/api/model/transfer.dart
+23 -21
@@ -49,38 +49,40 @@ class Transfer {
49 required this.unlockTime,
50 });
51
52 - factory Transfer.fromJson(Map<String, dynamic> json) =>
53 - Transfer(
52 + factory Transfer.fromJson(Map<String, dynamic> json) => Transfer(
53 comment: json['comment'] as String? ?? '',
55 - employedEntries: EmployedEntries.fromJson(
56 - json['employed_entries'] as Map<String, dynamic>? ?? {}),
54 + employedEntries:
55 + EmployedEntries.fromJson(json['employed_entries'] as Map<String, dynamic>? ?? {}),
56 fee: json['fee'] as int? ?? 0,
57 height: json['height'] as int? ?? 0,
58 isMining: json['is_mining'] as bool? ?? false,
59 isMixing: json['is_mixing'] as bool? ?? false,
60 isService: json['is_service'] as bool? ?? false,
61 paymentId: json['payment_id'] as String? ?? '',
63 - remoteAddresses: json['remote_addresses'] == null ? [] : (json['remote_addresses'] as List<
64 - dynamic>).cast<String>(),
65 - remoteAliases: json['remote_aliases'] == null ? [] : (json['remote_aliases'] as List<
66 - dynamic>).cast<String>(),
62 + remoteAddresses: json['remote_addresses'] == null
63 + ? []
64 + : (json['remote_addresses'] as List<dynamic>).cast<String>(),
65 + remoteAliases: json['remote_aliases'] == null
66 + ? []
67 + : (json['remote_aliases'] as List<dynamic>).cast<String>(),
68 showSender: json['show_sender'] as bool? ?? false,
68 - subtransfers: (json['subtransfers'] as List<dynamic>? ?? []).map((e) =>
69 - Subtransfer.fromJson(e as Map<String, dynamic>)).toList(),
69 + subtransfers: (json['subtransfers'] as List<dynamic>? ?? [])
70 + .map((e) => Subtransfer.fromJson(e as Map<String, dynamic>))
71 + .toList(),
72 timestamp: json['timestamp'] as int? ?? 0,
73 transferInternalIndex: json['transfer_internal_index'] == null
74 ? 0
75 : json['transfer_internal_index'] is double
74 - ? (json['transfer_internal_index'] as double).toInt()
75 - : json['transfer_internal_index'] as int,
76 + ? (json['transfer_internal_index'] as double).toInt()
77 + : json['transfer_internal_index'] as int,
78 txBlobSize: json['tx_blob_size'] as int? ?? 0,
79 txHash: json['tx_hash'] as String? ?? '',
80 txType: json['tx_type'] as int? ?? 0,
81 unlockTime: json['unlock_time'] as int? ?? 0,
82 );
83
82 - static Map<String, ZanoTransactionInfo> makeMap(List<Transfer> transfers,
83 - Map<String, ZanoAsset> zanoAssets, int currentDaemonHeight) {
84 + static Map<String, ZanoTransactionInfo> makeMap(
85 + List<Transfer> transfers, Map<String, ZanoAsset> zanoAssets, int currentDaemonHeight) {
86 return Map.fromIterable(
87 transfers,
88 key: (item) => (item as Transfer).txHash,
@@ -89,19 +91,19 @@ class Transfer {
91 // Simple (only one subtransfer OR two subtransfers and the second is Zano, outgoing and amount equals to fee) or complex?
92 Subtransfer? single = transfer.subtransfers.singleOrNull;
93 if (transfer.subtransfers.length == 2) {
92 - final zano = transfer.subtransfers.firstWhereOrNull((element) =>
93 - element.assetId == ZanoWalletBase.zanoAssetId);
94 + final zano = transfer.subtransfers
95 + .firstWhereOrNull((element) => element.assetId == ZanoWalletBase.zanoAssetId);
96 if (zano != null && !zano.isIncome && zano.amount == BigInt.from(transfer.fee)) {
95 - single = transfer.subtransfers.firstWhere((element) => element.assetId !=
96 - ZanoWalletBase.zanoAssetId);
97 + single = transfer.subtransfers
98 + .firstWhere((element) => element.assetId != ZanoWalletBase.zanoAssetId);
99 }
100 }
101 bool isSimple = single != null;
102 // TODO: for complex transactions we show zano or any other transaction, will fix it later
103 if (!isSimple) {
102 - single =
103 - transfer.subtransfers.firstWhereOrNull((element) =>
104 - element.assetId == ZanoWalletBase.zanoAssetId) ?? transfer.subtransfers.first;
104 + single = transfer.subtransfers
105 + .firstWhereOrNull((element) => element.assetId == ZanoWalletBase.zanoAssetId) ??
106 + transfer.subtransfers.first;
107 }
108 if (single.assetId != ZanoWalletBase.zanoAssetId) {
109 final asset = zanoAssets[single.assetId];
cw_zano/lib/api/model/transfer_params.dart
+12 -9
@@ -20,17 +20,20 @@ class TransferParams {
20 });
21
22 Map<String, dynamic> toJson() => {
23 - 'destinations': destinations,
24 - 'fee': fee.toInt(),
25 - 'mixin': mixin,
26 - 'payment_id': paymentId,
27 - 'comment': comment,
28 - 'push_payer': pushPayer,
29 - 'hide_receiver': hideReceiver,
30 - };
23 + 'destinations': destinations,
24 + 'fee': fee.toInt(),
25 + 'mixin': mixin,
26 + 'payment_id': paymentId,
27 + 'comment': comment,
28 + 'push_payer': pushPayer,
29 + 'hide_receiver': hideReceiver,
30 + };
31
32 factory TransferParams.fromJson(Map<String, dynamic> json) => TransferParams(
33 - destinations: (json['destinations'] as List<dynamic>?)?.map((e) => Destination.fromJson(e as Map<String, dynamic>)).toList() ?? [],
33 + destinations: (json['destinations'] as List<dynamic>?)
34 + ?.map((e) => Destination.fromJson(e as Map<String, dynamic>))
35 + .toList() ??
36 + [],
37 fee: BigInt.from(json['fee'] as int? ?? 0),
38 mixin: json['mixin'] as int? ?? 0,
39 paymentId: json['payment_id'] as String? ?? '',
cw_zano/lib/api/model/wi_extended.dart
+11 -7
@@ -6,16 +6,20 @@ class WiExtended {
6 final String viewPrivateKey;
7 final String viewPublicKey;
8
9 - WiExtended({required this.spendPrivateKey, required this.spendPublicKey, required this.viewPrivateKey, required this.viewPublicKey});
9 + WiExtended(
10 + {required this.spendPrivateKey,
11 + required this.spendPublicKey,
12 + required this.viewPrivateKey,
13 + required this.viewPublicKey});
14
15 factory WiExtended.fromJson(Map<String, dynamic> json) => WiExtended(
12 - spendPrivateKey: json['spend_private_key'] as String? ?? '',
13 - spendPublicKey: json['spend_public_key'] as String? ?? '',
14 - viewPrivateKey: json['view_private_key'] as String? ?? '',
15 - viewPublicKey: json['view_public_key'] as String? ?? '',
16 - );
16 + spendPrivateKey: json['spend_private_key'] as String? ?? '',
17 + spendPublicKey: json['spend_public_key'] as String? ?? '',
18 + viewPrivateKey: json['view_private_key'] as String? ?? '',
19 + viewPublicKey: json['view_public_key'] as String? ?? '',
20 + );
21
22 Future<String> seed(ZanoWalletBase api) {
23 return api.getSeed();
24 }
21 -}
\ No newline at end of file
25 +}
cw_zano/lib/mnemonics/english.dart
+1626 -1626
@@ -1,1630 +1,1630 @@
1 class EnglishMnemonics {
2 static const words = [
3 - "like",
4 - "just",
5 - "love",
6 - "know",
7 - "never",
8 - "want",
9 - "time",
10 - "out",
11 - "there",
12 - "make",
13 - "look",
14 - "eye",
15 - "down",
16 - "only",
17 - "think",
18 - "heart",
19 - "back",
20 - "then",
21 - "into",
22 - "about",
23 - "more",
24 - "away",
25 - "still",
26 - "them",
27 - "take",
28 - "thing",
29 - "even",
30 - "through",
31 - "long",
32 - "always",
33 - "world",
34 - "too",
35 - "friend",
36 - "tell",
37 - "try",
38 - "hand",
39 - "thought",
40 - "over",
41 - "here",
42 - "other",
43 - "need",
44 - "smile",
45 - "again",
46 - "much",
47 - "cry",
48 - "been",
49 - "night",
50 - "ever",
51 - "little",
52 - "said",
53 - "end",
54 - "some",
55 - "those",
56 - "around",
57 - "mind",
58 - "people",
59 - "girl",
60 - "leave",
61 - "dream",
62 - "left",
63 - "turn",
64 - "myself",
65 - "give",
66 - "nothing",
67 - "really",
68 - "off",
69 - "before",
70 - "something",
71 - "find",
72 - "walk",
73 - "wish",
74 - "good",
75 - "once",
76 - "place",
77 - "ask",
78 - "stop",
79 - "keep",
80 - "watch",
81 - "seem",
82 - "everything",
83 - "wait",
84 - "got",
85 - "yet",
86 - "made",
87 - "remember",
88 - "start",
89 - "alone",
90 - "run",
91 - "hope",
92 - "maybe",
93 - "believe",
94 - "body",
95 - "hate",
96 - "after",
97 - "close",
98 - "talk",
99 - "stand",
100 - "own",
101 - "each",
102 - "hurt",
103 - "help",
104 - "home",
105 - "god",
106 - "soul",
107 - "new",
108 - "many",
109 - "two",
110 - "inside",
111 - "should",
112 - "true",
113 - "first",
114 - "fear",
115 - "mean",
116 - "better",
117 - "play",
118 - "another",
119 - "gone",
120 - "change",
121 - "use",
122 - "wonder",
123 - "someone",
124 - "hair",
125 - "cold",
126 - "open",
127 - "best",
128 - "any",
129 - "behind",
130 - "happen",
131 - "water",
132 - "dark",
133 - "laugh",
134 - "stay",
135 - "forever",
136 - "name",
137 - "work",
138 - "show",
139 - "sky",
140 - "break",
141 - "came",
142 - "deep",
143 - "door",
144 - "put",
145 - "black",
146 - "together",
147 - "upon",
148 - "happy",
149 - "such",
150 - "great",
151 - "white",
152 - "matter",
153 - "fill",
154 - "past",
155 - "please",
156 - "burn",
157 - "cause",
158 - "enough",
159 - "touch",
160 - "moment",
161 - "soon",
162 - "voice",
163 - "scream",
164 - "anything",
165 - "stare",
166 - "sound",
167 - "red",
168 - "everyone",
169 - "hide",
170 - "kiss",
171 - "truth",
172 - "death",
173 - "beautiful",
174 - "mine",
175 - "blood",
176 - "broken",
177 - "very",
178 - "pass",
179 - "next",
180 - "forget",
181 - "tree",
182 - "wrong",
183 - "air",
184 - "mother",
185 - "understand",
186 - "lip",
187 - "hit",
188 - "wall",
189 - "memory",
190 - "sleep",
191 - "free",
192 - "high",
193 - "realize",
194 - "school",
195 - "might",
196 - "skin",
197 - "sweet",
198 - "perfect",
199 - "blue",
200 - "kill",
201 - "breath",
202 - "dance",
203 - "against",
204 - "fly",
205 - "between",
206 - "grow",
207 - "strong",
208 - "under",
209 - "listen",
210 - "bring",
211 - "sometimes",
212 - "speak",
213 - "pull",
214 - "person",
215 - "become",
216 - "family",
217 - "begin",
218 - "ground",
219 - "real",
220 - "small",
221 - "father",
222 - "sure",
223 - "feet",
224 - "rest",
225 - "young",
226 - "finally",
227 - "land",
228 - "across",
229 - "today",
230 - "different",
231 - "guy",
232 - "line",
233 - "fire",
234 - "reason",
235 - "reach",
236 - "second",
237 - "slowly",
238 - "write",
239 - "eat",
240 - "smell",
241 - "mouth",
242 - "step",
243 - "learn",
244 - "three",
245 - "floor",
246 - "promise",
247 - "breathe",
248 - "darkness",
249 - "push",
250 - "earth",
251 - "guess",
252 - "save",
253 - "song",
254 - "above",
255 - "along",
256 - "both",
257 - "color",
258 - "house",
259 - "almost",
260 - "sorry",
261 - "anymore",
262 - "brother",
263 - "okay",
264 - "dear",
265 - "game",
266 - "fade",
267 - "already",
268 - "apart",
269 - "warm",
270 - "beauty",
271 - "heard",
272 - "notice",
273 - "question",
274 - "shine",
275 - "began",
276 - "piece",
277 - "whole",
278 - "shadow",
279 - "secret",
280 - "street",
281 - "within",
282 - "finger",
283 - "point",
284 - "morning",
285 - "whisper",
286 - "child",
287 - "moon",
288 - "green",
289 - "story",
290 - "glass",
291 - "kid",
292 - "silence",
293 - "since",
294 - "soft",
295 - "yourself",
296 - "empty",
297 - "shall",
298 - "angel",
299 - "answer",
300 - "baby",
301 - "bright",
302 - "dad",
303 - "path",
304 - "worry",
305 - "hour",
306 - "drop",
307 - "follow",
308 - "power",
309 - "war",
310 - "half",
311 - "flow",
312 - "heaven",
313 - "act",
314 - "chance",
315 - "fact",
316 - "least",
317 - "tired",
318 - "children",
319 - "near",
320 - "quite",
321 - "afraid",
322 - "rise",
323 - "sea",
324 - "taste",
325 - "window",
326 - "cover",
327 - "nice",
328 - "trust",
329 - "lot",
330 - "sad",
331 - "cool",
332 - "force",
333 - "peace",
334 - "return",
335 - "blind",
336 - "easy",
337 - "ready",
338 - "roll",
339 - "rose",
340 - "drive",
341 - "held",
342 - "music",
343 - "beneath",
344 - "hang",
345 - "mom",
346 - "paint",
347 - "emotion",
348 - "quiet",
349 - "clear",
350 - "cloud",
351 - "few",
352 - "pretty",
353 - "bird",
354 - "outside",
355 - "paper",
356 - "picture",
357 - "front",
358 - "rock",
359 - "simple",
360 - "anyone",
361 - "meant",
362 - "reality",
363 - "road",
364 - "sense",
365 - "waste",
366 - "bit",
367 - "leaf",
368 - "thank",
369 - "happiness",
370 - "meet",
371 - "men",
372 - "smoke",
373 - "truly",
374 - "decide",
375 - "self",
376 - "age",
377 - "book",
378 - "form",
379 - "alive",
380 - "carry",
381 - "escape",
382 - "damn",
383 - "instead",
384 - "able",
385 - "ice",
386 - "minute",
387 - "throw",
388 - "catch",
389 - "leg",
390 - "ring",
391 - "course",
392 - "goodbye",
393 - "lead",
394 - "poem",
395 - "sick",
396 - "corner",
397 - "desire",
398 - "known",
399 - "problem",
400 - "remind",
401 - "shoulder",
402 - "suppose",
403 - "toward",
404 - "wave",
405 - "drink",
406 - "jump",
407 - "woman",
408 - "pretend",
409 - "sister",
410 - "week",
411 - "human",
412 - "joy",
413 - "crack",
414 - "grey",
415 - "pray",
416 - "surprise",
417 - "dry",
418 - "knee",
419 - "less",
420 - "search",
421 - "bleed",
422 - "caught",
423 - "clean",
424 - "embrace",
425 - "future",
426 - "king",
427 - "son",
428 - "sorrow",
429 - "chest",
430 - "hug",
431 - "remain",
432 - "sat",
433 - "worth",
434 - "blow",
435 - "daddy",
436 - "final",
437 - "parent",
438 - "tight",
439 - "also",
440 - "create",
441 - "lonely",
442 - "safe",
443 - "cross",
444 - "dress",
445 - "evil",
446 - "silent",
447 - "bone",
448 - "fate",
449 - "perhaps",
450 - "anger",
451 - "class",
452 - "scar",
453 - "snow",
454 - "tiny",
455 - "tonight",
456 - "continue",
457 - "control",
458 - "dog",
459 - "edge",
460 - "mirror",
461 - "month",
462 - "suddenly",
463 - "comfort",
464 - "given",
465 - "loud",
466 - "quickly",
467 - "gaze",
468 - "plan",
469 - "rush",
470 - "stone",
471 - "town",
472 - "battle",
473 - "ignore",
474 - "spirit",
475 - "stood",
476 - "stupid",
477 - "yours",
478 - "brown",
479 - "build",
480 - "dust",
481 - "hey",
482 - "kept",
483 - "pay",
484 - "phone",
485 - "twist",
486 - "although",
487 - "ball",
488 - "beyond",
489 - "hidden",
490 - "nose",
491 - "taken",
492 - "fail",
493 - "float",
494 - "pure",
495 - "somehow",
496 - "wash",
497 - "wrap",
498 - "angry",
499 - "cheek",
500 - "creature",
501 - "forgotten",
502 - "heat",
503 - "rip",
504 - "single",
505 - "space",
506 - "special",
507 - "weak",
508 - "whatever",
509 - "yell",
510 - "anyway",
511 - "blame",
512 - "job",
513 - "choose",
514 - "country",
515 - "curse",
516 - "drift",
517 - "echo",
518 - "figure",
519 - "grew",
520 - "laughter",
521 - "neck",
522 - "suffer",
523 - "worse",
524 - "yeah",
525 - "disappear",
526 - "foot",
527 - "forward",
528 - "knife",
529 - "mess",
530 - "somewhere",
531 - "stomach",
532 - "storm",
533 - "beg",
534 - "idea",
535 - "lift",
536 - "offer",
537 - "breeze",
538 - "field",
539 - "five",
540 - "often",
541 - "simply",
542 - "stuck",
543 - "win",
544 - "allow",
545 - "confuse",
546 - "enjoy",
547 - "except",
548 - "flower",
549 - "seek",
550 - "strength",
551 - "calm",
552 - "grin",
553 - "gun",
554 - "heavy",
555 - "hill",
556 - "large",
557 - "ocean",
558 - "shoe",
559 - "sigh",
560 - "straight",
561 - "summer",
562 - "tongue",
563 - "accept",
564 - "crazy",
565 - "everyday",
566 - "exist",
567 - "grass",
568 - "mistake",
569 - "sent",
570 - "shut",
571 - "surround",
572 - "table",
573 - "ache",
574 - "brain",
575 - "destroy",
576 - "heal",
577 - "nature",
578 - "shout",
579 - "sign",
580 - "stain",
581 - "choice",
582 - "doubt",
583 - "glance",
584 - "glow",
585 - "mountain",
586 - "queen",
587 - "stranger",
588 - "throat",
589 - "tomorrow",
590 - "city",
591 - "either",
592 - "fish",
593 - "flame",
594 - "rather",
595 - "shape",
596 - "spin",
597 - "spread",
598 - "ash",
599 - "distance",
600 - "finish",
601 - "image",
602 - "imagine",
603 - "important",
604 - "nobody",
605 - "shatter",
606 - "warmth",
607 - "became",
608 - "feed",
609 - "flesh",
610 - "funny",
611 - "lust",
612 - "shirt",
613 - "trouble",
614 - "yellow",
615 - "attention",
616 - "bare",
617 - "bite",
618 - "money",
619 - "protect",
620 - "amaze",
621 - "appear",
622 - "born",
623 - "choke",
624 - "completely",
625 - "daughter",
626 - "fresh",
627 - "friendship",
628 - "gentle",
629 - "probably",
630 - "six",
631 - "deserve",
632 - "expect",
633 - "grab",
634 - "middle",
635 - "nightmare",
636 - "river",
637 - "thousand",
638 - "weight",
639 - "worst",
640 - "wound",
641 - "barely",
642 - "bottle",
643 - "cream",
644 - "regret",
645 - "relationship",
646 - "stick",
647 - "test",
648 - "crush",
649 - "endless",
650 - "fault",
651 - "itself",
652 - "rule",
653 - "spill",
654 - "art",
655 - "circle",
656 - "join",
657 - "kick",
658 - "mask",
659 - "master",
660 - "passion",
661 - "quick",
662 - "raise",
663 - "smooth",
664 - "unless",
665 - "wander",
666 - "actually",
667 - "broke",
668 - "chair",
669 - "deal",
670 - "favorite",
671 - "gift",
672 - "note",
673 - "number",
674 - "sweat",
675 - "box",
676 - "chill",
677 - "clothes",
678 - "lady",
679 - "mark",
680 - "park",
681 - "poor",
682 - "sadness",
683 - "tie",
684 - "animal",
685 - "belong",
686 - "brush",
687 - "consume",
688 - "dawn",
689 - "forest",
690 - "innocent",
691 - "pen",
692 - "pride",
693 - "stream",
694 - "thick",
695 - "clay",
696 - "complete",
697 - "count",
698 - "draw",
699 - "faith",
700 - "press",
701 - "silver",
702 - "struggle",
703 - "surface",
704 - "taught",
705 - "teach",
706 - "wet",
707 - "bless",
708 - "chase",
709 - "climb",
710 - "enter",
711 - "letter",
712 - "melt",
713 - "metal",
714 - "movie",
715 - "stretch",
716 - "swing",
717 - "vision",
718 - "wife",
719 - "beside",
720 - "crash",
721 - "forgot",
722 - "guide",
723 - "haunt",
724 - "joke",
725 - "knock",
726 - "plant",
727 - "pour",
728 - "prove",
729 - "reveal",
730 - "steal",
731 - "stuff",
732 - "trip",
733 - "wood",
734 - "wrist",
735 - "bother",
736 - "bottom",
737 - "crawl",
738 - "crowd",
739 - "fix",
740 - "forgive",
741 - "frown",
742 - "grace",
743 - "loose",
744 - "lucky",
745 - "party",
746 - "release",
747 - "surely",
748 - "survive",
749 - "teacher",
750 - "gently",
751 - "grip",
752 - "speed",
753 - "suicide",
754 - "travel",
755 - "treat",
756 - "vein",
757 - "written",
758 - "cage",
759 - "chain",
760 - "conversation",
761 - "date",
762 - "enemy",
763 - "however",
764 - "interest",
765 - "million",
766 - "page",
767 - "pink",
768 - "proud",
769 - "sway",
770 - "themselves",
771 - "winter",
772 - "church",
773 - "cruel",
774 - "cup",
775 - "demon",
776 - "experience",
777 - "freedom",
778 - "pair",
779 - "pop",
780 - "purpose",
781 - "respect",
782 - "shoot",
783 - "softly",
784 - "state",
785 - "strange",
786 - "bar",
787 - "birth",
788 - "curl",
789 - "dirt",
790 - "excuse",
791 - "lord",
792 - "lovely",
793 - "monster",
794 - "order",
795 - "pack",
796 - "pants",
797 - "pool",
798 - "scene",
799 - "seven",
800 - "shame",
801 - "slide",
802 - "ugly",
803 - "among",
804 - "blade",
805 - "blonde",
806 - "closet",
807 - "creek",
808 - "deny",
809 - "drug",
810 - "eternity",
811 - "gain",
812 - "grade",
813 - "handle",
814 - "key",
815 - "linger",
816 - "pale",
817 - "prepare",
818 - "swallow",
819 - "swim",
820 - "tremble",
821 - "wheel",
822 - "won",
823 - "cast",
824 - "cigarette",
825 - "claim",
826 - "college",
827 - "direction",
828 - "dirty",
829 - "gather",
830 - "ghost",
831 - "hundred",
832 - "loss",
833 - "lung",
834 - "orange",
835 - "present",
836 - "swear",
837 - "swirl",
838 - "twice",
839 - "wild",
840 - "bitter",
841 - "blanket",
842 - "doctor",
843 - "everywhere",
844 - "flash",
845 - "grown",
846 - "knowledge",
847 - "numb",
848 - "pressure",
849 - "radio",
850 - "repeat",
851 - "ruin",
852 - "spend",
853 - "unknown",
854 - "buy",
855 - "clock",
856 - "devil",
857 - "early",
858 - "false",
859 - "fantasy",
860 - "pound",
861 - "precious",
862 - "refuse",
863 - "sheet",
864 - "teeth",
865 - "welcome",
866 - "add",
867 - "ahead",
868 - "block",
869 - "bury",
870 - "caress",
871 - "content",
872 - "depth",
873 - "despite",
874 - "distant",
875 - "marry",
876 - "purple",
877 - "threw",
878 - "whenever",
879 - "bomb",
880 - "dull",
881 - "easily",
882 - "grasp",
883 - "hospital",
884 - "innocence",
885 - "normal",
886 - "receive",
887 - "reply",
888 - "rhyme",
889 - "shade",
890 - "someday",
891 - "sword",
892 - "toe",
893 - "visit",
894 - "asleep",
895 - "bought",
896 - "center",
897 - "consider",
898 - "flat",
899 - "hero",
900 - "history",
901 - "ink",
902 - "insane",
903 - "muscle",
904 - "mystery",
905 - "pocket",
906 - "reflection",
907 - "shove",
908 - "silently",
909 - "smart",
910 - "soldier",
911 - "spot",
912 - "stress",
913 - "train",
914 - "type",
915 - "view",
916 - "whether",
917 - "bus",
918 - "energy",
919 - "explain",
920 - "holy",
921 - "hunger",
922 - "inch",
923 - "magic",
924 - "mix",
925 - "noise",
926 - "nowhere",
927 - "prayer",
928 - "presence",
929 - "shock",
930 - "snap",
931 - "spider",
932 - "study",
933 - "thunder",
934 - "trail",
935 - "admit",
936 - "agree",
937 - "bag",
938 - "bang",
939 - "bound",
940 - "butterfly",
941 - "cute",
942 - "exactly",
943 - "explode",
944 - "familiar",
945 - "fold",
946 - "further",
947 - "pierce",
948 - "reflect",
949 - "scent",
950 - "selfish",
951 - "sharp",
952 - "sink",
953 - "spring",
954 - "stumble",
955 - "universe",
956 - "weep",
957 - "women",
958 - "wonderful",
959 - "action",
960 - "ancient",
961 - "attempt",
962 - "avoid",
963 - "birthday",
964 - "branch",
965 - "chocolate",
966 - "core",
967 - "depress",
968 - "drunk",
969 - "especially",
970 - "focus",
971 - "fruit",
972 - "honest",
973 - "match",
974 - "palm",
975 - "perfectly",
976 - "pillow",
977 - "pity",
978 - "poison",
979 - "roar",
980 - "shift",
981 - "slightly",
982 - "thump",
983 - "truck",
984 - "tune",
985 - "twenty",
986 - "unable",
987 - "wipe",
988 - "wrote",
989 - "coat",
990 - "constant",
991 - "dinner",
992 - "drove",
993 - "egg",
994 - "eternal",
995 - "flight",
996 - "flood",
997 - "frame",
998 - "freak",
999 - "gasp",
1000 - "glad",
1001 - "hollow",
1002 - "motion",
1003 - "peer",
1004 - "plastic",
1005 - "root",
1006 - "screen",
1007 - "season",
1008 - "sting",
1009 - "strike",
1010 - "team",
1011 - "unlike",
1012 - "victim",
1013 - "volume",
1014 - "warn",
1015 - "weird",
1016 - "attack",
1017 - "await",
1018 - "awake",
1019 - "built",
1020 - "charm",
1021 - "crave",
1022 - "despair",
1023 - "fought",
1024 - "grant",
1025 - "grief",
1026 - "horse",
1027 - "limit",
1028 - "message",
1029 - "ripple",
1030 - "sanity",
1031 - "scatter",
1032 - "serve",
1033 - "split",
1034 - "string",
1035 - "trick",
1036 - "annoy",
1037 - "blur",
1038 - "boat",
1039 - "brave",
1040 - "clearly",
1041 - "cling",
1042 - "connect",
1043 - "fist",
1044 - "forth",
1045 - "imagination",
1046 - "iron",
1047 - "jock",
1048 - "judge",
1049 - "lesson",
1050 - "milk",
1051 - "misery",
1052 - "nail",
1053 - "naked",
1054 - "ourselves",
1055 - "poet",
1056 - "possible",
1057 - "princess",
1058 - "sail",
1059 - "size",
1060 - "snake",
1061 - "society",
1062 - "stroke",
1063 - "torture",
1064 - "toss",
1065 - "trace",
1066 - "wise",
1067 - "bloom",
1068 - "bullet",
1069 - "cell",
1070 - "check",
1071 - "cost",
1072 - "darling",
1073 - "during",
1074 - "footstep",
1075 - "fragile",
1076 - "hallway",
1077 - "hardly",
1078 - "horizon",
1079 - "invisible",
1080 - "journey",
1081 - "midnight",
1082 - "mud",
1083 - "nod",
1084 - "pause",
1085 - "relax",
1086 - "shiver",
1087 - "sudden",
1088 - "value",
1089 - "youth",
1090 - "abuse",
1091 - "admire",
1092 - "blink",
1093 - "breast",
1094 - "bruise",
1095 - "constantly",
1096 - "couple",
1097 - "creep",
1098 - "curve",
1099 - "difference",
1100 - "dumb",
1101 - "emptiness",
1102 - "gotta",
1103 - "honor",
1104 - "plain",
1105 - "planet",
1106 - "recall",
1107 - "rub",
1108 - "ship",
1109 - "slam",
1110 - "soar",
1111 - "somebody",
1112 - "tightly",
1113 - "weather",
1114 - "adore",
1115 - "approach",
1116 - "bond",
1117 - "bread",
1118 - "burst",
1119 - "candle",
1120 - "coffee",
1121 - "cousin",
1122 - "crime",
1123 - "desert",
1124 - "flutter",
1125 - "frozen",
1126 - "grand",
1127 - "heel",
1128 - "hello",
1129 - "language",
1130 - "level",
1131 - "movement",
1132 - "pleasure",
1133 - "powerful",
1134 - "random",
1135 - "rhythm",
1136 - "settle",
1137 - "silly",
1138 - "slap",
1139 - "sort",
1140 - "spoken",
1141 - "steel",
1142 - "threaten",
1143 - "tumble",
1144 - "upset",
1145 - "aside",
1146 - "awkward",
1147 - "bee",
1148 - "blank",
1149 - "board",
1150 - "button",
1151 - "card",
1152 - "carefully",
1153 - "complain",
1154 - "crap",
1155 - "deeply",
1156 - "discover",
1157 - "drag",
1158 - "dread",
1159 - "effort",
1160 - "entire",
1161 - "fairy",
1162 - "giant",
1163 - "gotten",
1164 - "greet",
1165 - "illusion",
1166 - "jeans",
1167 - "leap",
1168 - "liquid",
1169 - "march",
1170 - "mend",
1171 - "nervous",
1172 - "nine",
1173 - "replace",
1174 - "rope",
1175 - "spine",
1176 - "stole",
1177 - "terror",
1178 - "accident",
1179 - "apple",
1180 - "balance",
1181 - "boom",
1182 - "childhood",
1183 - "collect",
1184 - "demand",
1185 - "depression",
1186 - "eventually",
1187 - "faint",
1188 - "glare",
1189 - "goal",
1190 - "group",
1191 - "honey",
1192 - "kitchen",
1193 - "laid",
1194 - "limb",
1195 - "machine",
1196 - "mere",
1197 - "mold",
1198 - "murder",
1199 - "nerve",
1200 - "painful",
1201 - "poetry",
1202 - "prince",
1203 - "rabbit",
1204 - "shelter",
1205 - "shore",
1206 - "shower",
1207 - "soothe",
1208 - "stair",
1209 - "steady",
1210 - "sunlight",
1211 - "tangle",
1212 - "tease",
1213 - "treasure",
1214 - "uncle",
1215 - "begun",
1216 - "bliss",
1217 - "canvas",
1218 - "cheer",
1219 - "claw",
1220 - "clutch",
1221 - "commit",
1222 - "crimson",
1223 - "crystal",
1224 - "delight",
1225 - "doll",
1226 - "existence",
1227 - "express",
1228 - "fog",
1229 - "football",
1230 - "gay",
1231 - "goose",
1232 - "guard",
1233 - "hatred",
1234 - "illuminate",
1235 - "mass",
1236 - "math",
1237 - "mourn",
1238 - "rich",
1239 - "rough",
1240 - "skip",
1241 - "stir",
1242 - "student",
1243 - "style",
1244 - "support",
1245 - "thorn",
1246 - "tough",
1247 - "yard",
1248 - "yearn",
1249 - "yesterday",
1250 - "advice",
1251 - "appreciate",
1252 - "autumn",
1253 - "bank",
1254 - "beam",
1255 - "bowl",
1256 - "capture",
1257 - "carve",
1258 - "collapse",
1259 - "confusion",
1260 - "creation",
1261 - "dove",
1262 - "feather",
1263 - "girlfriend",
1264 - "glory",
1265 - "government",
1266 - "harsh",
1267 - "hop",
1268 - "inner",
1269 - "loser",
1270 - "moonlight",
1271 - "neighbor",
1272 - "neither",
1273 - "peach",
1274 - "pig",
1275 - "praise",
1276 - "screw",
1277 - "shield",
1278 - "shimmer",
1279 - "sneak",
1280 - "stab",
1281 - "subject",
1282 - "throughout",
1283 - "thrown",
1284 - "tower",
1285 - "twirl",
1286 - "wow",
1287 - "army",
1288 - "arrive",
1289 - "bathroom",
1290 - "bump",
1291 - "cease",
1292 - "cookie",
1293 - "couch",
1294 - "courage",
1295 - "dim",
1296 - "guilt",
1297 - "howl",
1298 - "hum",
1299 - "husband",
1300 - "insult",
1301 - "led",
1302 - "lunch",
1303 - "mock",
1304 - "mostly",
1305 - "natural",
1306 - "nearly",
1307 - "needle",
1308 - "nerd",
1309 - "peaceful",
1310 - "perfection",
1311 - "pile",
1312 - "price",
1313 - "remove",
1314 - "roam",
1315 - "sanctuary",
1316 - "serious",
1317 - "shiny",
1318 - "shook",
1319 - "sob",
1320 - "stolen",
1321 - "tap",
1322 - "vain",
1323 - "void",
1324 - "warrior",
1325 - "wrinkle",
1326 - "affection",
1327 - "apologize",
1328 - "blossom",
1329 - "bounce",
1330 - "bridge",
1331 - "cheap",
1332 - "crumble",
1333 - "decision",
1334 - "descend",
1335 - "desperately",
1336 - "dig",
1337 - "dot",
1338 - "flip",
1339 - "frighten",
1340 - "heartbeat",
1341 - "huge",
1342 - "lazy",
1343 - "lick",
1344 - "odd",
1345 - "opinion",
1346 - "process",
1347 - "puzzle",
1348 - "quietly",
1349 - "retreat",
1350 - "score",
1351 - "sentence",
1352 - "separate",
1353 - "situation",
1354 - "skill",
1355 - "soak",
1356 - "square",
1357 - "stray",
1358 - "taint",
1359 - "task",
1360 - "tide",
1361 - "underneath",
1362 - "veil",
1363 - "whistle",
1364 - "anywhere",
1365 - "bedroom",
1366 - "bid",
1367 - "bloody",
1368 - "burden",
1369 - "careful",
1370 - "compare",
1371 - "concern",
1372 - "curtain",
1373 - "decay",
1374 - "defeat",
1375 - "describe",
1376 - "double",
1377 - "dreamer",
1378 - "driver",
1379 - "dwell",
1380 - "evening",
1381 - "flare",
1382 - "flicker",
1383 - "grandma",
1384 - "guitar",
1385 - "harm",
1386 - "horrible",
1387 - "hungry",
1388 - "indeed",
1389 - "lace",
1390 - "melody",
1391 - "monkey",
1392 - "nation",
1393 - "object",
1394 - "obviously",
1395 - "rainbow",
1396 - "salt",
1397 - "scratch",
1398 - "shown",
1399 - "shy",
1400 - "stage",
1401 - "stun",
1402 - "third",
1403 - "tickle",
1404 - "useless",
1405 - "weakness",
1406 - "worship",
1407 - "worthless",
1408 - "afternoon",
1409 - "beard",
1410 - "boyfriend",
1411 - "bubble",
1412 - "busy",
1413 - "certain",
1414 - "chin",
1415 - "concrete",
1416 - "desk",
1417 - "diamond",
1418 - "doom",
1419 - "drawn",
1420 - "due",
1421 - "felicity",
1422 - "freeze",
1423 - "frost",
1424 - "garden",
1425 - "glide",
1426 - "harmony",
1427 - "hopefully",
1428 - "hunt",
1429 - "jealous",
1430 - "lightning",
1431 - "mama",
1432 - "mercy",
1433 - "peel",
1434 - "physical",
1435 - "position",
1436 - "pulse",
1437 - "punch",
1438 - "quit",
1439 - "rant",
1440 - "respond",
1441 - "salty",
1442 - "sane",
1443 - "satisfy",
1444 - "savior",
1445 - "sheep",
1446 - "slept",
1447 - "social",
1448 - "sport",
1449 - "tuck",
1450 - "utter",
1451 - "valley",
1452 - "wolf",
1453 - "aim",
1454 - "alas",
1455 - "alter",
1456 - "arrow",
1457 - "awaken",
1458 - "beaten",
1459 - "belief",
1460 - "brand",
1461 - "ceiling",
1462 - "cheese",
1463 - "clue",
1464 - "confidence",
1465 - "connection",
1466 - "daily",
1467 - "disguise",
1468 - "eager",
1469 - "erase",
1470 - "essence",
1471 - "everytime",
1472 - "expression",
1473 - "fan",
1474 - "flag",
1475 - "flirt",
1476 - "foul",
1477 - "fur",
1478 - "giggle",
1479 - "glorious",
1480 - "ignorance",
1481 - "law",
1482 - "lifeless",
1483 - "measure",
1484 - "mighty",
1485 - "muse",
1486 - "north",
1487 - "opposite",
1488 - "paradise",
1489 - "patience",
1490 - "patient",
1491 - "pencil",
1492 - "petal",
1493 - "plate",
1494 - "ponder",
1495 - "possibly",
1496 - "practice",
1497 - "slice",
1498 - "spell",
1499 - "stock",
1500 - "strife",
1501 - "strip",
1502 - "suffocate",
1503 - "suit",
1504 - "tender",
1505 - "tool",
1506 - "trade",
1507 - "velvet",
1508 - "verse",
1509 - "waist",
1510 - "witch",
1511 - "aunt",
1512 - "bench",
1513 - "bold",
1514 - "cap",
1515 - "certainly",
1516 - "click",
1517 - "companion",
1518 - "creator",
1519 - "dart",
1520 - "delicate",
1521 - "determine",
1522 - "dish",
1523 - "dragon",
1524 - "drama",
1525 - "drum",
1526 - "dude",
1527 - "everybody",
1528 - "feast",
1529 - "forehead",
1530 - "former",
1531 - "fright",
1532 - "fully",
1533 - "gas",
1534 - "hook",
1535 - "hurl",
1536 - "invite",
1537 - "juice",
1538 - "manage",
1539 - "moral",
1540 - "possess",
1541 - "raw",
1542 - "rebel",
1543 - "royal",
1544 - "scale",
1545 - "scary",
1546 - "several",
1547 - "slight",
1548 - "stubborn",
1549 - "swell",
1550 - "talent",
1551 - "tea",
1552 - "terrible",
1553 - "thread",
1554 - "torment",
1555 - "trickle",
1556 - "usually",
1557 - "vast",
1558 - "violence",
1559 - "weave",
1560 - "acid",
1561 - "agony",
1562 - "ashamed",
1563 - "awe",
1564 - "belly",
1565 - "blend",
1566 - "blush",
1567 - "character",
1568 - "cheat",
1569 - "common",
1570 - "company",
1571 - "coward",
1572 - "creak",
1573 - "danger",
1574 - "deadly",
1575 - "defense",
1576 - "define",
1577 - "depend",
1578 - "desperate",
1579 - "destination",
1580 - "dew",
1581 - "duck",
1582 - "dusty",
1583 - "embarrass",
1584 - "engine",
1585 - "example",
1586 - "explore",
1587 - "foe",
1588 - "freely",
1589 - "frustrate",
1590 - "generation",
1591 - "glove",
1592 - "guilty",
1593 - "health",
1594 - "hurry",
1595 - "idiot",
1596 - "impossible",
1597 - "inhale",
1598 - "jaw",
1599 - "kingdom",
1600 - "mention",
1601 - "mist",
1602 - "moan",
1603 - "mumble",
1604 - "mutter",
1605 - "observe",
1606 - "ode",
1607 - "pathetic",
1608 - "pattern",
1609 - "pie",
1610 - "prefer",
1611 - "puff",
1612 - "rape",
1613 - "rare",
1614 - "revenge",
1615 - "rude",
1616 - "scrape",
1617 - "spiral",
1618 - "squeeze",
1619 - "strain",
1620 - "sunset",
1621 - "suspend",
1622 - "sympathy",
1623 - "thigh",
1624 - "throne",
1625 - "total",
1626 - "unseen",
1627 - "weapon",
1628 - "weary"
3 + "like",
4 + "just",
5 + "love",
6 + "know",
7 + "never",
8 + "want",
9 + "time",
10 + "out",
11 + "there",
12 + "make",
13 + "look",
14 + "eye",
15 + "down",
16 + "only",
17 + "think",
18 + "heart",
19 + "back",
20 + "then",
21 + "into",
22 + "about",
23 + "more",
24 + "away",
25 + "still",
26 + "them",
27 + "take",
28 + "thing",
29 + "even",
30 + "through",
31 + "long",
32 + "always",
33 + "world",
34 + "too",
35 + "friend",
36 + "tell",
37 + "try",
38 + "hand",
39 + "thought",
40 + "over",
41 + "here",
42 + "other",
43 + "need",
44 + "smile",
45 + "again",
46 + "much",
47 + "cry",
48 + "been",
49 + "night",
50 + "ever",
51 + "little",
52 + "said",
53 + "end",
54 + "some",
55 + "those",
56 + "around",
57 + "mind",
58 + "people",
59 + "girl",
60 + "leave",
61 + "dream",
62 + "left",
63 + "turn",
64 + "myself",
65 + "give",
66 + "nothing",
67 + "really",
68 + "off",
69 + "before",
70 + "something",
71 + "find",
72 + "walk",
73 + "wish",
74 + "good",
75 + "once",
76 + "place",
77 + "ask",
78 + "stop",
79 + "keep",
80 + "watch",
81 + "seem",
82 + "everything",
83 + "wait",
84 + "got",
85 + "yet",
86 + "made",
87 + "remember",
88 + "start",
89 + "alone",
90 + "run",
91 + "hope",
92 + "maybe",
93 + "believe",
94 + "body",
95 + "hate",
96 + "after",
97 + "close",
98 + "talk",
99 + "stand",
100 + "own",
101 + "each",
102 + "hurt",
103 + "help",
104 + "home",
105 + "god",
106 + "soul",
107 + "new",
108 + "many",
109 + "two",
110 + "inside",
111 + "should",
112 + "true",
113 + "first",
114 + "fear",
115 + "mean",
116 + "better",
117 + "play",
118 + "another",
119 + "gone",
120 + "change",
121 + "use",
122 + "wonder",
123 + "someone",
124 + "hair",
125 + "cold",
126 + "open",
127 + "best",
128 + "any",
129 + "behind",
130 + "happen",
131 + "water",
132 + "dark",
133 + "laugh",
134 + "stay",
135 + "forever",
136 + "name",
137 + "work",
138 + "show",
139 + "sky",
140 + "break",
141 + "came",
142 + "deep",
143 + "door",
144 + "put",
145 + "black",
146 + "together",
147 + "upon",
148 + "happy",
149 + "such",
150 + "great",
151 + "white",
152 + "matter",
153 + "fill",
154 + "past",
155 + "please",
156 + "burn",
157 + "cause",
158 + "enough",
159 + "touch",
160 + "moment",
161 + "soon",
162 + "voice",
163 + "scream",
164 + "anything",
165 + "stare",
166 + "sound",
167 + "red",
168 + "everyone",
169 + "hide",
170 + "kiss",
171 + "truth",
172 + "death",
173 + "beautiful",
174 + "mine",
175 + "blood",
176 + "broken",
177 + "very",
178 + "pass",
179 + "next",
180 + "forget",
181 + "tree",
182 + "wrong",
183 + "air",
184 + "mother",
185 + "understand",
186 + "lip",
187 + "hit",
188 + "wall",
189 + "memory",
190 + "sleep",
191 + "free",
192 + "high",
193 + "realize",
194 + "school",
195 + "might",
196 + "skin",
197 + "sweet",
198 + "perfect",
199 + "blue",
200 + "kill",
201 + "breath",
202 + "dance",
203 + "against",
204 + "fly",
205 + "between",
206 + "grow",
207 + "strong",
208 + "under",
209 + "listen",
210 + "bring",
211 + "sometimes",
212 + "speak",
213 + "pull",
214 + "person",
215 + "become",
216 + "family",
217 + "begin",
218 + "ground",
219 + "real",
220 + "small",
221 + "father",
222 + "sure",
223 + "feet",
224 + "rest",
225 + "young",
226 + "finally",
227 + "land",
228 + "across",
229 + "today",
230 + "different",
231 + "guy",
232 + "line",
233 + "fire",
234 + "reason",
235 + "reach",
236 + "second",
237 + "slowly",
238 + "write",
239 + "eat",
240 + "smell",
241 + "mouth",
242 + "step",
243 + "learn",
244 + "three",
245 + "floor",
246 + "promise",
247 + "breathe",
248 + "darkness",
249 + "push",
250 + "earth",
251 + "guess",
252 + "save",
253 + "song",
254 + "above",
255 + "along",
256 + "both",
257 + "color",
258 + "house",
259 + "almost",
260 + "sorry",
261 + "anymore",
262 + "brother",
263 + "okay",
264 + "dear",
265 + "game",
266 + "fade",
267 + "already",
268 + "apart",
269 + "warm",
270 + "beauty",
271 + "heard",
272 + "notice",
273 + "question",
274 + "shine",
275 + "began",
276 + "piece",
277 + "whole",
278 + "shadow",
279 + "secret",
280 + "street",
281 + "within",
282 + "finger",
283 + "point",
284 + "morning",
285 + "whisper",
286 + "child",
287 + "moon",
288 + "green",
289 + "story",
290 + "glass",
291 + "kid",
292 + "silence",
293 + "since",
294 + "soft",
295 + "yourself",
296 + "empty",
297 + "shall",
298 + "angel",
299 + "answer",
300 + "baby",
301 + "bright",
302 + "dad",
303 + "path",
304 + "worry",
305 + "hour",
306 + "drop",
307 + "follow",
308 + "power",
309 + "war",
310 + "half",
311 + "flow",
312 + "heaven",
313 + "act",
314 + "chance",
315 + "fact",
316 + "least",
317 + "tired",
318 + "children",
319 + "near",
320 + "quite",
321 + "afraid",
322 + "rise",
323 + "sea",
324 + "taste",
325 + "window",
326 + "cover",
327 + "nice",
328 + "trust",
329 + "lot",
330 + "sad",
331 + "cool",
332 + "force",
333 + "peace",
334 + "return",
335 + "blind",
336 + "easy",
337 + "ready",
338 + "roll",
339 + "rose",
340 + "drive",
341 + "held",
342 + "music",
343 + "beneath",
344 + "hang",
345 + "mom",
346 + "paint",
347 + "emotion",
348 + "quiet",
349 + "clear",
350 + "cloud",
351 + "few",
352 + "pretty",
353 + "bird",
354 + "outside",
355 + "paper",
356 + "picture",
357 + "front",
358 + "rock",
359 + "simple",
360 + "anyone",
361 + "meant",
362 + "reality",
363 + "road",
364 + "sense",
365 + "waste",
366 + "bit",
367 + "leaf",
368 + "thank",
369 + "happiness",
370 + "meet",
371 + "men",
372 + "smoke",
373 + "truly",
374 + "decide",
375 + "self",
376 + "age",
377 + "book",
378 + "form",
379 + "alive",
380 + "carry",
381 + "escape",
382 + "damn",
383 + "instead",
384 + "able",
385 + "ice",
386 + "minute",
387 + "throw",
388 + "catch",
389 + "leg",
390 + "ring",
391 + "course",
392 + "goodbye",
393 + "lead",
394 + "poem",
395 + "sick",
396 + "corner",
397 + "desire",
398 + "known",
399 + "problem",
400 + "remind",
401 + "shoulder",
402 + "suppose",
403 + "toward",
404 + "wave",
405 + "drink",
406 + "jump",
407 + "woman",
408 + "pretend",
409 + "sister",
410 + "week",
411 + "human",
412 + "joy",
413 + "crack",
414 + "grey",
415 + "pray",
416 + "surprise",
417 + "dry",
418 + "knee",
419 + "less",
420 + "search",
421 + "bleed",
422 + "caught",
423 + "clean",
424 + "embrace",
425 + "future",
426 + "king",
427 + "son",
428 + "sorrow",
429 + "chest",
430 + "hug",
431 + "remain",
432 + "sat",
433 + "worth",
434 + "blow",
435 + "daddy",
436 + "final",
437 + "parent",
438 + "tight",
439 + "also",
440 + "create",
441 + "lonely",
442 + "safe",
443 + "cross",
444 + "dress",
445 + "evil",
446 + "silent",
447 + "bone",
448 + "fate",
449 + "perhaps",
450 + "anger",
451 + "class",
452 + "scar",
453 + "snow",
454 + "tiny",
455 + "tonight",
456 + "continue",
457 + "control",
458 + "dog",
459 + "edge",
460 + "mirror",
461 + "month",
462 + "suddenly",
463 + "comfort",
464 + "given",
465 + "loud",
466 + "quickly",
467 + "gaze",
468 + "plan",
469 + "rush",
470 + "stone",
471 + "town",
472 + "battle",
473 + "ignore",
474 + "spirit",
475 + "stood",
476 + "stupid",
477 + "yours",
478 + "brown",
479 + "build",
480 + "dust",
481 + "hey",
482 + "kept",
483 + "pay",
484 + "phone",
485 + "twist",
486 + "although",
487 + "ball",
488 + "beyond",
489 + "hidden",
490 + "nose",
491 + "taken",
492 + "fail",
493 + "float",
494 + "pure",
495 + "somehow",
496 + "wash",
497 + "wrap",
498 + "angry",
499 + "cheek",
500 + "creature",
501 + "forgotten",
502 + "heat",
503 + "rip",
504 + "single",
505 + "space",
506 + "special",
507 + "weak",
508 + "whatever",
509 + "yell",
510 + "anyway",
511 + "blame",
512 + "job",
513 + "choose",
514 + "country",
515 + "curse",
516 + "drift",
517 + "echo",
518 + "figure",
519 + "grew",
520 + "laughter",
521 + "neck",
522 + "suffer",
523 + "worse",
524 + "yeah",
525 + "disappear",
526 + "foot",
527 + "forward",
528 + "knife",
529 + "mess",
530 + "somewhere",
531 + "stomach",
532 + "storm",
533 + "beg",
534 + "idea",
535 + "lift",
536 + "offer",
537 + "breeze",
538 + "field",
539 + "five",
540 + "often",
541 + "simply",
542 + "stuck",
543 + "win",
544 + "allow",
545 + "confuse",
546 + "enjoy",
547 + "except",
548 + "flower",
549 + "seek",
550 + "strength",
551 + "calm",
552 + "grin",
553 + "gun",
554 + "heavy",
555 + "hill",
556 + "large",
557 + "ocean",
558 + "shoe",
559 + "sigh",
560 + "straight",
561 + "summer",
562 + "tongue",
563 + "accept",
564 + "crazy",
565 + "everyday",
566 + "exist",
567 + "grass",
568 + "mistake",
569 + "sent",
570 + "shut",
571 + "surround",
572 + "table",
573 + "ache",
574 + "brain",
575 + "destroy",
576 + "heal",
577 + "nature",
578 + "shout",
579 + "sign",
580 + "stain",
581 + "choice",
582 + "doubt",
583 + "glance",
584 + "glow",
585 + "mountain",
586 + "queen",
587 + "stranger",
588 + "throat",
589 + "tomorrow",
590 + "city",
591 + "either",
592 + "fish",
593 + "flame",
594 + "rather",
595 + "shape",
596 + "spin",
597 + "spread",
598 + "ash",
599 + "distance",
600 + "finish",
601 + "image",
602 + "imagine",
603 + "important",
604 + "nobody",
605 + "shatter",
606 + "warmth",
607 + "became",
608 + "feed",
609 + "flesh",
610 + "funny",
611 + "lust",
612 + "shirt",
613 + "trouble",
614 + "yellow",
615 + "attention",
616 + "bare",
617 + "bite",
618 + "money",
619 + "protect",
620 + "amaze",
621 + "appear",
622 + "born",
623 + "choke",
624 + "completely",
625 + "daughter",
626 + "fresh",
627 + "friendship",
628 + "gentle",
629 + "probably",
630 + "six",
631 + "deserve",
632 + "expect",
633 + "grab",
634 + "middle",
635 + "nightmare",
636 + "river",
637 + "thousand",
638 + "weight",
639 + "worst",
640 + "wound",
641 + "barely",
642 + "bottle",
643 + "cream",
644 + "regret",
645 + "relationship",
646 + "stick",
647 + "test",
648 + "crush",
649 + "endless",
650 + "fault",
651 + "itself",
652 + "rule",
653 + "spill",
654 + "art",
655 + "circle",
656 + "join",
657 + "kick",
658 + "mask",
659 + "master",
660 + "passion",
661 + "quick",
662 + "raise",
663 + "smooth",
664 + "unless",
665 + "wander",
666 + "actually",
667 + "broke",
668 + "chair",
669 + "deal",
670 + "favorite",
671 + "gift",
672 + "note",
673 + "number",
674 + "sweat",
675 + "box",
676 + "chill",
677 + "clothes",
678 + "lady",
679 + "mark",
680 + "park",
681 + "poor",
682 + "sadness",
683 + "tie",
684 + "animal",
685 + "belong",
686 + "brush",
687 + "consume",
688 + "dawn",
689 + "forest",
690 + "innocent",
691 + "pen",
692 + "pride",
693 + "stream",
694 + "thick",
695 + "clay",
696 + "complete",
697 + "count",
698 + "draw",
699 + "faith",
700 + "press",
701 + "silver",
702 + "struggle",
703 + "surface",
704 + "taught",
705 + "teach",
706 + "wet",
707 + "bless",
708 + "chase",
709 + "climb",
710 + "enter",
711 + "letter",
712 + "melt",
713 + "metal",
714 + "movie",
715 + "stretch",
716 + "swing",
717 + "vision",
718 + "wife",
719 + "beside",
720 + "crash",
721 + "forgot",
722 + "guide",
723 + "haunt",
724 + "joke",
725 + "knock",
726 + "plant",
727 + "pour",
728 + "prove",
729 + "reveal",
730 + "steal",
731 + "stuff",
732 + "trip",
733 + "wood",
734 + "wrist",
735 + "bother",
736 + "bottom",
737 + "crawl",
738 + "crowd",
739 + "fix",
740 + "forgive",
741 + "frown",
742 + "grace",
743 + "loose",
744 + "lucky",
745 + "party",
746 + "release",
747 + "surely",
748 + "survive",
749 + "teacher",
750 + "gently",
751 + "grip",
752 + "speed",
753 + "suicide",
754 + "travel",
755 + "treat",
756 + "vein",
757 + "written",
758 + "cage",
759 + "chain",
760 + "conversation",
761 + "date",
762 + "enemy",
763 + "however",
764 + "interest",
765 + "million",
766 + "page",
767 + "pink",
768 + "proud",
769 + "sway",
770 + "themselves",
771 + "winter",
772 + "church",
773 + "cruel",
774 + "cup",
775 + "demon",
776 + "experience",
777 + "freedom",
778 + "pair",
779 + "pop",
780 + "purpose",
781 + "respect",
782 + "shoot",
783 + "softly",
784 + "state",
785 + "strange",
786 + "bar",
787 + "birth",
788 + "curl",
789 + "dirt",
790 + "excuse",
791 + "lord",
792 + "lovely",
793 + "monster",
794 + "order",
795 + "pack",
796 + "pants",
797 + "pool",
798 + "scene",
799 + "seven",
800 + "shame",
801 + "slide",
802 + "ugly",
803 + "among",
804 + "blade",
805 + "blonde",
806 + "closet",
807 + "creek",
808 + "deny",
809 + "drug",
810 + "eternity",
811 + "gain",
812 + "grade",
813 + "handle",
814 + "key",
815 + "linger",
816 + "pale",
817 + "prepare",
818 + "swallow",
819 + "swim",
820 + "tremble",
821 + "wheel",
822 + "won",
823 + "cast",
824 + "cigarette",
825 + "claim",
826 + "college",
827 + "direction",
828 + "dirty",
829 + "gather",
830 + "ghost",
831 + "hundred",
832 + "loss",
833 + "lung",
834 + "orange",
835 + "present",
836 + "swear",
837 + "swirl",
838 + "twice",
839 + "wild",
840 + "bitter",
841 + "blanket",
842 + "doctor",
843 + "everywhere",
844 + "flash",
845 + "grown",
846 + "knowledge",
847 + "numb",
848 + "pressure",
849 + "radio",
850 + "repeat",
851 + "ruin",
852 + "spend",
853 + "unknown",
854 + "buy",
855 + "clock",
856 + "devil",
857 + "early",
858 + "false",
859 + "fantasy",
860 + "pound",
861 + "precious",
862 + "refuse",
863 + "sheet",
864 + "teeth",
865 + "welcome",
866 + "add",
867 + "ahead",
868 + "block",
869 + "bury",
870 + "caress",
871 + "content",
872 + "depth",
873 + "despite",
874 + "distant",
875 + "marry",
876 + "purple",
877 + "threw",
878 + "whenever",
879 + "bomb",
880 + "dull",
881 + "easily",
882 + "grasp",
883 + "hospital",
884 + "innocence",
885 + "normal",
886 + "receive",
887 + "reply",
888 + "rhyme",
889 + "shade",
890 + "someday",
891 + "sword",
892 + "toe",
893 + "visit",
894 + "asleep",
895 + "bought",
896 + "center",
897 + "consider",
898 + "flat",
899 + "hero",
900 + "history",
901 + "ink",
902 + "insane",
903 + "muscle",
904 + "mystery",
905 + "pocket",
906 + "reflection",
907 + "shove",
908 + "silently",
909 + "smart",
910 + "soldier",
911 + "spot",
912 + "stress",
913 + "train",
914 + "type",
915 + "view",
916 + "whether",
917 + "bus",
918 + "energy",
919 + "explain",
920 + "holy",
921 + "hunger",
922 + "inch",
923 + "magic",
924 + "mix",
925 + "noise",
926 + "nowhere",
927 + "prayer",
928 + "presence",
929 + "shock",
930 + "snap",
931 + "spider",
932 + "study",
933 + "thunder",
934 + "trail",
935 + "admit",
936 + "agree",
937 + "bag",
938 + "bang",
939 + "bound",
940 + "butterfly",
941 + "cute",
942 + "exactly",
943 + "explode",
944 + "familiar",
945 + "fold",
946 + "further",
947 + "pierce",
948 + "reflect",
949 + "scent",
950 + "selfish",
951 + "sharp",
952 + "sink",
953 + "spring",
954 + "stumble",
955 + "universe",
956 + "weep",
957 + "women",
958 + "wonderful",
959 + "action",
960 + "ancient",
961 + "attempt",
962 + "avoid",
963 + "birthday",
964 + "branch",
965 + "chocolate",
966 + "core",
967 + "depress",
968 + "drunk",
969 + "especially",
970 + "focus",
971 + "fruit",
972 + "honest",
973 + "match",
974 + "palm",
975 + "perfectly",
976 + "pillow",
977 + "pity",
978 + "poison",
979 + "roar",
980 + "shift",
981 + "slightly",
982 + "thump",
983 + "truck",
984 + "tune",
985 + "twenty",
986 + "unable",
987 + "wipe",
988 + "wrote",
989 + "coat",
990 + "constant",
991 + "dinner",
992 + "drove",
993 + "egg",
994 + "eternal",
995 + "flight",
996 + "flood",
997 + "frame",
998 + "freak",
999 + "gasp",
1000 + "glad",
1001 + "hollow",
1002 + "motion",
1003 + "peer",
1004 + "plastic",
1005 + "root",
1006 + "screen",
1007 + "season",
1008 + "sting",
1009 + "strike",
1010 + "team",
1011 + "unlike",
1012 + "victim",
1013 + "volume",
1014 + "warn",
1015 + "weird",
1016 + "attack",
1017 + "await",
1018 + "awake",
1019 + "built",
1020 + "charm",
1021 + "crave",
1022 + "despair",
1023 + "fought",
1024 + "grant",
1025 + "grief",
1026 + "horse",
1027 + "limit",
1028 + "message",
1029 + "ripple",
1030 + "sanity",
1031 + "scatter",
1032 + "serve",
1033 + "split",
1034 + "string",
1035 + "trick",
1036 + "annoy",
1037 + "blur",
1038 + "boat",
1039 + "brave",
1040 + "clearly",
1041 + "cling",
1042 + "connect",
1043 + "fist",
1044 + "forth",
1045 + "imagination",
1046 + "iron",
1047 + "jock",
1048 + "judge",
1049 + "lesson",
1050 + "milk",
1051 + "misery",
1052 + "nail",
1053 + "naked",
1054 + "ourselves",
1055 + "poet",
1056 + "possible",
1057 + "princess",
1058 + "sail",
1059 + "size",
1060 + "snake",
1061 + "society",
1062 + "stroke",
1063 + "torture",
1064 + "toss",
1065 + "trace",
1066 + "wise",
1067 + "bloom",
1068 + "bullet",
1069 + "cell",
1070 + "check",
1071 + "cost",
1072 + "darling",
1073 + "during",
1074 + "footstep",
1075 + "fragile",
1076 + "hallway",
1077 + "hardly",
1078 + "horizon",
1079 + "invisible",
1080 + "journey",
1081 + "midnight",
1082 + "mud",
1083 + "nod",
1084 + "pause",
1085 + "relax",
1086 + "shiver",
1087 + "sudden",
1088 + "value",
1089 + "youth",
1090 + "abuse",
1091 + "admire",
1092 + "blink",
1093 + "breast",
1094 + "bruise",
1095 + "constantly",
1096 + "couple",
1097 + "creep",
1098 + "curve",
1099 + "difference",
1100 + "dumb",
1101 + "emptiness",
1102 + "gotta",
1103 + "honor",
1104 + "plain",
1105 + "planet",
1106 + "recall",
1107 + "rub",
1108 + "ship",
1109 + "slam",
1110 + "soar",
1111 + "somebody",
1112 + "tightly",
1113 + "weather",
1114 + "adore",
1115 + "approach",
1116 + "bond",
1117 + "bread",
1118 + "burst",
1119 + "candle",
1120 + "coffee",
1121 + "cousin",
1122 + "crime",
1123 + "desert",
1124 + "flutter",
1125 + "frozen",
1126 + "grand",
1127 + "heel",
1128 + "hello",
1129 + "language",
1130 + "level",
1131 + "movement",
1132 + "pleasure",
1133 + "powerful",
1134 + "random",
1135 + "rhythm",
1136 + "settle",
1137 + "silly",
1138 + "slap",
1139 + "sort",
1140 + "spoken",
1141 + "steel",
1142 + "threaten",
1143 + "tumble",
1144 + "upset",
1145 + "aside",
1146 + "awkward",
1147 + "bee",
1148 + "blank",
1149 + "board",
1150 + "button",
1151 + "card",
1152 + "carefully",
1153 + "complain",
1154 + "crap",
1155 + "deeply",
1156 + "discover",
1157 + "drag",
1158 + "dread",
1159 + "effort",
1160 + "entire",
1161 + "fairy",
1162 + "giant",
1163 + "gotten",
1164 + "greet",
1165 + "illusion",
1166 + "jeans",
1167 + "leap",
1168 + "liquid",
1169 + "march",
1170 + "mend",
1171 + "nervous",
1172 + "nine",
1173 + "replace",
1174 + "rope",
1175 + "spine",
1176 + "stole",
1177 + "terror",
1178 + "accident",
1179 + "apple",
1180 + "balance",
1181 + "boom",
1182 + "childhood",
1183 + "collect",
1184 + "demand",
1185 + "depression",
1186 + "eventually",
1187 + "faint",
1188 + "glare",
1189 + "goal",
1190 + "group",
1191 + "honey",
1192 + "kitchen",
1193 + "laid",
1194 + "limb",
1195 + "machine",
1196 + "mere",
1197 + "mold",
1198 + "murder",
1199 + "nerve",
1200 + "painful",
1201 + "poetry",
1202 + "prince",
1203 + "rabbit",
1204 + "shelter",
1205 + "shore",
1206 + "shower",
1207 + "soothe",
1208 + "stair",
1209 + "steady",
1210 + "sunlight",
1211 + "tangle",
1212 + "tease",
1213 + "treasure",
1214 + "uncle",
1215 + "begun",
1216 + "bliss",
1217 + "canvas",
1218 + "cheer",
1219 + "claw",
1220 + "clutch",
1221 + "commit",
1222 + "crimson",
1223 + "crystal",
1224 + "delight",
1225 + "doll",
1226 + "existence",
1227 + "express",
1228 + "fog",
1229 + "football",
1230 + "gay",
1231 + "goose",
1232 + "guard",
1233 + "hatred",
1234 + "illuminate",
1235 + "mass",
1236 + "math",
1237 + "mourn",
1238 + "rich",
1239 + "rough",
1240 + "skip",
1241 + "stir",
1242 + "student",
1243 + "style",
1244 + "support",
1245 + "thorn",
1246 + "tough",
1247 + "yard",
1248 + "yearn",
1249 + "yesterday",
1250 + "advice",
1251 + "appreciate",
1252 + "autumn",
1253 + "bank",
1254 + "beam",
1255 + "bowl",
1256 + "capture",
1257 + "carve",
1258 + "collapse",
1259 + "confusion",
1260 + "creation",
1261 + "dove",
1262 + "feather",
1263 + "girlfriend",
1264 + "glory",
1265 + "government",
1266 + "harsh",
1267 + "hop",
1268 + "inner",
1269 + "loser",
1270 + "moonlight",
1271 + "neighbor",
1272 + "neither",
1273 + "peach",
1274 + "pig",
1275 + "praise",
1276 + "screw",
1277 + "shield",
1278 + "shimmer",
1279 + "sneak",
1280 + "stab",
1281 + "subject",
1282 + "throughout",
1283 + "thrown",
1284 + "tower",
1285 + "twirl",
1286 + "wow",
1287 + "army",
1288 + "arrive",
1289 + "bathroom",
1290 + "bump",
1291 + "cease",
1292 + "cookie",
1293 + "couch",
1294 + "courage",
1295 + "dim",
1296 + "guilt",
1297 + "howl",
1298 + "hum",
1299 + "husband",
1300 + "insult",
1301 + "led",
1302 + "lunch",
1303 + "mock",
1304 + "mostly",
1305 + "natural",
1306 + "nearly",
1307 + "needle",
1308 + "nerd",
1309 + "peaceful",
1310 + "perfection",
1311 + "pile",
1312 + "price",
1313 + "remove",
1314 + "roam",
1315 + "sanctuary",
1316 + "serious",
1317 + "shiny",
1318 + "shook",
1319 + "sob",
1320 + "stolen",
1321 + "tap",
1322 + "vain",
1323 + "void",
1324 + "warrior",
1325 + "wrinkle",
1326 + "affection",
1327 + "apologize",
1328 + "blossom",
1329 + "bounce",
1330 + "bridge",
1331 + "cheap",
1332 + "crumble",
1333 + "decision",
1334 + "descend",
1335 + "desperately",
1336 + "dig",
1337 + "dot",
1338 + "flip",
1339 + "frighten",
1340 + "heartbeat",
1341 + "huge",
1342 + "lazy",
1343 + "lick",
1344 + "odd",
1345 + "opinion",
1346 + "process",
1347 + "puzzle",
1348 + "quietly",
1349 + "retreat",
1350 + "score",
1351 + "sentence",
1352 + "separate",
1353 + "situation",
1354 + "skill",
1355 + "soak",
1356 + "square",
1357 + "stray",
1358 + "taint",
1359 + "task",
1360 + "tide",
1361 + "underneath",
1362 + "veil",
1363 + "whistle",
1364 + "anywhere",
1365 + "bedroom",
1366 + "bid",
1367 + "bloody",
1368 + "burden",
1369 + "careful",
1370 + "compare",
1371 + "concern",
1372 + "curtain",
1373 + "decay",
1374 + "defeat",
1375 + "describe",
1376 + "double",
1377 + "dreamer",
1378 + "driver",
1379 + "dwell",
1380 + "evening",
1381 + "flare",
1382 + "flicker",
1383 + "grandma",
1384 + "guitar",
1385 + "harm",
1386 + "horrible",
1387 + "hungry",
1388 + "indeed",
1389 + "lace",
1390 + "melody",
1391 + "monkey",
1392 + "nation",
1393 + "object",
1394 + "obviously",
1395 + "rainbow",
1396 + "salt",
1397 + "scratch",
1398 + "shown",
1399 + "shy",
1400 + "stage",
1401 + "stun",
1402 + "third",
1403 + "tickle",
1404 + "useless",
1405 + "weakness",
1406 + "worship",
1407 + "worthless",
1408 + "afternoon",
1409 + "beard",
1410 + "boyfriend",
1411 + "bubble",
1412 + "busy",
1413 + "certain",
1414 + "chin",
1415 + "concrete",
1416 + "desk",
1417 + "diamond",
1418 + "doom",
1419 + "drawn",
1420 + "due",
1421 + "felicity",
1422 + "freeze",
1423 + "frost",
1424 + "garden",
1425 + "glide",
1426 + "harmony",
1427 + "hopefully",
1428 + "hunt",
1429 + "jealous",
1430 + "lightning",
1431 + "mama",
1432 + "mercy",
1433 + "peel",
1434 + "physical",
1435 + "position",
1436 + "pulse",
1437 + "punch",
1438 + "quit",
1439 + "rant",
1440 + "respond",
1441 + "salty",
1442 + "sane",
1443 + "satisfy",
1444 + "savior",
1445 + "sheep",
1446 + "slept",
1447 + "social",
1448 + "sport",
1449 + "tuck",
1450 + "utter",
1451 + "valley",
1452 + "wolf",
1453 + "aim",
1454 + "alas",
1455 + "alter",
1456 + "arrow",
1457 + "awaken",
1458 + "beaten",
1459 + "belief",
1460 + "brand",
1461 + "ceiling",
1462 + "cheese",
1463 + "clue",
1464 + "confidence",
1465 + "connection",
1466 + "daily",
1467 + "disguise",
1468 + "eager",
1469 + "erase",
1470 + "essence",
1471 + "everytime",
1472 + "expression",
1473 + "fan",
1474 + "flag",
1475 + "flirt",
1476 + "foul",
1477 + "fur",
1478 + "giggle",
1479 + "glorious",
1480 + "ignorance",
1481 + "law",
1482 + "lifeless",
1483 + "measure",
1484 + "mighty",
1485 + "muse",
1486 + "north",
1487 + "opposite",
1488 + "paradise",
1489 + "patience",
1490 + "patient",
1491 + "pencil",
1492 + "petal",
1493 + "plate",
1494 + "ponder",
1495 + "possibly",
1496 + "practice",
1497 + "slice",
1498 + "spell",
1499 + "stock",
1500 + "strife",
1501 + "strip",
1502 + "suffocate",
1503 + "suit",
1504 + "tender",
1505 + "tool",
1506 + "trade",
1507 + "velvet",
1508 + "verse",
1509 + "waist",
1510 + "witch",
1511 + "aunt",
1512 + "bench",
1513 + "bold",
1514 + "cap",
1515 + "certainly",
1516 + "click",
1517 + "companion",
1518 + "creator",
1519 + "dart",
1520 + "delicate",
1521 + "determine",
1522 + "dish",
1523 + "dragon",
1524 + "drama",
1525 + "drum",
1526 + "dude",
1527 + "everybody",
1528 + "feast",
1529 + "forehead",
1530 + "former",
1531 + "fright",
1532 + "fully",
1533 + "gas",
1534 + "hook",
1535 + "hurl",
1536 + "invite",
1537 + "juice",
1538 + "manage",
1539 + "moral",
1540 + "possess",
1541 + "raw",
1542 + "rebel",
1543 + "royal",
1544 + "scale",
1545 + "scary",
1546 + "several",
1547 + "slight",
1548 + "stubborn",
1549 + "swell",
1550 + "talent",
1551 + "tea",
1552 + "terrible",
1553 + "thread",
1554 + "torment",
1555 + "trickle",
1556 + "usually",
1557 + "vast",
1558 + "violence",
1559 + "weave",
1560 + "acid",
1561 + "agony",
1562 + "ashamed",
1563 + "awe",
1564 + "belly",
1565 + "blend",
1566 + "blush",
1567 + "character",
1568 + "cheat",
1569 + "common",
1570 + "company",
1571 + "coward",
1572 + "creak",
1573 + "danger",
1574 + "deadly",
1575 + "defense",
1576 + "define",
1577 + "depend",
1578 + "desperate",
1579 + "destination",
1580 + "dew",
1581 + "duck",
1582 + "dusty",
1583 + "embarrass",
1584 + "engine",
1585 + "example",
1586 + "explore",
1587 + "foe",
1588 + "freely",
1589 + "frustrate",
1590 + "generation",
1591 + "glove",
1592 + "guilty",
1593 + "health",
1594 + "hurry",
1595 + "idiot",
1596 + "impossible",
1597 + "inhale",
1598 + "jaw",
1599 + "kingdom",
1600 + "mention",
1601 + "mist",
1602 + "moan",
1603 + "mumble",
1604 + "mutter",
1605 + "observe",
1606 + "ode",
1607 + "pathetic",
1608 + "pattern",
1609 + "pie",
1610 + "prefer",
1611 + "puff",
1612 + "rape",
1613 + "rare",
1614 + "revenge",
1615 + "rude",
1616 + "scrape",
1617 + "spiral",
1618 + "squeeze",
1619 + "strain",
1620 + "sunset",
1621 + "suspend",
1622 + "sympathy",
1623 + "thigh",
1624 + "throne",
1625 + "total",
1626 + "unseen",
1627 + "weapon",
1628 + "weary"
1629 ];
1630 }
cw_zano/lib/model/pending_zano_transaction.dart
+1 -1
@@ -41,7 +41,7 @@ class PendingZanoTransaction with PendingTransaction {
41 transferResult = await zanoWallet.transfer(destinations, fee.amount, comment);
42 zanoWallet.fetchTransactions();
43 }
44 -
44 +
45 @override
46 Future<Map<String, String>> commitUR() => throw UnimplementedError();
47 }
cw_zano/lib/model/zano_asset.dart
+1
@@ -0,0 +1 @@
1 +
cw_zano/lib/model/zano_transaction_creation_exception.dart
+1 -1
@@ -5,4 +5,4 @@ class ZanoTransactionCreationException implements Exception {
5
6 @override
7 String toString() => message;
8 -}
\ No newline at end of file
8 +}
cw_zano/lib/model/zano_transaction_credentials.dart
+2 -1
@@ -3,7 +3,8 @@ import 'package:cw_core/monero_transaction_priority.dart';
3 import 'package:cw_core/output_info.dart';
4
5 class ZanoTransactionCredentials {
6 - ZanoTransactionCredentials({required this.outputs, required this.priority, required this.currency});
6 + ZanoTransactionCredentials(
7 + {required this.outputs, required this.priority, required this.currency});
8
9 final List<OutputInfo> outputs;
10 final MoneroTransactionPriority priority;
cw_zano/lib/model/zano_transaction_info.dart
+7 -8
@@ -24,11 +24,11 @@ class ZanoTransactionInfo extends TransactionInfo {
24
25 ZanoTransactionInfo.fromTransfer(Transfer transfer,
26 {required int confirmations,
27 - required bool isIncome,
28 - required String assetId,
29 - required Money amount,
30 - this.tokenSymbol = 'ZANO',
31 - this.decimalPoint = ZanoFormatter.defaultDecimalPoint})
27 + required bool isIncome,
28 + required String assetId,
29 + required Money amount,
30 + this.tokenSymbol = 'ZANO',
31 + this.decimalPoint = ZanoFormatter.defaultDecimalPoint})
32 : id = transfer.txHash,
33 height = transfer.height,
34 direction = isIncome ? TransactionDirection.incoming : TransactionDirection.outgoing,
@@ -37,9 +37,8 @@ class ZanoTransactionInfo extends TransactionInfo {
37 fee = Money.fromInt(transfer.fee, CryptoCurrency.zano),
38 confirmations = confirmations,
39 isPending = confirmations < 10,
40 - recipientAddress = transfer.remoteAddresses.isNotEmpty
41 - ? transfer.remoteAddresses.first
42 - : '' {
40 + recipientAddress =
41 + transfer.remoteAddresses.isNotEmpty ? transfer.remoteAddresses.first : '' {
42 additionalInfo = <String, dynamic>{
43 'comment': transfer.comment,
44 'assetId': assetId,
cw_zano/lib/model/zano_wallet_keys.dart
+4 -4
@@ -1,12 +1,12 @@
1 class ZanoWalletKeys {
2 const ZanoWalletKeys(
3 {required this.privateSpendKey,
4 - required this.privateViewKey,
5 - required this.publicSpendKey,
6 - required this.publicViewKey});
4 + required this.privateViewKey,
5 + required this.publicSpendKey,
6 + required this.publicViewKey});
7
8 final String publicViewKey;
9 final String privateViewKey;
10 final String publicSpendKey;
11 final String privateSpendKey;
12 -}
\ No newline at end of file
12 +}
cw_zano/lib/zano_formatter.dart
+31 -23
@@ -18,46 +18,54 @@ class ZanoFormatter {
18 }
19
20 static String intAmountToString(int amount, [int decimalPoint = defaultDecimalPoint]) {
21 - final numberFormat = NumberFormat()..maximumFractionDigits = decimalPoint
22 - ..minimumFractionDigits = 1;
23 - return numberFormat.format(
24 - DecimalIntl(
25 - _bigIntDivision(
26 - amount: BigInt.from(amount),
27 - divider: BigInt.from(pow(10, decimalPoint)),
21 + final numberFormat = NumberFormat()
22 + ..maximumFractionDigits = decimalPoint
23 + ..minimumFractionDigits = 1;
24 + return numberFormat
25 + .format(
26 + DecimalIntl(
27 + _bigIntDivision(
28 + amount: BigInt.from(amount),
29 + divider: BigInt.from(pow(10, decimalPoint)),
30 + ),
31 ),
29 - ),
30 - )
31 - .replaceAll(',', '');
32 + )
33 + .replaceAll(',', '');
34 }
35
36 static String bigIntAmountToString(BigInt amount, [int decimalPoint = defaultDecimalPoint]) {
37 if (decimalPoint == 0) {
38 return '0';
39 }
38 - final numberFormat = NumberFormat()..maximumFractionDigits = decimalPoint
39 - ..minimumFractionDigits = 1;
40 - return numberFormat.format(
41 - DecimalIntl(
42 - _bigIntDivision(
43 - amount: amount,
44 - divider: BigInt.from(pow(10, decimalPoint)),
40 + final numberFormat = NumberFormat()
41 + ..maximumFractionDigits = decimalPoint
42 + ..minimumFractionDigits = 1;
43 + return numberFormat
44 + .format(
45 + DecimalIntl(
46 + _bigIntDivision(
47 + amount: amount,
48 + divider: BigInt.from(pow(10, decimalPoint)),
49 + ),
50 ),
46 - ),
47 - )
48 - .replaceAll(',', '');
51 + )
52 + .replaceAll(',', '');
53 }
54
51 - static double intAmountToDouble(int amount, [int decimalPoint = defaultDecimalPoint]) => _bigIntDivision(
55 + static double intAmountToDouble(int amount, [int decimalPoint = defaultDecimalPoint]) =>
56 + _bigIntDivision(
57 amount: BigInt.from(amount),
58 divider: BigInt.from(pow(10, decimalPoint)),
59 ).toDouble();
60
61 static int parseAmount(String amount, [int decimalPoint = defaultDecimalPoint]) {
57 - final resultBigInt = (Decimal.parse(amount) * Decimal.fromBigInt(BigInt.from(10).pow(decimalPoint))).toBigInt();
62 + final resultBigInt =
63 + (Decimal.parse(amount) * Decimal.fromBigInt(BigInt.from(10).pow(decimalPoint))).toBigInt();
64 if (!resultBigInt.isValidInt) {
65 try {
60 - Fluttertoast.showToast(msg: 'Cannot transfer $amount. Maximum is ${intAmountToString(resultBigInt.toInt(), decimalPoint)}.');
66 + Fluttertoast.showToast(
67 + msg:
68 + 'Cannot transfer $amount. Maximum is ${intAmountToString(resultBigInt.toInt(), decimalPoint)}.');
69 } catch (_) {}
70 }
71 return resultBigInt.toInt();
cw_zano/lib/zano_transaction_history.dart
+4 -6
@@ -5,11 +5,10 @@ import 'package:cw_zano/model/zano_transaction_info.dart';
5
6 part 'zano_transaction_history.g.dart';
7
8 -class ZanoTransactionHistory = ZanoTransactionHistoryBase
9 - with _$ZanoTransactionHistory;
8 +class ZanoTransactionHistory = ZanoTransactionHistoryBase with _$ZanoTransactionHistory;
9
11 -abstract class ZanoTransactionHistoryBase
12 - extends TransactionHistoryBase<ZanoTransactionInfo> with Store {
10 +abstract class ZanoTransactionHistoryBase extends TransactionHistoryBase<ZanoTransactionInfo>
11 + with Store {
12 ZanoTransactionHistoryBase() {
13 transactions = ObservableMap<String, ZanoTransactionInfo>();
14 }
@@ -18,8 +17,7 @@ abstract class ZanoTransactionHistoryBase
17 Future<void> save() async {}
18
19 @override
21 - void addOne(ZanoTransactionInfo transaction) =>
22 - transactions[transaction.id] = transaction;
20 + void addOne(ZanoTransactionInfo transaction) => transactions[transaction.id] = transaction;
21
22 @override
23 void addMany(Map<String, ZanoTransactionInfo> transactions) =>
cw_zano/lib/zano_wallet.dart
+12 -7
@@ -129,7 +129,8 @@ abstract class ZanoWalletBase
129 }
130
131 static Future<ZanoWallet> create({required WalletCredentials credentials}) async {
132 - final wallet = ZanoWallet(credentials.walletInfo!, await credentials.walletInfo!.getDerivationInfo(), credentials.password!);
132 + final wallet = ZanoWallet(credentials.walletInfo!,
133 + await credentials.walletInfo!.getDerivationInfo(), credentials.password!);
134 await wallet.initWallet();
135 final path = await pathForWallet(name: credentials.name, type: credentials.walletInfo!.type);
136 final createWalletResult = await wallet.createWallet(path, credentials.password!);
@@ -146,7 +147,8 @@ abstract class ZanoWalletBase
147
148 static Future<ZanoWallet> restore(
149 {required ZanoRestoreWalletFromSeedCredentials credentials}) async {
149 - final wallet = ZanoWallet(credentials.walletInfo!, await credentials.walletInfo!.getDerivationInfo(), credentials.password!);
150 + final wallet = ZanoWallet(credentials.walletInfo!,
151 + await credentials.walletInfo!.getDerivationInfo(), credentials.password!);
152 await wallet.initWallet();
153 final path = await pathForWallet(name: credentials.name, type: credentials.walletInfo!.type);
154 final createWalletResult = await wallet.restoreWalletFromSeed(
@@ -232,9 +234,12 @@ abstract class ZanoWalletBase
234 final isZano = credentials.currency == CryptoCurrency.zano;
235 final outputs = credentials.outputs;
236 final hasMultiDestination = outputs.length > 1;
235 - final unlockedBalanceZano = balance[CryptoCurrency.zano]?.unlocked ?? Money.zero(CryptoCurrency.zano);
236 - final unlockedBalanceCurrency = balance[credentials.currency]?.unlocked ?? Money.zero(credentials.currency);
237 - final fee = Money(BigInt.from(calculateEstimatedFee(credentials.priority)), CryptoCurrency.zano);
237 + final unlockedBalanceZano =
238 + balance[CryptoCurrency.zano]?.unlocked ?? Money.zero(CryptoCurrency.zano);
239 + final unlockedBalanceCurrency =
240 + balance[credentials.currency]?.unlocked ?? Money.zero(credentials.currency);
241 + final fee =
242 + Money(BigInt.from(calculateEstimatedFee(credentials.priority)), CryptoCurrency.zano);
243
244 var totalAmount = Money.zero(credentials.currency);
245 void checkForEnoughBalances() {
@@ -398,8 +403,8 @@ abstract class ZanoWalletBase
403 syncStatus = AttemptingSyncStatus();
404 _lastKnownBlockHeight = 0;
405 _initialSyncHeight = 0;
401 - _updateSyncInfoTimer ??=
402 - Timer.periodic(Duration(milliseconds: _pollIntervalMilliseconds), (_) => _updateSyncInfo());
406 + _updateSyncInfoTimer ??= Timer.periodic(
407 + Duration(milliseconds: _pollIntervalMilliseconds), (_) => _updateSyncInfo());
408 } catch (e) {
409 syncStatus = FailedSyncStatus();
410 printV((e.toString()));
cw_zano/lib/zano_wallet_api.dart
+35 -26
@@ -41,7 +41,8 @@ mixin ZanoWalletApi {
41 _hWallet = value;
42 }
43
44 - int getCurrentTxFee(TransactionPriority priority) => zano.PlainWallet_getCurrentTxFee(priority.raw);
44 + int getCurrentTxFee(TransactionPriority priority) =>
45 + zano.PlainWallet_getCurrentTxFee(priority.raw);
46
47 void setPassword(String password) => zano.PlainWallet_resetWalletPassword(hWallet, password);
48
@@ -112,7 +113,7 @@ mixin ZanoWalletApi {
113 Future<void> _setWalletSecret(String key, String value) async {
114 final secrets = await _getSecrets();
115 secrets[key] = value;
115 - await _setSecrets(secrets);
116 + await _setSecrets(secrets);
117 }
118
119 Future<String?> getPassphrase() async {
@@ -125,7 +126,7 @@ mixin ZanoWalletApi {
126
127 Future<String> getSeed() async {
128 final passphrase = await getPassphrase();
128 - final respStr = await invokeMethod("get_restore_info", {"seed_password": passphrase??""});
129 + final respStr = await invokeMethod("get_restore_info", {"seed_password": passphrase ?? ""});
130 final resp = convert.json.decode(respStr);
131 return resp["result"]["seed_phrase"] as String;
132 }
@@ -146,7 +147,7 @@ mixin ZanoWalletApi {
147 final status = GetWalletStatusResult.fromJson(jsonDecode(json));
148 if (_logInfo)
149 printV(
149 - 'get_wallet_status connected: ${status.isDaemonConnected} in refresh: ${status.isInLongRefresh} progress: ${status.progress} wallet state: ${status.walletState} sync: ${status.currentWalletHeight}/${status.currentDaemonHeight} ${(status.currentWalletHeight/status.currentDaemonHeight*100).toStringAsFixed(2)}%');
150 + 'get_wallet_status connected: ${status.isDaemonConnected} in refresh: ${status.isInLongRefresh} progress: ${status.progress} wallet state: ${status.walletState} sync: ${status.currentWalletHeight}/${status.currentDaemonHeight} ${(status.currentWalletHeight / status.currentDaemonHeight * 100).toStringAsFixed(2)}%');
151 return status;
152 }
153
@@ -159,7 +160,8 @@ mixin ZanoWalletApi {
160 try {
161 jsonDecode(invokeResult);
162 } catch (e) {
162 - if (invokeResult.contains(Consts.errorWalletWrongId)) throw ZanoWalletException('Wrong wallet id');
163 + if (invokeResult.contains(Consts.errorWalletWrongId))
164 + throw ZanoWalletException('Wrong wallet id');
165 printV('exception in parsing json in invokeMethod: $invokeResult');
166 rethrow;
167 }
@@ -173,14 +175,16 @@ mixin ZanoWalletApi {
175 _checkForErrors(map);
176 List<ZanoAsset> assets(String type, bool isGlobalWhitelist) =>
177 (map?['result']?[type] as List<dynamic>?)
176 - ?.map((e) => ZanoAsset.fromJson(e as Map<String, dynamic>, isInGlobalWhitelist: isGlobalWhitelist))
178 + ?.map((e) => ZanoAsset.fromJson(e as Map<String, dynamic>,
179 + isInGlobalWhitelist: isGlobalWhitelist))
180 .toList() ??
181 [];
182 final localWhitelist = assets('local_whitelist', false);
183 final globalWhitelist = assets('global_whitelist', true);
184 final ownAssets = assets('own_assets', false);
185 if (_logInfo)
183 - printV('assets_whitelist_get got local whitelist: ${localWhitelist.length} ($localWhitelist); '
186 + printV(
187 + 'assets_whitelist_get got local whitelist: ${localWhitelist.length} ($localWhitelist); '
188 'global whitelist: ${globalWhitelist.length} ($globalWhitelist); '
189 'own assets: ${ownAssets.length} ($ownAssets)');
190 return [...globalWhitelist, ...localWhitelist, ...ownAssets];
@@ -197,7 +201,8 @@ mixin ZanoWalletApi {
201 final map = jsonDecode(json) as Map<String, dynamic>?;
202 _checkForErrors(map);
203 if (map!['result']!['status']! == 'OK') {
200 - final assetDescriptor = ZanoAsset.fromJson(map['result']!['asset_descriptor']! as Map<String, dynamic>);
204 + final assetDescriptor =
205 + ZanoAsset.fromJson(map['result']!['asset_descriptor']! as Map<String, dynamic>);
206 printV('assets_whitelist_add added ${assetDescriptor.fullName} ${assetDescriptor.ticker}');
207 return assetDescriptor;
208 } else {
@@ -233,7 +238,8 @@ mixin ZanoWalletApi {
238 Future<ZanoAsset?> getAssetInfo(String assetId) async {
239 final methodName = 'get_asset_info';
240 final params = AssetIdParams(assetId: assetId);
236 - final result = await _proxyToDaemon('/json_rpc', '{"method": "$methodName","params": ${jsonEncode(params)}}');
241 + final result = await _proxyToDaemon(
242 + '/json_rpc', '{"method": "$methodName","params": ${jsonEncode(params)}}');
243 if (result == null) {
244 printV('get_asset_info empty result');
245 return null;
@@ -245,8 +251,8 @@ mixin ZanoWalletApi {
251 'get_asset_info $assetId error ${map['error']!['code']} ${map['error']!['message']}');
252 return null;
253 } else if (map['result']!['status']! == 'OK') {
248 - final assetDescriptor = ZanoAsset.fromJson(
249 - map['result']!['asset_descriptor']! as Map<String, dynamic>);
254 + final assetDescriptor =
255 + ZanoAsset.fromJson(map['result']!['asset_descriptor']! as Map<String, dynamic>);
256 printV('get_asset_info $assetId ${assetDescriptor.fullName} ${assetDescriptor.ticker}');
257 return assetDescriptor;
258 } else {
@@ -270,10 +276,12 @@ mixin ZanoWalletApi {
276 }
277 }
278
273 - Future<GetRecentTxsAndInfoResult> getRecentTxsAndInfo({required int offset, required int count}) async {
279 + Future<GetRecentTxsAndInfoResult> getRecentTxsAndInfo(
280 + {required int offset, required int count}) async {
281 printV('get_recent_txs_and_info $offset $count');
282 try {
276 - final json = await invokeMethod('get_recent_txs_and_info', GetRecentTxsAndInfoParams(offset: offset, count: count));
283 + final json = await invokeMethod(
284 + 'get_recent_txs_and_info', GetRecentTxsAndInfoParams(offset: offset, count: count));
285 final map = jsonDecode(json) as Map<String, dynamic>?;
286 _checkForErrors(map);
287 final lastItemIndex = map?['result']?['last_item_index'] as int?;
@@ -299,7 +307,8 @@ mixin ZanoWalletApi {
307 jsonDecode(zano.PlainWallet_getAddressInfo(address)),
308 );
309
302 - String _shorten(String s) => s.length > 10 ? '${s.substring(0, 4)}...${s.substring(s.length - 4)}' : s;
310 + String _shorten(String s) =>
311 + s.length > 10 ? '${s.substring(0, 4)}...${s.substring(s.length - 4)}' : s;
312
313 Future<CreateWalletResult> createWallet(String path, String password) async {
314 printV('create_wallet path $path password ${_shorten(password)}');
@@ -319,15 +328,17 @@ mixin ZanoWalletApi {
328 return result;
329 }
330
322 - Future<CreateWalletResult> restoreWalletFromSeed(String path, String password, String seed, String? passphrase) async {
331 + Future<CreateWalletResult> restoreWalletFromSeed(
332 + String path, String password, String seed, String? passphrase) async {
333 printV('restore_wallet path $path');
324 - final json = zano.PlainWallet_restore(seed, path, password, passphrase??'');
334 + final json = zano.PlainWallet_restore(seed, path, password, passphrase ?? '');
335 final map = jsonDecode(json) as Map<String, dynamic>?;
336 if (map?['error'] != null) {
337 final code = map!['error']!['code'] ?? '';
338 final message = map['error']!['message'] ?? '';
339 if (code == Consts.errorWrongSeed) {
330 - throw RestoreFromSeedsException('Error restoring wallet\nPlease check the seed words are correct. Additionally, if you created this wallet with a passphrase please add it under the Advanced Settings page.');
340 + throw RestoreFromSeedsException(
341 + 'Error restoring wallet\nPlease check the seed words are correct. Additionally, if you created this wallet with a passphrase please add it under the Advanced Settings page.');
342 } else if (code == Consts.errorAlreadyExists) {
343 throw RestoreFromSeedsException('Error restoring wallet, already exists');
344 }
@@ -348,7 +359,7 @@ mixin ZanoWalletApi {
359 try {
360 json = zano.PlainWallet_open(path, password);
361 } catch (e) {
351 - printV('error in loadingWallet $e');
362 + printV('error in loadingWallet $e');
363 rethrow;
364 }
365
@@ -376,7 +387,8 @@ mixin ZanoWalletApi {
387
388 static Map<String, CreateWalletResult> openWalletCache = {};
389
379 - Future<TransferResult> transfer(List<Destination> destinations, BigInt fee, String comment) async {
390 + Future<TransferResult> transfer(
391 + List<Destination> destinations, BigInt fee, String comment) async {
392 final params = TransferParams(
393 destinations: destinations,
394 fee: fee,
@@ -453,7 +465,6 @@ mixin ZanoWalletApi {
465 throw ZanoWalletException('Error, $message ($code)');
466 }
467 }
456 -
468 }
469
470 Future<String> callSyncMethod(String methodName, int hWallet, String params) async {
@@ -462,10 +473,7 @@ Future<String> callSyncMethod(String methodName, int hWallet, String params) asy
473 final invokeResult = await Isolate.run(() async {
474 final lib = zanoapi.ZanoC(DynamicLibrary.open(zano.libPath));
475 final txid = lib.ZANO_PlainWallet_syncCall(
465 - Pointer.fromAddress(method_name_).cast(),
466 - hWallet,
467 - Pointer.fromAddress(params_).cast()
468 - );
476 + Pointer.fromAddress(method_name_).cast(), hWallet, Pointer.fromAddress(params_).cast());
477 try {
478 final strPtr = txid.cast<Utf8>();
479 final str = strPtr.toDartString();
@@ -496,7 +504,7 @@ Future<String> _getWalletStatus(int hWallet) async {
504 final jsonPtr = await Isolate.run(() async {
505 final lib = zanoapi.ZanoC(DynamicLibrary.open(zano.libPath));
506 final status = lib.ZANO_PlainWallet_getWalletStatus(
499 - hWallet,
507 + hWallet,
508 );
509 return status.address;
510 });
@@ -511,11 +519,12 @@ Future<String> _getWalletStatus(int hWallet) async {
519 }
520 return json;
521 }
522 +
523 Future<String> _getWalletInfo(int hWallet) async {
524 final jsonPtr = await Isolate.run(() async {
525 final lib = zanoapi.ZanoC(DynamicLibrary.open(zano.libPath));
526 final status = lib.ZANO_PlainWallet_getWalletInfo(
518 - hWallet,
527 + hWallet,
528 );
529 return status.address;
530 });
cw_zano/lib/zano_wallet_exceptions.dart
+3 -3
@@ -13,9 +13,9 @@ class RestoreFromSeedsException extends RestoreFromSeedException {
13 }
14
15 class TransferException extends ZanoWalletException {
16 - TransferException(String message): super(message);
16 + TransferException(String message) : super(message);
17 }
18
19 class ZanoWalletBusyException extends ZanoWalletException {
20 - ZanoWalletBusyException(): super('');
21 -}
\ No newline at end of file
20 + ZanoWalletBusyException() : super('');
21 +}
cw_zano/lib/zano_wallet_service.dart
+25 -10
@@ -14,11 +14,17 @@ import 'package:hive/hive.dart';
14 import 'package:monero/zano.dart' as zano;
15
16 class ZanoNewWalletCredentials extends WalletCredentials {
17 - ZanoNewWalletCredentials({required String name, String? password, required String? passphrase}) : super(name: name, password: password, passphrase: passphrase);
17 + ZanoNewWalletCredentials({required String name, String? password, required String? passphrase})
18 + : super(name: name, password: password, passphrase: passphrase);
19 }
20
21 class ZanoRestoreWalletFromSeedCredentials extends WalletCredentials {
21 - ZanoRestoreWalletFromSeedCredentials({required String name, required String password, required String passphrase, required int height, required this.mnemonic})
22 + ZanoRestoreWalletFromSeedCredentials(
23 + {required String name,
24 + required String password,
25 + required String passphrase,
26 + required int height,
27 + required this.mnemonic})
28 : super(name: name, password: password, passphrase: passphrase, height: height);
29
30 final String mnemonic;
@@ -41,11 +47,15 @@ class ZanoRestoreWalletFromKeysCredentials extends WalletCredentials {
47 final String spendKey;
48 }
49
44 -class ZanoWalletService extends WalletService<ZanoNewWalletCredentials,
45 - ZanoRestoreWalletFromSeedCredentials, ZanoRestoreWalletFromKeysCredentials, ZanoNewWalletCredentials> {
50 +class ZanoWalletService extends WalletService<
51 + ZanoNewWalletCredentials,
52 + ZanoRestoreWalletFromSeedCredentials,
53 + ZanoRestoreWalletFromKeysCredentials,
54 + ZanoNewWalletCredentials> {
55 ZanoWalletService();
56
48 - static bool walletFilesExist(String path) => !File(path).existsSync() && !File('$path.keys').existsSync();
57 + static bool walletFilesExist(String path) =>
58 + !File(path).existsSync() && !File('$path.keys').existsSync();
59
60 int hWallet = 0;
61
@@ -71,7 +81,8 @@ class ZanoWalletService extends WalletService<ZanoNewWalletCredentials,
81 throw Exception('Wallet not found');
82 }
83 try {
74 - final wallet = await ZanoWalletBase.open(name: name, password: password, walletInfo: walletInfo);
84 + final wallet =
85 + await ZanoWalletBase.open(name: name, password: password, walletInfo: walletInfo);
86 saveBackup(name);
87 return wallet;
88 } catch (e) {
@@ -103,7 +114,8 @@ class ZanoWalletService extends WalletService<ZanoNewWalletCredentials,
114 if (currentWalletInfo == null) {
115 throw Exception('Wallet not found');
116 }
106 - final currentWallet = ZanoWallet(currentWalletInfo, await currentWalletInfo.getDerivationInfo(), password);
117 + final currentWallet =
118 + ZanoWallet(currentWalletInfo, await currentWalletInfo.getDerivationInfo(), password);
119
120 await currentWallet.renameWalletFiles(newName);
121
@@ -115,17 +127,20 @@ class ZanoWalletService extends WalletService<ZanoNewWalletCredentials,
127 }
128
129 @override
118 - Future<ZanoWallet> restoreFromKeys(ZanoRestoreWalletFromKeysCredentials credentials, {bool? isTestnet}) async {
130 + Future<ZanoWallet> restoreFromKeys(ZanoRestoreWalletFromKeysCredentials credentials,
131 + {bool? isTestnet}) async {
132 throw UnimplementedError();
133 }
134
135 @override
123 - Future<ZanoWallet> restoreFromSeed(ZanoRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async {
136 + Future<ZanoWallet> restoreFromSeed(ZanoRestoreWalletFromSeedCredentials credentials,
137 + {bool? isTestnet}) async {
138 return ZanoWalletBase.restore(credentials: credentials);
139 }
140
141 @override
142 Future<ZanoWallet> restoreFromHardwareWallet(ZanoNewWalletCredentials credentials) {
129 - throw UnimplementedError("Restoring a Zano wallet from a hardware wallet is not yet supported!");
143 + throw UnimplementedError(
144 + "Restoring a Zano wallet from a hardware wallet is not yet supported!");
145 }
146 }
lib/anonpay/anonpay_api.dart
+2 -2
@@ -78,7 +78,7 @@ class AnonPayApi {
78 clearnetUri: Uri.https(clearNetAuthority, anonPayPath, body),
79 onionUri: Uri.https(onionApiAuthority, anonPayPath, body),
80 );
81 -
81 +
82 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
83 final id = responseJSON['ID'] as String;
84 final url = responseJSON['url'] as String;
@@ -156,7 +156,7 @@ class AnonPayApi {
156 clearnetUri: Uri.https(clearNetAuthority, coinPath, params),
157 onionUri: Uri.https(onionApiAuthority, coinPath, params),
158 );
159 -
159 +
160 final responseJSON = json.decode(response.body) as List<dynamic>;
161 if (response.statusCode != 200) {
162 throw Exception('Unexpected http status: ${response.statusCode}');
lib/anonpay/anonpay_donation_link_info.dart
+3 -3
@@ -1,13 +1,13 @@
1 import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
2
3 -class AnonpayDonationLinkInfo implements AnonpayInfoBase{
3 +class AnonpayDonationLinkInfo implements AnonpayInfoBase {
4 final String clearnetUrl;
5 final String onionUrl;
6 final String address;
7 -
7 +
8 AnonpayDonationLinkInfo({
9 required this.clearnetUrl,
10 required this.onionUrl,
11 required this.address,
12 });
13 -}
\ No newline at end of file
13 +}
lib/anonpay/anonpay_info_base.dart
+1 -1
@@ -2,4 +2,4 @@ abstract class AnonpayInfoBase {
2 String get clearnetUrl;
3 String get onionUrl;
4 String get address;
5 -}
\ No newline at end of file
5 +}
lib/anypay/any_pay_chain.dart
+4 -4
@@ -1,5 +1,5 @@
1 class AnyPayChain {
2 - static const xmr = 'XMR';
3 - static const btc = 'BTC';
4 - static const ltc = 'LTC';
5 -}
\ No newline at end of file
2 + static const xmr = 'XMR';
3 + static const btc = 'BTC';
4 + static const ltc = 'LTC';
5 +}
lib/anypay/any_pay_payment.dart
+55 -53
@@ -4,60 +4,62 @@ import 'package:cake_wallet/bitcoin/bitcoin.dart';
4 import 'package:cake_wallet/monero/monero.dart';
5
6 class AnyPayPayment {
7 - AnyPayPayment({
8 - required this.time,
9 - required this.expires,
10 - required this.memo,
11 - required this.paymentUrl,
12 - required this.paymentId,
13 - required this.chain,
14 - required this.network,
15 - required this.instructions});
7 + AnyPayPayment(
8 + {required this.time,
9 + required this.expires,
10 + required this.memo,
11 + required this.paymentUrl,
12 + required this.paymentId,
13 + required this.chain,
14 + required this.network,
15 + required this.instructions});
16
17 - factory AnyPayPayment.fromMap(Map<String, dynamic> obj) {
18 - final instructions = (obj['instructions'] as List<dynamic>)
19 - .map((dynamic instruction) => AnyPayPaymentInstruction.fromMap(instruction as Map<String, dynamic>))
20 - .toList();
21 - return AnyPayPayment(
22 - time: DateTime.parse(obj['time'] as String),
23 - expires: DateTime.parse(obj['expires'] as String),
24 - memo: obj['memo'] as String,
25 - paymentUrl: obj['paymentUrl'] as String,
26 - paymentId: obj['paymentId'] as String,
27 - chain: obj['chain'] as String,
28 - network: obj['network'] as String,
29 - instructions: instructions);
30 - }
17 + factory AnyPayPayment.fromMap(Map<String, dynamic> obj) {
18 + final instructions = (obj['instructions'] as List<dynamic>)
19 + .map((dynamic instruction) =>
20 + AnyPayPaymentInstruction.fromMap(instruction as Map<String, dynamic>))
21 + .toList();
22 + return AnyPayPayment(
23 + time: DateTime.parse(obj['time'] as String),
24 + expires: DateTime.parse(obj['expires'] as String),
25 + memo: obj['memo'] as String,
26 + paymentUrl: obj['paymentUrl'] as String,
27 + paymentId: obj['paymentId'] as String,
28 + chain: obj['chain'] as String,
29 + network: obj['network'] as String,
30 + instructions: instructions);
31 + }
32
32 - final DateTime time;
33 - final DateTime expires;
34 - final String memo;
35 - final String paymentUrl;
36 - final String paymentId;
37 - final String chain;
38 - final String network;
39 - final List<AnyPayPaymentInstruction> instructions;
33 + final DateTime time;
34 + final DateTime expires;
35 + final String memo;
36 + final String paymentUrl;
37 + final String paymentId;
38 + final String chain;
39 + final String network;
40 + final List<AnyPayPaymentInstruction> instructions;
41
41 - String get totalAmount {
42 - final total = instructions
43 - .fold<int>(0, (int acc, instruction) => acc + instruction.outputs
44 - .fold<int>(0, (int outAcc, out) => outAcc + out.amount));
45 - switch (chain) {
46 - case AnyPayChain.xmr:
47 - return monero!.formatterMoneroAmountToString(amount: total);
48 - case AnyPayChain.btc:
49 - return bitcoin!.formatterBitcoinAmountToString(amount: total);
50 - case AnyPayChain.ltc:
51 - return bitcoin!.formatterBitcoinAmountToString(amount: total);
52 - default:
53 - return '';
54 - }
55 - }
42 + String get totalAmount {
43 + final total = instructions.fold<int>(
44 + 0,
45 + (int acc, instruction) =>
46 + acc + instruction.outputs.fold<int>(0, (int outAcc, out) => outAcc + out.amount));
47 + switch (chain) {
48 + case AnyPayChain.xmr:
49 + return monero!.formatterMoneroAmountToString(amount: total);
50 + case AnyPayChain.btc:
51 + return bitcoin!.formatterBitcoinAmountToString(amount: total);
52 + case AnyPayChain.ltc:
53 + return bitcoin!.formatterBitcoinAmountToString(amount: total);
54 + default:
55 + return '';
56 + }
57 + }
58
57 - List<String> get outAddresses {
58 - return instructions
59 - .map((instruction) => instruction.outputs.map((out) => out.address))
60 - .expand((e) => e)
61 - .toList();
62 - }
63 -}
\ No newline at end of file
59 + List<String> get outAddresses {
60 + return instructions
61 + .map((instruction) => instruction.outputs.map((out) => out.address))
62 + .expand((e) => e)
63 + .toList();
64 + }
65 +}
lib/anypay/any_pay_payment_committed_info.dart
+12 -12
@@ -1,16 +1,16 @@
1 import 'package:cake_wallet/anypay/any_pay_trasnaction.dart';
2
3 class AnyPayPaymentCommittedInfo {
4 - const AnyPayPaymentCommittedInfo({
5 - required this.uri,
6 - required this.currency,
7 - required this.chain,
8 - required this.transactions,
9 - required this.memo});
4 + const AnyPayPaymentCommittedInfo(
5 + {required this.uri,
6 + required this.currency,
7 + required this.chain,
8 + required this.transactions,
9 + required this.memo});
10
11 - final String uri;
12 - final String currency;
13 - final String chain;
14 - final List<AnyPayTransaction> transactions;
15 - final String memo;
16 -}
\ No newline at end of file
11 + final String uri;
12 + final String currency;
13 + final String chain;
14 + final List<AnyPayTransaction> transactions;
15 + final String memo;
16 +}
lib/anypay/any_pay_payment_instruction.dart
+24 -25
@@ -1,31 +1,30 @@
1 import 'package:cake_wallet/anypay/any_pay_payment_instruction_output.dart';
2
3 class AnyPayPaymentInstruction {
4 - AnyPayPaymentInstruction({
5 - required this.type,
6 - required this.requiredFeeRate,
7 - required this.txKey,
8 - required this.txHash,
9 - required this.outputs});
4 + AnyPayPaymentInstruction(
5 + {required this.type,
6 + required this.requiredFeeRate,
7 + required this.txKey,
8 + required this.txHash,
9 + required this.outputs});
10
11 - factory AnyPayPaymentInstruction.fromMap(Map<String, dynamic> obj) {
12 - final outputs = (obj['outputs'] as List<dynamic>)
13 - .map((dynamic out) =>
14 - AnyPayPaymentInstructionOutput.fromMap(out as Map<String, dynamic>))
15 - .toList();
16 - return AnyPayPaymentInstruction(
17 - type: obj['type'] as String,
18 - requiredFeeRate: obj['requiredFeeRate'] as int,
19 - txKey: obj['tx_key'] as bool? ?? false,
20 - txHash: obj['tx_hash'] as bool? ?? false,
21 - outputs: outputs);
22 - }
11 + factory AnyPayPaymentInstruction.fromMap(Map<String, dynamic> obj) {
12 + final outputs = (obj['outputs'] as List<dynamic>)
13 + .map((dynamic out) => AnyPayPaymentInstructionOutput.fromMap(out as Map<String, dynamic>))
14 + .toList();
15 + return AnyPayPaymentInstruction(
16 + type: obj['type'] as String,
17 + requiredFeeRate: obj['requiredFeeRate'] as int,
18 + txKey: obj['tx_key'] as bool? ?? false,
19 + txHash: obj['tx_hash'] as bool? ?? false,
20 + outputs: outputs);
21 + }
22
24 - static const transactionType = 'transaction';
23 + static const transactionType = 'transaction';
24
26 - final String type;
27 - final int requiredFeeRate;
28 - final bool txKey;
29 - final bool txHash;
30 - final List<AnyPayPaymentInstructionOutput> outputs;
31 -}
\ No newline at end of file
25 + final String type;
26 + final int requiredFeeRate;
27 + final bool txKey;
28 + final bool txHash;
29 + final List<AnyPayPaymentInstructionOutput> outputs;
30 +}
lib/anypay/any_pay_payment_instruction_output.dart
+7 -7
@@ -1,10 +1,10 @@
1 class AnyPayPaymentInstructionOutput {
2 - const AnyPayPaymentInstructionOutput(this.address, this.amount);
2 + const AnyPayPaymentInstructionOutput(this.address, this.amount);
3
4 - factory AnyPayPaymentInstructionOutput.fromMap(Map<String, dynamic> obj) {
5 - return AnyPayPaymentInstructionOutput(obj['address'] as String, obj['amount'] as int);
6 - }
4 + factory AnyPayPaymentInstructionOutput.fromMap(Map<String, dynamic> obj) {
5 + return AnyPayPaymentInstructionOutput(obj['address'] as String, obj['amount'] as int);
6 + }
7
8 - final String address;
9 - final int amount;
10 -}
\ No newline at end of file
8 + final String address;
9 + final int amount;
10 +}
lib/anypay/any_pay_trasnaction.dart
+5 -5
@@ -1,7 +1,7 @@
1 class AnyPayTransaction {
2 - const AnyPayTransaction(this.tx, {required this.id, required this.key});
2 + const AnyPayTransaction(this.tx, {required this.id, required this.key});
3
4 - final String tx;
5 - final String id;
6 - final String? key;
7 -}
\ No newline at end of file
4 + final String tx;
5 + final String id;
6 + final String? key;
7 +}
lib/anypay/anypay_api.dart
+83 -79
@@ -9,101 +9,105 @@ import 'package:cake_wallet/anypay/any_pay_trasnaction.dart';
9 import 'package:cake_wallet/.secrets.g.dart' as secrets;
10
11 class AnyPayApi {
12 - static const contentTypePaymentRequest = 'application/payment-request';
13 - static const contentTypePayment = 'application/payment';
14 - static const xPayproVersion = '2';
15 - static const anypayToken = secrets.anypayToken;
12 + static const contentTypePaymentRequest = 'application/payment-request';
13 + static const contentTypePayment = 'application/payment';
14 + static const xPayproVersion = '2';
15 + static const anypayToken = secrets.anypayToken;
16
17 - static String chainByScheme(String scheme) {
18 - switch (scheme.toLowerCase()) {
19 - case 'monero':
20 - return CryptoCurrency.xmr.title;
21 - case 'bitcoin':
22 - return CryptoCurrency.btc.title;
23 - case 'litecoin':
24 - return CryptoCurrency.ltc.title;
25 - default:
26 - return '';
27 - }
28 - }
17 + static String chainByScheme(String scheme) {
18 + switch (scheme.toLowerCase()) {
19 + case 'monero':
20 + return CryptoCurrency.xmr.title;
21 + case 'bitcoin':
22 + return CryptoCurrency.btc.title;
23 + case 'litecoin':
24 + return CryptoCurrency.ltc.title;
25 + default:
26 + return '';
27 + }
28 + }
29
30 - static CryptoCurrency currencyByScheme(String scheme) {
31 - switch (scheme.toLowerCase()) {
32 - case 'monero':
33 - return CryptoCurrency.xmr;
34 - case 'bitcoin':
35 - return CryptoCurrency.btc;
36 - case 'litecoin':
37 - return CryptoCurrency.ltc;
38 - default:
39 - throw Exception('Unexpected scheme: ${scheme}');
40 - }
41 - }
30 + static CryptoCurrency currencyByScheme(String scheme) {
31 + switch (scheme.toLowerCase()) {
32 + case 'monero':
33 + return CryptoCurrency.xmr;
34 + case 'bitcoin':
35 + return CryptoCurrency.btc;
36 + case 'litecoin':
37 + return CryptoCurrency.ltc;
38 + default:
39 + throw Exception('Unexpected scheme: ${scheme}');
40 + }
41 + }
42
43 - Future<AnyPayPayment> paymentRequest(String uri) async {
44 - final fragments = uri.split(':?r=');
45 - final scheme = fragments.first;
46 - final url = Uri.parse(fragments[1]);
47 - final headers = <String, String>{
48 - 'Content-Type': contentTypePaymentRequest,
49 - 'X-Paypro-Version': xPayproVersion,
50 - 'Accept': '*/*',
51 - 'x-wallet': 'cake',
52 - 'x-wallet-token': anypayToken,};
53 - final body = <String, dynamic>{
54 - 'chain': chainByScheme(scheme),
55 - 'currency': currencyByScheme(scheme).title};
56 - final response = await ProxyWrapper().post(
43 + Future<AnyPayPayment> paymentRequest(String uri) async {
44 + final fragments = uri.split(':?r=');
45 + final scheme = fragments.first;
46 + final url = Uri.parse(fragments[1]);
47 + final headers = <String, String>{
48 + 'Content-Type': contentTypePaymentRequest,
49 + 'X-Paypro-Version': xPayproVersion,
50 + 'Accept': '*/*',
51 + 'x-wallet': 'cake',
52 + 'x-wallet-token': anypayToken,
53 + };
54 + final body = <String, dynamic>{
55 + 'chain': chainByScheme(scheme),
56 + 'currency': currencyByScheme(scheme).title
57 + };
58 + final response = await ProxyWrapper().post(
59 clearnetUri: url,
60 headers: headers,
61 body: json.encode(body),
62 );
61 -
63 +
64 if (response.statusCode != 200) {
63 - await ExceptionHandler.onError(FlutterErrorDetails(exception: response));
65 + await ExceptionHandler.onError(FlutterErrorDetails(exception: response));
66 throw Exception('Unexpected response http code: ${response.statusCode}');
65 - }
67 + }
68
69 final decodedBody = json.decode(response.body) as Map<String, dynamic>;
70 return AnyPayPayment.fromMap(decodedBody);
69 - }
71 + }
72
71 - Future<AnyPayPaymentCommittedInfo> payment(
72 - String uri,
73 - {required String chain,
74 - required String currency,
75 - required List<AnyPayTransaction> transactions}) async {
76 - final headers = <String, String>{
77 - 'Content-Type': contentTypePayment,
78 - 'X-Paypro-Version': xPayproVersion,
79 - 'Accept': '*/*',
80 - 'x-wallet': 'cake',
81 - 'x-wallet-token': anypayToken,};
82 - final body = <String, dynamic>{
83 - 'chain': chain,
84 - 'currency': currency,
85 - 'transactions': transactions.map((tx) => {'tx': tx.tx, 'tx_hash': tx.id, 'tx_key': tx.key}).toList()};
86 - final response = await ProxyWrapper().post(
73 + Future<AnyPayPaymentCommittedInfo> payment(String uri,
74 + {required String chain,
75 + required String currency,
76 + required List<AnyPayTransaction> transactions}) async {
77 + final headers = <String, String>{
78 + 'Content-Type': contentTypePayment,
79 + 'X-Paypro-Version': xPayproVersion,
80 + 'Accept': '*/*',
81 + 'x-wallet': 'cake',
82 + 'x-wallet-token': anypayToken,
83 + };
84 + final body = <String, dynamic>{
85 + 'chain': chain,
86 + 'currency': currency,
87 + 'transactions':
88 + transactions.map((tx) => {'tx': tx.tx, 'tx_hash': tx.id, 'tx_key': tx.key}).toList()
89 + };
90 + final response = await ProxyWrapper().post(
91 clearnetUri: Uri.parse(uri),
92 headers: headers,
93 body: json.encode(body),
94 );
91 -
92 - if (response.statusCode == 400) {
93 - final decodedBody = json.decode(response.body) as Map<String, dynamic>;
94 - throw Exception(decodedBody['message'] as String? ?? 'Unexpected response\nError code: 400');
95 - }
95
97 - if (response.statusCode != 200) {
98 - throw Exception('Unexpected response');
99 - }
96 + if (response.statusCode == 400) {
97 + final decodedBody = json.decode(response.body) as Map<String, dynamic>;
98 + throw Exception(decodedBody['message'] as String? ?? 'Unexpected response\nError code: 400');
99 + }
100 +
101 + if (response.statusCode != 200) {
102 + throw Exception('Unexpected response');
103 + }
104
101 - final decodedBody = json.decode(response.body) as Map<String, dynamic>;
102 - return AnyPayPaymentCommittedInfo(
103 - uri: uri,
104 - currency: currency,
105 - chain: chain,
106 - transactions: transactions,
107 - memo: decodedBody['memo'] as String);
108 - }
109 -}
\ No newline at end of file
105 + final decodedBody = json.decode(response.body) as Map<String, dynamic>;
106 + return AnyPayPaymentCommittedInfo(
107 + uri: uri,
108 + currency: currency,
109 + chain: chain,
110 + transactions: transactions,
111 + memo: decodedBody['memo'] as String);
112 + }
113 +}
lib/bitcoin/cw_bitcoin.dart
+19 -19
@@ -185,7 +185,7 @@ class CWBitcoin extends Bitcoin {
185 balance: addr.balance,
186 isChange: addr.isHidden,
187 isLegacyDerivation: addr.isLegacyDerivation,
188 - derivationPath: addr.derivationPath))
188 + derivationPath: addr.derivationPath))
189 .toList();
190 }
191
@@ -206,10 +206,8 @@ class CWBitcoin extends Bitcoin {
206 return estimatedTx.amount;
207 }
208
209 -
209 if (wallet.type == WalletType.dogecoin) {
211 - final dogeAddr =
212 - sk.getPublic().toP2pkhAddress();
210 + final dogeAddr = sk.getPublic().toP2pkhAddress();
211 final estimatedTx = await electrumWallet.estimateSendAllTx(
212 [BitcoinOutput(address: dogeAddr, value: BigInt.zero)],
213 getFeeRate(wallet, priority as BitcoinTransactionPriority),
@@ -276,14 +274,13 @@ class CWBitcoin extends Bitcoin {
274 await bitcoinWallet.updateAllUnspents();
275 }
276
279 - WalletService createBitcoinWalletService(
280 - Box<UnspentCoinsInfo> unspentCoinSource,
281 - Box<PayjoinSession> payjoinSessionSource,
282 - bool isDirect) {
277 + WalletService createBitcoinWalletService(Box<UnspentCoinsInfo> unspentCoinSource,
278 + Box<PayjoinSession> payjoinSessionSource, bool isDirect) {
279 return BitcoinWalletService(unspentCoinSource, payjoinSessionSource, isDirect);
280 }
281
286 - WalletService createLitecoinWalletService(Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
282 + WalletService createLitecoinWalletService(
283 + Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
284 return LitecoinWalletService(unspentCoinSource, isDirect);
285 }
286
@@ -340,7 +337,8 @@ class CWBitcoin extends Bitcoin {
337 }
338
339 @override
343 - BitcoinReceivePageOption getBitcoinLightningReceivePageOption() => BitcoinReceivePageOption.lightning;
340 + BitcoinReceivePageOption getBitcoinLightningReceivePageOption() =>
341 + BitcoinReceivePageOption.lightning;
342 @override
343 BitcoinReceivePageOption getBitcoinSegwitPageOption() => BitcoinReceivePageOption.p2wpkh;
344 @override
@@ -839,9 +837,11 @@ class CWBitcoin extends Bitcoin {
837 final addresses = <String>[];
838
839 if (bitcoinTx.unspents == null || bitcoinTx.unspents!.isEmpty) {
842 - if(bitcoinTx.outputAddresses == null) return null;
843 - for(final addr in bitcoinTx.outputAddresses!) {
844 - if(bitcoinWallet.walletAddresses.allAddresses.firstWhereOrNull((item)=>item.address==addr) != null) {
840 + if (bitcoinTx.outputAddresses == null) return null;
841 + for (final addr in bitcoinTx.outputAddresses!) {
842 + if (bitcoinWallet.walletAddresses.allAddresses
843 + .firstWhereOrNull((item) => item.address == addr) !=
844 + null) {
845 addresses.add(addr);
846 }
847 }
@@ -850,12 +850,12 @@ class CWBitcoin extends Bitcoin {
850
851 final labels = <String>[];
852 try {
853 - bitcoinTx.unspents!.forEach((unspent) {
854 - addresses.add(bitcoinWallet.walletAddresses.silentAddresses
855 - .firstWhere((address) => address.silentPaymentTweak == unspent.silentPaymentLabel)
856 - .address);
857 - });
858 - } catch (e) {}
853 + bitcoinTx.unspents!.forEach((unspent) {
854 + addresses.add(bitcoinWallet.walletAddresses.silentAddresses
855 + .firstWhere((address) => address.silentPaymentTweak == unspent.silentPaymentLabel)
856 + .address);
857 + });
858 + } catch (e) {}
859
860 return addresses;
861 }
lib/bitcoin_cash/cw_bitcoin_cash.dart
+6 -2
@@ -5,7 +5,8 @@ class CWBitcoinCash extends BitcoinCash {
5 String getCashAddrFormat(String address) => AddressUtils.getCashAddrFormat(address);
6
7 @override
8 - WalletService createBitcoinCashWalletService(Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
8 + WalletService createBitcoinCashWalletService(
9 + Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
10 return BitcoinCashWalletService(unspentCoinSource, isDirect);
11 }
12
@@ -27,7 +28,10 @@ class CWBitcoinCash extends BitcoinCash {
28
29 @override
30 WalletCredentials createBitcoinCashRestoreWalletFromSeedCredentials(
30 - {required String name, required String mnemonic, required String password, String? passphrase}) =>
31 + {required String name,
32 + required String mnemonic,
33 + required String password,
34 + String? passphrase}) =>
35 BitcoinCashRestoreWalletFromSeedCredentials(
36 name: name, mnemonic: mnemonic, password: password, passphrase: passphrase);
37
lib/buy/buy_amount.dart
+6 -7
@@ -1,13 +1,12 @@
1 -
1 class BuyAmount {
3 - BuyAmount({
4 - required this.sourceAmount,
5 - required this.destAmount,
6 - this.achSourceAmount,
7 - this.minAmount = 0});
2 + BuyAmount(
3 + {required this.sourceAmount,
4 + required this.destAmount,
5 + this.achSourceAmount,
6 + this.minAmount = 0});
7
8 final double sourceAmount;
9 final double destAmount;
10 final double? achSourceAmount;
11 final int minAmount;
13 -}
\ No newline at end of file
12 +}
lib/buy/buy_exception.dart
+1 -2
@@ -1,4 +1,3 @@
1 -
1 class BuyException implements Exception {
2 BuyException({required this.title, required this.content});
3
@@ -7,4 +6,4 @@ class BuyException implements Exception {
6
7 @override
8 String toString() => '$title: $content';
10 -}
\ No newline at end of file
9 +}
lib/buy/buy_provider.dart
+8 -9
@@ -10,13 +10,12 @@ import 'package:cw_core/wallet_base.dart';
10 import 'package:flutter/material.dart';
11
12 abstract class BuyProvider {
13 - BuyProvider({
14 - required this.wallet,
15 - required this.isTestEnvironment,
16 - required this.hardwareWalletVM,
17 - required this.supportedCryptoList,
18 - required this.supportedFiatList
19 - });
13 + BuyProvider(
14 + {required this.wallet,
15 + required this.isTestEnvironment,
16 + required this.hardwareWalletVM,
17 + required this.supportedCryptoList,
18 + required this.supportedFiatList});
19
20 final WalletBase wallet;
21 final bool isTestEnvironment;
@@ -54,7 +53,7 @@ abstract class BuyProvider {
53 throw UnimplementedError();
54
55 Future<List<PaymentMethod>> getAvailablePaymentTypes(
57 - String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async =>
56 + String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async =>
57 [];
58
59 Future<List<Quote>?> fetchQuote(
@@ -64,7 +63,7 @@ abstract class BuyProvider {
63 required bool isBuyAction,
64 required String walletAddress,
65 PaymentType? paymentType,
67 - String? customPaymentMethodType,
66 + String? customPaymentMethodType,
67 String? countryCode}) async =>
68 null;
69 }
lib/buy/dfx/dfx_buy_provider.dart
+8 -9
@@ -56,7 +56,7 @@ class DFXBuyProvider extends BuyProvider {
56
57 static final List<FiatCurrency> _supportedFiat = [FiatCurrency.chf, FiatCurrency.eur];
58 static final List<FiatCurrency> _notSupportedFiat =
59 - FiatCurrency.all.where((fiat) => !_supportedFiat.contains(fiat)).toList();
59 + FiatCurrency.all.where((fiat) => !_supportedFiat.contains(fiat)).toList();
60
61 @override
62 String get title => 'DFX.swiss';
@@ -84,7 +84,6 @@ class DFXBuyProvider extends BuyProvider {
84 }
85 }
86
87 -
87 Future<String> getSignMessage(String walletAddress) async =>
88 "By_signing_this_message,_you_confirm_that_you_are_the_sole_owner_of_the_provided_Blockchain_address._Your_ID:_$walletAddress";
89
@@ -156,10 +155,9 @@ class DFXBuyProvider extends BuyProvider {
155 final url = Uri.https(_baseUrl, '/v1/fiat');
156
157 try {
159 - final response = await ProxyWrapper().get(
160 - clearnetUri: url,
161 - headers: {'accept': 'application/json'});
162 -
158 + final response =
159 + await ProxyWrapper().get(clearnetUri: url, headers: {'accept': 'application/json'});
160 +
161 if (response.statusCode == 200) {
162 final data = jsonDecode(response.body) as List<dynamic>;
163 for (final item in data) {
@@ -181,8 +179,9 @@ class DFXBuyProvider extends BuyProvider {
179 final url = Uri.https(_baseUrl, '/v1/asset', {'blockchains': blockchain});
180
181 try {
184 - final response = await ProxyWrapper().get(clearnetUri: url, headers: {'accept': 'application/json'});
185 -
182 + final response =
183 + await ProxyWrapper().get(clearnetUri: url, headers: {'accept': 'application/json'});
184 +
185 if (response.statusCode == 200) {
186 final responseData = jsonDecode(response.body);
187
@@ -300,7 +299,7 @@ class DFXBuyProvider extends BuyProvider {
299 headers: headers,
300 body: body,
301 );
303 -
302 +
303 final responseData = jsonDecode(response.body);
304
305 if (response.statusCode == 200) {
lib/buy/get_buy_provider_icon.dart
+4 -7
@@ -2,13 +2,10 @@ import 'package:flutter/material.dart';
2 import 'package:cake_wallet/buy/buy_provider_description.dart';
3
4 Image? getBuyProviderIcon(BuyProviderDescription providerDescription,
5 - {Color iconColor = Colors.black}) {
6 -
7 - final _wyreIcon =
8 - Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
5 + {Color iconColor = Colors.black}) {
6 + final _wyreIcon = Image.asset('assets/images/wyre-icon.png', width: 36, height: 36);
7 final _moonPayIcon =
10 - Image.asset('assets/images/moonpay-icon.png', color: iconColor,
11 - width: 36, height: 34);
8 + Image.asset('assets/images/moonpay-icon.png', color: iconColor, width: 36, height: 34);
9
10 switch (providerDescription) {
11 case BuyProviderDescription.wyre:
@@ -18,4 +15,4 @@ Image? getBuyProviderIcon(BuyProviderDescription providerDescription,
15 default:
16 return null;
17 }
21 -}
\ No newline at end of file
18 +}
lib/buy/kryptonim/kryptonim.dart
+9 -10
@@ -18,13 +18,13 @@ import 'package:url_launcher/url_launcher.dart';
18 class KryptonimBuyProvider extends BuyProvider {
19 KryptonimBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
20 : super(
21 - wallet: wallet,
22 - isTestEnvironment: isTestEnvironment,
23 - hardwareWalletVM: null,
24 - supportedCryptoList: supportedCryptoToFiatPairs(
25 - notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
26 - supportedFiatList: supportedFiatToCryptoPairs(
27 - notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
21 + wallet: wallet,
22 + isTestEnvironment: isTestEnvironment,
23 + hardwareWalletVM: null,
24 + supportedCryptoList: supportedCryptoToFiatPairs(
25 + notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
26 + supportedFiatList: supportedFiatToCryptoPairs(
27 + notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
28
29 static const _isProduction = true;
30
@@ -81,7 +81,6 @@ class KryptonimBuyProvider extends BuyProvider {
81 );
82
83 if (response.statusCode == 200 || response.statusCode == 201 || response.statusCode == 401) {
84 -
84 return jsonDecode(response.body) as Map<String, dynamic>;
85 } else {
86 return {};
@@ -94,7 +93,6 @@ class KryptonimBuyProvider extends BuyProvider {
93 @override
94 Future<List<PaymentMethod>> getAvailablePaymentTypes(
95 String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async {
97 -
96 final data = await getExchangeRates(
97 cryptoCurrency: cryptoCurrency,
98 fiatCurrency: fiatCurrency,
@@ -155,7 +153,8 @@ class KryptonimBuyProvider extends BuyProvider {
153
154 final selectedPaymentType =
155 PaymentMethod.getPaymentTypeId(selectedPaymentMethod['payment_method'] as String?);
158 - final quote = Quote.fromKryptonimJson(selectedPaymentMethod, isBuyAction, selectedPaymentType ?? PaymentType.unknown);
156 + final quote = Quote.fromKryptonimJson(
157 + selectedPaymentMethod, isBuyAction, selectedPaymentType ?? PaymentType.unknown);
158
159 quote.setFiatCurrency = fiatCurrency;
160 quote.setCryptoCurrency = cryptoCurrency;
lib/buy/meld/meld_buy_provider.dart
+15 -17
@@ -20,13 +20,13 @@ import 'package:url_launcher/url_launcher.dart';
20 class MeldBuyProvider extends BuyProvider {
21 MeldBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
22 : super(
23 - wallet: wallet,
24 - isTestEnvironment: isTestEnvironment,
25 - hardwareWalletVM: null,
26 - supportedCryptoList: supportedCryptoToFiatPairs(
27 - notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
28 - supportedFiatList: supportedFiatToCryptoPairs(
29 - notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
23 + wallet: wallet,
24 + isTestEnvironment: isTestEnvironment,
25 + hardwareWalletVM: null,
26 + supportedCryptoList: supportedCryptoToFiatPairs(
27 + notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
28 + supportedFiatList: supportedFiatToCryptoPairs(
29 + notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
30
31 static const _isProduction = false;
32
@@ -45,7 +45,7 @@ class MeldBuyProvider extends BuyProvider {
45 static const List<CryptoCurrency> _notSupportedCrypto = [];
46 static const List<FiatCurrency> _notSupportedFiat = [];
47
48 - static String get _testPublicKey => '' ; //secrets.meldTestPublicKey;
48 + static String get _testPublicKey => ''; //secrets.meldTestPublicKey;
49
50 @override
51 String get title => 'Meld';
@@ -80,7 +80,6 @@ class MeldBuyProvider extends BuyProvider {
80 'content-type': 'application/json',
81 },
82 );
83 -
83
84 if (response.statusCode == 200) {
85 final data = jsonDecode(response.body) as List<dynamic>;
@@ -100,13 +99,13 @@ class MeldBuyProvider extends BuyProvider {
99 @override
100 Future<List<Quote>?> fetchQuote(
101 {required CryptoCurrency cryptoCurrency,
103 - required FiatCurrency fiatCurrency,
104 - required double amount,
105 - required bool isBuyAction,
106 - required String walletAddress,
107 - PaymentType? paymentType,
108 - String? customPaymentMethodType,
109 - String? countryCode}) async {
102 + required FiatCurrency fiatCurrency,
103 + required double amount,
104 + required bool isBuyAction,
105 + required String walletAddress,
106 + PaymentType? paymentType,
107 + String? customPaymentMethodType,
108 + String? countryCode}) async {
109 String? paymentMethod;
110 if (paymentType != null && paymentType != PaymentType.all) {
111 paymentMethod = normalizePaymentMethod(paymentType);
@@ -136,7 +135,6 @@ class MeldBuyProvider extends BuyProvider {
135 headers: headers,
136 body: body,
137 );
139 -
138
139 if (response.statusCode == 200) {
140 final data = jsonDecode(response.body) as Map<String, dynamic>;
lib/buy/moonpay/moonpay_provider.dart
+11 -12
@@ -34,13 +34,13 @@ class MoonPayProvider extends BuyProvider {
34 baseBuyUrl = isTestEnvironment ? _baseBuyTestUrl : _baseBuyProductUrl,
35 this._appStore = appStore,
36 super(
37 - wallet: wallet,
38 - isTestEnvironment: isTestEnvironment,
39 - hardwareWalletVM: null,
40 - supportedCryptoList: supportedCryptoToFiatPairs(
41 - notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
42 - supportedFiatList: supportedFiatToCryptoPairs(
43 - notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
37 + wallet: wallet,
38 + isTestEnvironment: isTestEnvironment,
39 + hardwareWalletVM: null,
40 + supportedCryptoList: supportedCryptoToFiatPairs(
41 + notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
42 + supportedFiatList: supportedFiatToCryptoPairs(
43 + notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
44
45 final AppStore _appStore;
46
@@ -81,7 +81,8 @@ class MoonPayProvider extends BuyProvider {
81
82 String get _apiKey => isTestEnvironment ? secrets.moonPaySandboxApiKey : secrets.moonPayApiKey;
83
84 - String get currencyCode => walletTypeToCryptoCurrency(wallet.type, chainId: wallet.chainId).title.toLowerCase();
84 + String get currencyCode =>
85 + walletTypeToCryptoCurrency(wallet.type, chainId: wallet.chainId).title.toLowerCase();
86
87 String get trackUrl => baseBuyUrl + '/transaction_receipt?transactionId=';
88
@@ -105,7 +106,6 @@ class MoonPayProvider extends BuyProvider {
106 headers: {'Content-Type': 'application/json', 'x-api-key': _exchangeHelperApiKey},
107 body: json.encode({'query': query}),
108 );
108 -
109
110 if (response.statusCode == 200) {
111 printV((jsonDecode(response.body) as Map<String, dynamic>));
@@ -130,7 +130,7 @@ class MoonPayProvider extends BuyProvider {
130 clearnetUri: url,
131 headers: {'accept': 'application/json'},
132 );
133 -
133 +
134 if (response.statusCode == 200) {
135 return jsonDecode(response.body) as Map<String, dynamic>;
136 } else {
@@ -202,7 +202,7 @@ class MoonPayProvider extends BuyProvider {
202 final url = Uri.https(_baseUrl, path, params);
203 try {
204 final response = await ProxyWrapper().get(clearnetUri: url);
205 -
205 +
206 if (response.statusCode == 200) {
207 final data = jsonDecode(response.body) as Map<String, dynamic>;
208
@@ -312,7 +312,6 @@ class MoonPayProvider extends BuyProvider {
312 final url = _apiUrl + _transactionsSuffix + '/$id' + '?apiKey=' + _apiKey;
313 final uri = Uri.parse(url);
314 final response = await ProxyWrapper().get(clearnetUri: uri);
315 -
315
316 if (response.statusCode != 200) {
317 throw BuyException(title: providerDescription, content: 'Transaction $id is not found!');
lib/buy/onramper/onramper_buy_provider.dart
+35 -37
@@ -16,15 +16,15 @@ import 'package:flutter/material.dart';
16 import 'package:url_launcher/url_launcher.dart';
17
18 class OnRamperBuyProvider extends BuyProvider {
19 - OnRamperBuyProvider(
20 - {required WalletBase wallet, bool isTestEnvironment = false})
21 - : super(wallet: wallet,
22 - isTestEnvironment: isTestEnvironment,
23 - hardwareWalletVM: null,
24 - supportedCryptoList: supportedCryptoToFiatPairs(
25 - notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
26 - supportedFiatList: supportedFiatToCryptoPairs(
27 - notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
19 + OnRamperBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
20 + : super(
21 + wallet: wallet,
22 + isTestEnvironment: isTestEnvironment,
23 + hardwareWalletVM: null,
24 + supportedCryptoList: supportedCryptoToFiatPairs(
25 + notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
26 + supportedFiatList: supportedFiatToCryptoPairs(
27 + notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
28
29 static const _baseUrl = 'buy.onramper.com';
30 static const _baseApiUrl = 'api.onramper.com';
@@ -68,7 +68,6 @@ class OnRamperBuyProvider extends BuyProvider {
68 body: json.encode({'query': query}),
69 );
70
71 -
71 if (response.statusCode == 200) {
72 return (jsonDecode(response.body) as Map<String, dynamic>)['signature'] as String;
73 } else {
@@ -78,7 +77,6 @@ class OnRamperBuyProvider extends BuyProvider {
77 }
78
79 Future<String?> getRecommendedPaymentType(bool isBuyAction) async {
81 -
80 final params = {'type': isBuyAction ? 'buy' : 'sell'};
81
82 final url = Uri.https(_baseApiUrl, '$supported$defaultsAll', params);
@@ -95,10 +93,9 @@ class OnRamperBuyProvider extends BuyProvider {
93
94 final recommendedPaymentType = recommended['paymentMethod'] as String?;
95
98 - return recommendedPaymentType ;
96 + return recommendedPaymentType;
97 } else {
100 - final responseBody =
101 - jsonDecode(response.body) as Map<String, dynamic>;
98 + final responseBody = jsonDecode(response.body) as Map<String, dynamic>;
99 printV('Failed to fetch available payment types: ${responseBody['message']}');
100 }
101 } catch (e) {
@@ -109,21 +106,20 @@ class OnRamperBuyProvider extends BuyProvider {
106
107 Future<List<PaymentMethod>> getAvailablePaymentTypes(
108 String fiatCurrency, CryptoCurrency cryptoCurrency, bool isBuyAction) async {
112 -
113 - final normalizedCryptoCurrency =
114 - cryptoCurrency.title + _getNormalizeNetwork(cryptoCurrency);
109 + final normalizedCryptoCurrency = cryptoCurrency.title + _getNormalizeNetwork(cryptoCurrency);
110
111 final sourceCurrency = (isBuyAction ? fiatCurrency : normalizedCryptoCurrency).toLowerCase();
117 - final destinationCurrency = (isBuyAction ? normalizedCryptoCurrency : fiatCurrency).toLowerCase();
112 + final destinationCurrency =
113 + (isBuyAction ? normalizedCryptoCurrency : fiatCurrency).toLowerCase();
114
119 - final params = {'type': isBuyAction ? 'buy' : 'sell', 'destination' : destinationCurrency};
115 + final params = {'type': isBuyAction ? 'buy' : 'sell', 'destination': destinationCurrency};
116
117 final url = Uri.https(_baseApiUrl, '$supported$paymentTypes/$sourceCurrency', params);
118
119 try {
124 - final response =
125 - await ProxyWrapper().get(clearnetUri: url, headers: {'Authorization': _apiKey, 'accept': 'application/json'});
126 -
120 + final response = await ProxyWrapper()
121 + .get(clearnetUri: url, headers: {'Authorization': _apiKey, 'accept': 'application/json'});
122 +
123 if (response.statusCode == 200) {
124 final Map<String, dynamic> data = jsonDecode(response.body) as Map<String, dynamic>;
125 final List<dynamic> message = data['message'] as List<dynamic>;
@@ -136,8 +132,7 @@ class OnRamperBuyProvider extends BuyProvider {
132
133 return allAvailablePaymentMethods;
134 } else {
139 - final responseBody =
140 - jsonDecode(response.body) as Map<String, dynamic>;
135 + final responseBody = jsonDecode(response.body) as Map<String, dynamic>;
136 printV('Failed to fetch available payment types: ${responseBody['message']}');
137 return [];
138 }
@@ -151,9 +146,8 @@ class OnRamperBuyProvider extends BuyProvider {
146 final url = Uri.https(_baseApiUrl, '$supported/onramps/all');
147
148 try {
154 - final response =
155 - await ProxyWrapper().get(clearnetUri: url, headers: {'Authorization': _apiKey, 'accept': 'application/json'});
156 -
149 + final response = await ProxyWrapper()
150 + .get(clearnetUri: url, headers: {'Authorization': _apiKey, 'accept': 'application/json'});
151
152 if (response.statusCode == 200) {
153 final Map<String, dynamic> data = jsonDecode(response.body) as Map<String, dynamic>;
@@ -191,8 +185,10 @@ class OnRamperBuyProvider extends BuyProvider {
185 String? countryCode}) async {
186 String? paymentMethod;
187
194 - if (paymentType == PaymentType.all ) paymentMethod = null;
195 - else if (paymentType == PaymentType.unknown) paymentMethod = customPaymentMethodType;
188 + if (paymentType == PaymentType.all)
189 + paymentMethod = null;
190 + else if (paymentType == PaymentType.unknown)
191 + paymentMethod = customPaymentMethodType;
192 else if (paymentType != null) paymentMethod = normalizePaymentMethod(paymentType);
193
194 final actionType = isBuyAction ? 'buy' : 'sell';
@@ -217,7 +213,7 @@ class OnRamperBuyProvider extends BuyProvider {
213
214 try {
215 final response = await ProxyWrapper().get(clearnetUri: url, headers: headers);
220 -
216 +
217 if (response.statusCode == 200) {
218 final data = jsonDecode(response.body) as List<dynamic>;
219 if (data.isEmpty) return null;
@@ -227,7 +223,6 @@ class OnRamperBuyProvider extends BuyProvider {
223 if (_onrampMetadata.isEmpty) _onrampMetadata = await getOnrampMetadata();
224
225 for (var item in data) {
230 -
226 if (item['errors'] != null) continue;
227
228 final paymentMethod = (item as Map<String, dynamic>)['paymentMethod'] as String;
@@ -237,8 +232,8 @@ class OnRamperBuyProvider extends BuyProvider {
232
233 if (rampMetaData == null) continue;
234
240 - final quote = Quote.fromOnramperJson(
241 - item, isBuyAction, _onrampMetadata, _getPaymentTypeByString(paymentMethod), customPaymentMethodType);
235 + final quote = Quote.fromOnramperJson(item, isBuyAction, _onrampMetadata,
236 + _getPaymentTypeByString(paymentMethod), customPaymentMethodType);
237 quote.setFiatCurrency = fiatCurrency;
238 quote.setCryptoCurrency = cryptoCurrency;
239 validQuotes.add(quote);
@@ -266,18 +261,21 @@ class OnRamperBuyProvider extends BuyProvider {
261 String? countryCode}) async {
262 final actionType = isBuyAction ? 'buy' : 'sell';
263
269 - final primaryColor = getColorStr(Theme.of(context).colorScheme.primary,);
264 + final primaryColor = getColorStr(
265 + Theme.of(context).colorScheme.primary,
266 + );
267 final secondaryColor = getColorStr(Theme.of(context).colorScheme.surface);
268 final primaryTextColor = getColorStr(Theme.of(context).colorScheme.onSurface);
272 - final secondaryTextColor =
273 - getColorStr(Theme.of(context).colorScheme.onSurfaceVariant);
269 + final secondaryTextColor = getColorStr(Theme.of(context).colorScheme.onSurfaceVariant);
270 final containerColor = getColorStr(Theme.of(context).colorScheme.surface);
271 var cardColor = getColorStr(Theme.of(context).colorScheme.surfaceContainer);
272
273 final defaultCrypto =
274 quote.cryptoCurrency.title + _getNormalizeNetwork(quote.cryptoCurrency).toLowerCase();
275
280 - final paymentMethod = quote.paymentType == PaymentType.unknown ? quote.customPaymentMethodType : normalizePaymentMethod(quote.paymentType);
276 + final paymentMethod = quote.paymentType == PaymentType.unknown
277 + ? quote.customPaymentMethodType
278 + : normalizePaymentMethod(quote.paymentType);
279
280 final networkWallets =
281 '${_tagToNetwork(quote.cryptoCurrency.tag ?? quote.cryptoCurrency.title).toLowerCase()}:$cryptoCurrencyAddress';
lib/buy/robinhood/robinhood_buy_provider.dart
+3 -2
@@ -237,8 +237,9 @@ class RobinhoodBuyProvider extends BuyProvider {
237 Uri.https('api.robinhood.com', '/catpay/v1/${cryptoCurrency.title}/quote/', queryParams);
238
239 try {
240 - final response = await ProxyWrapper().get(clearnetUri: uri, headers: {'accept': 'application/json'});
241 -
240 + final response =
241 + await ProxyWrapper().get(clearnetUri: uri, headers: {'accept': 'application/json'});
242 +
243 final responseData = jsonDecode(response.body) as Map<String, dynamic>;
244
245 if (response.statusCode == 200) {
lib/buy/sell_buy_states.dart
+1 -2
@@ -8,7 +8,6 @@ class PaymentMethodLoaded extends PaymentMethodLoadingState {}
8
9 class PaymentMethodFailed extends PaymentMethodLoadingState {}
10
11 -
11 abstract class BuySellQuotLoadingState {}
12
13 class InitialBuySellQuotState extends BuySellQuotLoadingState {}
@@ -21,4 +20,4 @@ class BuySellQuotFailed extends BuySellQuotLoadingState {
20 final String? errorMessage;
21
22 BuySellQuotFailed({this.errorMessage});
24 -}
\ No newline at end of file
23 +}
lib/buy/wyre/wyre_buy_provider.dart
+7 -9
@@ -19,13 +19,13 @@ class WyreBuyProvider extends BuyProvider {
19 WyreBuyProvider({required WalletBase wallet, bool isTestEnvironment = false})
20 : baseApiUrl = isTestEnvironment ? _baseTestApiUrl : _baseProductApiUrl,
21 super(
22 - wallet: wallet,
23 - isTestEnvironment: isTestEnvironment,
24 - hardwareWalletVM: null,
25 - supportedCryptoList: supportedCryptoToFiatPairs(
26 - notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
27 - supportedFiatList: supportedFiatToCryptoPairs(
28 - notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
22 + wallet: wallet,
23 + isTestEnvironment: isTestEnvironment,
24 + hardwareWalletVM: null,
25 + supportedCryptoList: supportedCryptoToFiatPairs(
26 + notSupportedCrypto: _notSupportedCrypto, notSupportedFiat: _notSupportedFiat),
27 + supportedFiatList: supportedFiatToCryptoPairs(
28 + notSupportedFiat: _notSupportedFiat, notSupportedCrypto: _notSupportedCrypto));
29
30 static const _baseTestApiUrl = 'https://api.testwyre.com';
31 static const _baseProductApiUrl = 'https://api.sendwyre.com';
@@ -89,7 +89,6 @@ class WyreBuyProvider extends BuyProvider {
89 throw BuyException(title: providerDescription, content: 'Url $url is not found!');
90 }
91
92 -
92 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
93 final urlFromResponse = responseJSON['url'] as String;
94 return urlFromResponse;
@@ -120,7 +119,6 @@ class WyreBuyProvider extends BuyProvider {
119 throw BuyException(title: providerDescription, content: 'Quote is not found!');
120 }
121
123 -
122 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
123 final sourceAmount = responseJSON['sourceAmount'] as double;
124 final destAmount = responseJSON['destAmount'] as double;
lib/cake_pay/src/auth/cake_pay_account_page.dart
+6 -9
@@ -25,8 +25,7 @@ class CakePayAccountPage extends BasePage {
25 label: S.of(context).seed_alert_back,
26 child: TextButton(
27 style: ButtonStyle(
28 - overlayColor: WidgetStateColor.resolveWith(
29 - (states) => Colors.transparent),
28 + overlayColor: WidgetStateColor.resolveWith((states) => Colors.transparent),
29 ),
30 onPressed: () => Navigator.pop(context),
31 child: backButton(context),
@@ -41,10 +40,10 @@ class CakePayAccountPage extends BasePage {
40 Widget middle(BuildContext context) {
41 return Text(
42 S.current.account,
44 - style: Theme.of(context).textTheme.titleMedium?.copyWith(
45 - color: Theme.of(context).colorScheme.onSurface,
46 - fontWeight: FontWeight.w600,
47 - ),
43 + style: Theme.of(context).textTheme.titleMedium?.copyWith(
44 + color: Theme.of(context).colorScheme.onSurface,
45 + fontWeight: FontWeight.w600,
46 + ),
47 );
48 }
49
@@ -66,9 +65,7 @@ class CakePayAccountPage extends BasePage {
65 ),
66 ),
67 child: CakePayTile(
69 - title: S.of(context).email_address,
70 - subTitle: cakePayAccountViewModel.email
71 - ),
68 + title: S.of(context).email_address, subTitle: cakePayAccountViewModel.email),
69 ),
70 ),
71 ],
lib/cake_pay/src/auth/cake_pay_verify_otp_page.dart
+1 -3
@@ -146,9 +146,7 @@ class CakePayVerifyOtpPage extends BasePage {
146 });
147 }
148
149 -
150 - void _onOtpSuccessful(BuildContext context) =>
151 - Navigator.pop(context, true);
149 + void _onOtpSuccessful(BuildContext context) => Navigator.pop(context, true);
150
151 void _verify() async => await _authViewModel.verifyEmail(_codeController.text);
152 }
lib/cake_pay/src/cake_pay_states.dart
-1
@@ -58,7 +58,6 @@ class UserCakePayCardsStateFailure extends UserCakePayCardsState {
58
59 class UserCakePayCardsStateSuccess extends UserCakePayCardsState {}
60
61 -
61 abstract class CakePayVendorState {}
62
63 class InitialCakePayVendorLoadingState extends CakePayVendorState {}
lib/cake_pay/src/cards/cake_pay_buy_card_page.dart
+8 -9
@@ -360,7 +360,8 @@ class CakePayBuyCardPage extends BasePage {
360 },
361 text: S.of(context).purchase_gift_card,
362 isDisabled: !cakePayBuyCardViewModel.isAmountSufficient ||
363 - cakePayBuyCardViewModel.isPurchasing || _sendViewModel.state is ExecutedSuccessfullyState,
363 + cakePayBuyCardViewModel.isPurchasing ||
364 + _sendViewModel.state is ExecutedSuccessfullyState,
365 isLoading: _sendViewModel.state is IsExecutingState ||
366 cakePayBuyCardViewModel.isPurchasing,
367 color: Theme.of(context).colorScheme.primary,
@@ -585,8 +586,7 @@ class CakePayBuyCardPage extends BasePage {
586 .map((o) => o.OutputCopyWithParsedAddress(
587 parsedAddress: ParsedAddress(
588 parsedAddressByCurrencyMap: {
588 - cakePayBuyCardViewModel.sendViewModel.selectedCryptoCurrency:
589 - o.address,
589 + cakePayBuyCardViewModel.sendViewModel.selectedCryptoCurrency: o.address,
590 },
591 handle: 'Cake Pay',
592 profileName: order?.cards.first.cardName ?? 'Cake Pay',
@@ -613,13 +613,13 @@ class CakePayBuyCardPage extends BasePage {
613 titleIconPath: _sendViewModel.selectedCryptoCurrency.iconPath,
614 currency: _sendViewModel.selectedCryptoCurrency,
615 amount: S.of(bottomSheetContext).send_amount,
616 - amountValue: _sendViewModel.amountParsingProxy.asDisplayStringWithSymbol(
617 - _sendViewModel.pendingTransaction!.amount),
616 + amountValue: _sendViewModel.amountParsingProxy
617 + .asDisplayStringWithSymbol(_sendViewModel.pendingTransaction!.amount),
618 quantity: 'QTY: ${cakePayBuyCardViewModel.quantity}',
619 fiatAmountValue: _sendViewModel.pendingTransactionFiatAmountFormatted,
620 fee: S.of(bottomSheetContext).send_fee,
621 - feeValue: _sendViewModel.amountParsingProxy.asDisplayStringWithSymbol(
622 - _sendViewModel.pendingTransaction!.fee),
621 + feeValue: _sendViewModel.amountParsingProxy
622 + .asDisplayStringWithSymbol(_sendViewModel.pendingTransaction!.fee),
623 feeFiatAmount: _sendViewModel.pendingTransactionFeeFiatAmountFormatted,
624 outputs: displayingOutputs,
625 footerType: FooterType.slideActionButton,
@@ -657,8 +657,7 @@ class CakePayBuyCardPage extends BasePage {
657 .map((o) => o.OutputCopyWithParsedAddress(
658 parsedAddress: ParsedAddress(
659 parsedAddressByCurrencyMap: {
660 - cakePayBuyCardViewModel.sendViewModel.selectedCryptoCurrency:
661 - o.address,
660 + cakePayBuyCardViewModel.sendViewModel.selectedCryptoCurrency: o.address,
661 },
662 handle: 'Cake Pay',
663 profileName: order?.cards.first.cardName ?? 'Cake Pay',
lib/cake_pay/src/cards/cake_pay_cards_page.dart
+3 -1
@@ -92,7 +92,9 @@ class CakePayCardsPage extends BasePage {
92
93 @override
94 Widget body(BuildContext context) {
95 - return KeyboardHideOverlay(child:CakePayCardsPageBody(cardsListViewModel: _cardsListViewModel, titleColor: titleColor));
95 + return KeyboardHideOverlay(
96 + child:
97 + CakePayCardsPageBody(cardsListViewModel: _cardsListViewModel, titleColor: titleColor));
98 }
99 }
100
lib/cake_pay/src/models/cake_pay_card.dart
+6 -1
@@ -45,7 +45,11 @@ class CakePayCard {
45 final parsedMinValueLocal = _toDouble(json['min_value']);
46 final parsedMinValueUsd = _toDouble(json['min_value_usd']);
47
48 - if (parsedMinValueLocal != null && parsedMinValueLocal > 0 && parsedMinValueUsd != null && parsedMinValueUsd > 0 && parsedMinValueUsd < 10.0) {
48 + if (parsedMinValueLocal != null &&
49 + parsedMinValueLocal > 0 &&
50 + parsedMinValueUsd != null &&
51 + parsedMinValueUsd > 0 &&
52 + parsedMinValueUsd < 10.0) {
53 final rate = parsedMinValueLocal / parsedMinValueUsd;
54 final minLocalValueLimit = 10.0 * rate;
55 minValue = minLocalValueLimit.toStringAsFixed(2);
@@ -80,6 +84,7 @@ class CakePayCard {
84 static String stripHtmlIfNeeded(String text) {
85 return text.replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), ' ');
86 }
87 +
88 static double? _toDouble(dynamic v) {
89 if (v == null) return null;
90 if (v is num) return v.toDouble();
lib/cake_pay/src/models/cake_pay_order.dart
+19 -12
@@ -37,15 +37,12 @@ class CakePayOrder {
37 });
38
39 factory CakePayOrder.fromMap(Map<String, dynamic> map) {
40 -
40 final cards = map['cards'] as List<dynamic>;
41 final firstCard = cards.isNotEmpty ? cards.first as Map<String, dynamic> : {};
42
43 return CakePayOrder(
44 orderId: map['order_id'] as String,
46 - cards: cards
47 - .map((x) => OrderCard.fromMap(x as Map<String, dynamic>))
48 - .toList(),
45 + cards: cards.map((x) => OrderCard.fromMap(x as Map<String, dynamic>)).toList(),
46 externalId: map['external_id'] as String?,
47 amountUsd: map['amount_usd'] as double,
48 totalReceiveAmount: firstCard['subtotal'] as String? ?? '',
@@ -56,7 +53,7 @@ class CakePayOrder {
53 paymentData: PaymentData.fromMap(map['payment_data'] as Map<String, dynamic>));
54 }
55
59 - static CryptoPaymentData? getPaymentDataFor({CakePayPaymentMethod? method,CakePayOrder? order}) {
56 + static CryptoPaymentData? getPaymentDataFor({CakePayPaymentMethod? method, CakePayOrder? order}) {
57 if (order == null || method == null) return null;
58
59 final data = switch (method) {
@@ -76,7 +73,8 @@ class CakePayOrder {
73 final addr = uri.path;
74 final price = uri.queryParameters['amount'] ?? data.price;
75
79 - return CryptoPaymentData(price: price, address: addr, amount: data.amount, paymentUrls: data.paymentUrls);
76 + return CryptoPaymentData(
77 + price: price, address: addr, amount: data.amount, paymentUrls: data.paymentUrls);
78 }
79
80 return data;
@@ -151,12 +149,21 @@ class PaymentData {
149
150 factory PaymentData.fromMap(Map<String, dynamic> map) {
151 return PaymentData(
154 - btc: map['BTC'] != null ? CryptoPaymentData.fromMap(map['BTC'] as Map<String, dynamic>) : null,
155 - btc_ln: map['BTC_LN'] != null ? CryptoPaymentData.fromMap(map['BTC_LN'] as Map<String, dynamic>) : null,
156 - xmr: map['XMR'] != null ? CryptoPaymentData.fromMap(map['XMR'] as Map<String, dynamic>) : null,
157 - ltc: map['LTC'] != null ? CryptoPaymentData.fromMap(map['LTC'] as Map<String, dynamic>) : null,
158 - ltc_mweb: map['LTC_MWEB'] != null ? CryptoPaymentData.fromMap(map['LTC_MWEB'] as Map<String, dynamic>) : null,
159 - zec: map['ZEC_CHAIN'] != null ? CryptoPaymentData.fromMap(map['ZEC_CHAIN'] as Map<String, dynamic>) : null,
152 + btc:
153 + map['BTC'] != null ? CryptoPaymentData.fromMap(map['BTC'] as Map<String, dynamic>) : null,
154 + btc_ln: map['BTC_LN'] != null
155 + ? CryptoPaymentData.fromMap(map['BTC_LN'] as Map<String, dynamic>)
156 + : null,
157 + xmr:
158 + map['XMR'] != null ? CryptoPaymentData.fromMap(map['XMR'] as Map<String, dynamic>) : null,
159 + ltc:
160 + map['LTC'] != null ? CryptoPaymentData.fromMap(map['LTC'] as Map<String, dynamic>) : null,
161 + ltc_mweb: map['LTC_MWEB'] != null
162 + ? CryptoPaymentData.fromMap(map['LTC_MWEB'] as Map<String, dynamic>)
163 + : null,
164 + zec: map['ZEC_CHAIN'] != null
165 + ? CryptoPaymentData.fromMap(map['ZEC_CHAIN'] as Map<String, dynamic>)
166 + : null,
167 invoiceTime: DateTime.fromMillisecondsSinceEpoch(map['invoice_time'] as int),
168 expirationTime: DateTime.fromMillisecondsSinceEpoch(map['expiration_time'] as int),
169 commission: map['commission'] as int?,
lib/cake_pay/src/models/cake_pay_user_credentials.dart
+4 -4
@@ -1,6 +1,6 @@
1 class CakePayUserCredentials {
2 - const CakePayUserCredentials(this.username, this.token);
2 + const CakePayUserCredentials(this.username, this.token);
3
4 - final String username;
5 - final String token;
6 -}
\ No newline at end of file
4 + final String username;
5 + final String token;
6 +}
lib/cake_pay/src/widgets/cake_pay_tile.dart
+6 -6
@@ -15,7 +15,7 @@ class CakePayTile extends StatelessWidget {
15 @override
16 Widget build(BuildContext context) {
17 final colorScheme = Theme.of(context).colorScheme;
18 -
18 +
19 return GestureDetector(
20 onTap: onTap,
21 child: Row(
@@ -27,16 +27,16 @@ class CakePayTile extends StatelessWidget {
27 Text(
28 title,
29 style: Theme.of(context).textTheme.bodySmall?.copyWith(
30 - color: colorScheme.onSurfaceVariant,
31 - ),
30 + color: colorScheme.onSurfaceVariant,
31 + ),
32 ),
33 SizedBox(height: 8),
34 Text(
35 subTitle,
36 style: Theme.of(context).textTheme.titleMedium?.copyWith(
37 - color: colorScheme.onSurface,
38 - fontWeight: FontWeight.w600,
39 - ),
37 + color: colorScheme.onSurface,
38 + fontWeight: FontWeight.w600,
39 + ),
40 ),
41 ],
42 )
lib/cake_pay/src/widgets/denominations_amount_widget.dart
+7 -7
@@ -65,18 +65,18 @@ class _DenominationsAmountWidgetState extends State<DenominationsAmountWidget> {
65 mainAxisSize: MainAxisSize.min,
66 children: [
67 DropdownFilterList(
68 - items: widget.denominations
69 - .map((e) => e.value.toString())
70 - .toList(),
68 + items: widget.denominations.map((e) => e.value.toString()).toList(),
69 itemPrefix: widget.fiatCurrency,
70 selectedItem: _selected.$1,
71 onItemSelected: (value) {
74 - setState(() => _selected = (value, widget.denominations
75 - .firstWhere((e) => e.value.toString() == value)
76 - .cardId));
72 + setState(() => _selected = (
73 + value,
74 + widget.denominations.firstWhere((e) => e.value.toString() == value).cardId
75 + ));
76 widget.amountController.text = value;
77 widget.onAmountChanged(value);
79 - widget.cakePayBuyCardViewModel.selectedDenomination = (_selected.$1, _selected.$2);
78 + widget.cakePayBuyCardViewModel.selectedDenomination =
79 + (_selected.$1, _selected.$2);
80 },
81 ),
82 const SizedBox(height: 4),
lib/cake_pay/src/widgets/enter_amount_widget.dart
+9 -10
@@ -59,12 +59,11 @@ class EnterAmountWidget extends StatelessWidget {
59 mainAxisSize: MainAxisSize.min,
60 children: [
61 Text('QTY ', style: Theme.of(context).textTheme.titleMedium!),
62 - Text(
63 - '1',
64 - style: Theme.of(context).textTheme
65 - .titleMedium!
66 - .copyWith(color: Theme.of(context).colorScheme.onSurfaceVariant)
67 - ),
62 + Text('1',
63 + style: Theme.of(context)
64 + .textTheme
65 + .titleMedium!
66 + .copyWith(color: Theme.of(context).colorScheme.onSurfaceVariant)),
67 ],
68 ),
69 ),
@@ -87,12 +86,12 @@ class EnterAmountWidget extends StatelessWidget {
86 children: [
87 Text(S.of(context).min_amount(minValue) + ' $fiatCurrency',
88 style: Theme.of(context).textTheme.bodySmall?.copyWith(
90 - color: Theme.of(context).colorScheme.onSurfaceVariant,
91 - )),
89 + color: Theme.of(context).colorScheme.onSurfaceVariant,
90 + )),
91 Text(S.of(context).max_amount(maxValue) + ' $fiatCurrency',
92 style: Theme.of(context).textTheme.bodySmall?.copyWith(
94 - color: Theme.of(context).colorScheme.onSurfaceVariant,
95 - )),
93 + color: Theme.of(context).colorScheme.onSurfaceVariant,
94 + )),
95 ],
96 ),
97 Spacer(flex: 1),
lib/cake_pay/src/widgets/flip_card_widget.dart
+8 -9
@@ -21,7 +21,7 @@ class FlipCard extends StatefulWidget {
21
22 class FlipCardState extends State<FlipCard> with SingleTickerProviderStateMixin {
23 late final AnimationController _ctrl =
24 - AnimationController(vsync: this, duration: widget.duration);
24 + AnimationController(vsync: this, duration: widget.duration);
25 bool _isFront = true;
26
27 void toggleCard() {
@@ -45,18 +45,17 @@ class FlipCardState extends State<FlipCard> with SingleTickerProviderStateMixin
45 transform: Matrix4.identity()
46 ..setEntry(3, 2, 0.001)
47 ..rotateY(angle),
48 - child: isFront ? widget.front
48 + child: isFront
49 + ? widget.front
50 : Transform(
50 - alignment: Alignment.center,
51 - transform: Matrix4.rotationY(math.pi),
52 - child: widget.back,
53 - ),
51 + alignment: Alignment.center,
52 + transform: Matrix4.rotationY(math.pi),
53 + child: widget.back,
54 + ),
55 );
56 },
57 );
58
58 - return widget.flipOnTouch
59 - ? GestureDetector(onTap: toggleCard, child: content)
60 - : content;
59 + return widget.flipOnTouch ? GestureDetector(onTap: toggleCard, child: content) : content;
60 }
61 }
lib/cake_pay/src/widgets/link_extractor.dart
+1 -1
@@ -31,7 +31,7 @@ class ClickableLinksText extends StatelessWidget {
31 text: url,
32 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
33 color: Theme.of(context).colorScheme.primary,
34 - fontSize: 18,
34 + fontSize: 18,
35 ),
36 recognizer: TapGestureRecognizer()
37 ..onTap = () async {
lib/cake_pay/src/widgets/rounded_overlay_cards_widget.dart
+7 -8
@@ -14,16 +14,15 @@ class RoundedOverlayCards extends StatelessWidget {
14 final screenHeight = MediaQuery.of(context).size.height;
15 return ClipRRect(
16 borderRadius:
17 - BorderRadius.only(bottomLeft: Radius.circular(25.0), bottomRight: Radius.circular(25.0)),
17 + BorderRadius.only(bottomLeft: Radius.circular(25.0), bottomRight: Radius.circular(25.0)),
18 child: Container(
19 height: screenHeight * 0.50,
20 decoration: BoxDecoration(
21 - borderRadius: BorderRadius.only(
22 - bottomLeft: Radius.circular(24),
23 - bottomRight: Radius.circular(24),
24 - ),
25 - color: Theme.of(context).colorScheme.surfaceContainer
26 - ),
21 + borderRadius: BorderRadius.only(
22 + bottomLeft: Radius.circular(24),
23 + bottomRight: Radius.circular(24),
24 + ),
25 + color: Theme.of(context).colorScheme.surfaceContainer),
26 child: Column(
27 children: [
28 ClipRRect(
@@ -44,4 +43,4 @@ class RoundedOverlayCards extends StatelessWidget {
43 ),
44 );
45 }
47 -}
\ No newline at end of file
46 +}
lib/cake_pay/src/widgets/three_checkbox_alert_content_widget.dart
+9 -9
@@ -48,8 +48,8 @@ class ThreeCheckboxAlert extends BaseAlertDialog {
48
49 @override
50 VoidCallback get actionRight => () {
51 - actionRightButton(checkbox1, checkbox2, checkbox3);
52 - };
51 + actionRightButton(checkbox1, checkbox2, checkbox3);
52 + };
53
54 @override
55 bool get barrierDismissible => alertBarrierDismissible;
@@ -87,13 +87,13 @@ class ThreeCheckboxAlertContent extends StatefulWidget {
87
88 @override
89 _ThreeCheckboxAlertContentState createState() => _ThreeCheckboxAlertContentState(
90 - checkbox1: checkbox1,
91 - toggleCheckbox1: toggleCheckbox1,
92 - checkbox2: checkbox2,
93 - toggleCheckbox2: toggleCheckbox2,
94 - checkbox3: checkbox3,
95 - toggleCheckbox3: toggleCheckbox3,
96 - );
90 + checkbox1: checkbox1,
91 + toggleCheckbox1: toggleCheckbox1,
92 + checkbox2: checkbox2,
93 + toggleCheckbox2: toggleCheckbox2,
94 + checkbox3: checkbox3,
95 + toggleCheckbox3: toggleCheckbox3,
96 + );
97
98 static _ThreeCheckboxAlertContentState? of(BuildContext context) {
99 return context.findAncestorStateOfType<_ThreeCheckboxAlertContentState>();
lib/cake_pay/src/widgets/user_card_item.dart
+2 -7
@@ -2,12 +2,7 @@ import 'package:flutter/material.dart';
2 import 'image_placeholder.dart';
3
4 class UserCardItem extends StatelessWidget {
5 - UserCardItem({
6 - required this.title,
7 - required this.subTitle,
8 - this.onTap,
9 - this.logoUrl
10 - });
5 + UserCardItem({required this.title, required this.subTitle, this.onTap, this.logoUrl});
6
7 final VoidCallback? onTap;
8 final String title;
@@ -80,4 +75,4 @@ class UserCardItem extends StatelessWidget {
75 ),
76 );
77 }
83 -}
\ No newline at end of file
78 +}
lib/core/address_resolver/address_lookup_provider.dart
-1
@@ -5,7 +5,6 @@ import 'package:cw_core/crypto_currency.dart';
5 import 'package:cw_core/wallet_base.dart';
6
7 abstract class AddressLookupProvider {
8 -
8 AddressSource get source;
9
10 List<CryptoCurrency> get supportedCurrencies;
lib/core/address_resolver/address_resolver_service.dart
+2 -1
@@ -104,7 +104,8 @@ class AddressResolverService {
104
105 if (results.isNotEmpty) {
106 final parsedAddress = results.first.parsedAddressByCurrencyMap[currency];
107 - final parsedAddressStr = parsedAddress == null || parsedAddress.isEmpty ? 'N/A' : parsedAddress;
107 + final parsedAddressStr =
108 + parsedAddress == null || parsedAddress.isEmpty ? 'N/A' : parsedAddress;
109 printV('[address resolver service] resolved $src - $cur - $parsedAddressStr');
110 return [results.first];
111 }
lib/core/address_resolver/address_resolver_utils.dart
+2 -1
@@ -14,7 +14,8 @@ class AddressResolverUtils {
14 final result = <CryptoCurrency, String>{};
15
16 for (final currency in currencies) {
17 - final address = await UnstoppableAddressProvider.fetchUnstoppableDomainAddress(domain, currency.title);
17 + final address =
18 + await UnstoppableAddressProvider.fetchUnstoppableDomainAddress(domain, currency.title);
19 if (address.isNotEmpty) {
20 result[currency] = address;
21 }
lib/core/address_resolver/bip_353/bip_353_address_provider.dart
+9 -7
@@ -54,15 +54,17 @@ class Bip353AddressProvider extends AddressLookupProvider {
54 printV('Bip353Record.fetchDnsProof error: $e');
55 }
56
57 - return [ParsedAddress(
58 - parsedAddressByCurrencyMap: result,
59 - addressSource: AddressSource.bip353,
60 - handle: query,
61 - bip353DnsProof: dnsProof ?? '',
62 - )];
57 + return [
58 + ParsedAddress(
59 + parsedAddressByCurrencyMap: result,
60 + addressSource: AddressSource.bip353,
61 + handle: query,
62 + bip353DnsProof: dnsProof ?? '',
63 + )
64 + ];
65 } catch (e) {
66 printV('[address resolver] Error resolving BIP353 address: $e');
67 return [];
68 }
69 }
68 -}
\ No newline at end of file
70 +}
lib/core/address_resolver/bip_353/bip_353_record.dart
+1 -2
@@ -99,5 +99,4 @@ class Bip353Record {
99 return result;
100 }
101 }
102 -
103 -}
\ No newline at end of file
102 +}
lib/core/address_resolver/ens/ens_record.dart
+12 -12
@@ -9,10 +9,10 @@ import 'package:web3dart/web3dart.dart';
9
10 class EnsRecord {
11 static Future<String> fetchEnsAddress(
12 - String name,
13 - CryptoCurrency cur, {
14 - WalletBase? wallet,
15 - }) async {
12 + String name,
13 + CryptoCurrency cur, {
14 + WalletBase? wallet,
15 + }) async {
16 Web3Client? _client;
17
18 if (wallet?.type == WalletType.ethereum || wallet?.type == WalletType.polygon) {
@@ -45,11 +45,11 @@ class EnsRecord {
45 }
46
47 static CoinType? getEnsCoinType(CryptoCurrency cur) => switch (cur) {
48 - CryptoCurrency.xmr => CoinType.XMR,
49 - CryptoCurrency.btc => CoinType.BTC,
50 - CryptoCurrency.ltc => CoinType.LTC,
51 - CryptoCurrency.eth => CoinType.ETH,
52 - CryptoCurrency.matic => CoinType.MATIC,
53 - _ => null,
54 - };
55 -}
\ No newline at end of file
48 + CryptoCurrency.xmr => CoinType.XMR,
49 + CryptoCurrency.btc => CoinType.BTC,
50 + CryptoCurrency.ltc => CoinType.LTC,
51 + CryptoCurrency.eth => CoinType.ETH,
52 + CryptoCurrency.matic => CoinType.MATIC,
53 + _ => null,
54 + };
55 +}
lib/core/address_resolver/fio/fio_address_provider.dart
+15 -15
@@ -34,23 +34,23 @@ class FioAddressProvider extends AddressLookupProvider {
34 }) async {
35 final Map<CryptoCurrency, String> result = {};
36 try {
37 - final bool isFioRegistered = await FioAddressProvider.checkAvail(query);
38 - if (!isFioRegistered) return [];
39 -
40 - for (final cur in currencies) {
41 - final address = await FioAddressProvider.getPubAddress(query, cur.title);
42 - if (address != null && address.isNotEmpty) {
43 - result[cur] = address;
37 + final bool isFioRegistered = await FioAddressProvider.checkAvail(query);
38 + if (!isFioRegistered) return [];
39 +
40 + for (final cur in currencies) {
41 + final address = await FioAddressProvider.getPubAddress(query, cur.title);
42 + if (address != null && address.isNotEmpty) {
43 + result[cur] = address;
44 + }
45 }
45 - }
46
47 - if (result.isNotEmpty) {
48 - return [
49 - ParsedAddress(
50 - parsedAddressByCurrencyMap: result, addressSource: AddressSource.fio, handle: query)
51 - ];
52 - }
53 - return [];
47 + if (result.isNotEmpty) {
48 + return [
49 + ParsedAddress(
50 + parsedAddressByCurrencyMap: result, addressSource: AddressSource.fio, handle: query)
51 + ];
52 + }
53 + return [];
54 } catch (e) {
55 printV('FioAddressProvider.resolve error: $e');
56 return [];
lib/core/address_resolver/lnurl_pay/lnurl_pay_address_provider.dart
+3 -2
@@ -16,7 +16,8 @@ class LNUrlPayAddressProvider extends AddressLookupProvider {
16 List<CryptoCurrency> get supportedCurrencies => [CryptoCurrency.btcln];
17
18 @override
19 - bool canHandle(String q) => q.contains('.') && q.contains('@'); // LNURL-pay handle example: user@domain.com
19 + bool canHandle(String q) =>
20 + q.contains('.') && q.contains('@'); // LNURL-pay handle example: user@domain.com
21
22 @override
23 bool isEnabled(SettingsStore settingsStore) => settingsStore.lookupsLNUrl;
@@ -63,4 +64,4 @@ class LNUrlPayAddressProvider extends AddressLookupProvider {
64 return [];
65 }
66 }
66 -}
\ No newline at end of file
67 +}
lib/core/address_resolver/lnurl_pay/lnurlpay_record.dart
+1 -1
@@ -13,7 +13,7 @@ class LNUrlPayRecord {
13 final String address;
14
15 static Future<String?> checkWellKnownUsername(String username, CryptoCurrency currency,
16 - {bool allowRethrow = false}) async {
16 + {bool allowRethrow = false}) async {
17 if (![CryptoCurrency.btc, CryptoCurrency.btcln].contains(currency)) return null;
18
19 // split the string by the @ symbol:
lib/core/address_resolver/mastodon/mastodon_api.dart
-2
@@ -21,7 +21,6 @@ class MastodonAPI {
21 );
22
23 final response = await ProxyWrapper().get(clearnetUri: uri);
24 -
24
25 if (response.statusCode != 200) return null;
26
@@ -49,7 +48,6 @@ class MastodonAPI {
48 );
49
50 final response = await ProxyWrapper().get(clearnetUri: uri);
52 -
51
52 if (response.statusCode != 200) {
53 throw Exception('Unexpected HTTP status: ${response.statusCode}');
lib/core/address_resolver/mastodon/mastodon_user.dart
+5 -6
@@ -15,12 +15,11 @@ class MastodonUser {
15
16 factory MastodonUser.fromJson(Map<String, dynamic> json) {
17 return MastodonUser(
18 - id: json['id'] as String,
19 - username: json['username'] as String? ?? '',
20 - acct: json['acct'] as String,
21 - note: json['note'] as String,
22 - profileImageUrl: json['avatar'] as String? ?? ''
23 - );
18 + id: json['id'] as String,
19 + username: json['username'] as String? ?? '',
20 + acct: json['acct'] as String,
21 + note: json['note'] as String,
22 + profileImageUrl: json['avatar'] as String? ?? '');
23 }
24 }
25
lib/core/address_resolver/nostr/nostr_api.dart
+4 -4
@@ -21,9 +21,9 @@ class NostrProfileHandler {
21 }
22
23 static Future<UserMetadata?> processRelays(
24 - ProfilePointer profile,
25 - String nip05Address,
26 - ) async {
24 + ProfilePointer profile,
25 + String nip05Address,
26 + ) async {
27 final userDomain = _extractDomain(nip05Address);
28 const int metaKind = 0;
29
@@ -124,4 +124,4 @@ class NostrProfileHandler {
124 return '';
125 }
126 }
127 -}
\ No newline at end of file
127 +}
lib/core/address_resolver/nostr/nostr_user.dart
+1 -2
@@ -1,4 +1,3 @@
1 -
1 class UserMetadata {
2 final String name;
3 final String lnurl;
@@ -32,4 +31,4 @@ class UserMetadata {
31 website: json['website'] as String? ?? '',
32 );
33 }
35 -}
\ No newline at end of file
34 +}
lib/core/address_resolver/openalias/openalias_record.dart
+1 -1
@@ -66,4 +66,4 @@ class OpenaliasRecord {
66
67 return OpenaliasRecord(address: address, name: name, description: note);
68 }
69 -}
\ No newline at end of file
69 +}
lib/core/address_resolver/parsed_address.dart
+1 -1
@@ -19,4 +19,4 @@ class ParsedAddress {
19 final String profileName;
20 final String description;
21 final String? bip353DnsProof;
22 -}
\ No newline at end of file
22 +}
lib/core/address_resolver/twitter/twitter_address_provider.dart
-1
@@ -11,7 +11,6 @@ import 'package:cw_core/utils/print_verbose.dart';
11 import 'package:cw_core/wallet_base.dart';
12
13 class TwitterAddressProvider extends AddressLookupProvider {
14 -
14 @override
15 AddressSource get source => AddressSource.twitter;
16
lib/core/address_resolver/twitter/twitter_api.dart
+2 -2
@@ -23,14 +23,14 @@ class TwitterApi {
23 path: userPath + userName,
24 queryParameters: queryParams);
25
26 - final response = await ProxyWrapper().get(clearnetUri: uri, headers: headers).catchError((error) {
26 + final response =
27 + await ProxyWrapper().get(clearnetUri: uri, headers: headers).catchError((error) {
28 throw Exception('HTTP request failed: $error');
29 });
30
31 if (response.statusCode != 200) {
32 throw Exception('Unexpected http status: ${response.statusCode}');
33 }
33 -
34
35 final Map<String, dynamic> responseJSON = jsonDecode(response.body) as Map<String, dynamic>;
36 if (responseJSON['errors'] != null &&
lib/core/address_resolver/unstoppable/unstoppable_address_provider.dart
+4 -2
@@ -211,13 +211,15 @@ class UnstoppableAddressProvider extends AddressLookupProvider {
211 var address = '';
212
213 try {
214 - final uri = Uri.parse("https://api.unstoppabledomains.com/profile/public/${Uri.encodeQueryComponent(domain)}?fields=records");
214 + final uri = Uri.parse(
215 + "https://api.unstoppabledomains.com/profile/public/${Uri.encodeQueryComponent(domain)}?fields=records");
216 final response = await ProxyWrapper().get(clearnetUri: uri);
217
218 final jsonParsed = json.decode(response.body) as Map<String, dynamic>;
219 if (jsonParsed["records"] == null) {
220 throw Exception(".records response from $uri is empty");
220 - };
221 + }
222 + ;
223 final records = jsonParsed["records"] as Map<String, dynamic>;
224 final key = "crypto.${ticker.toUpperCase()}.address";
225 if (records[key] == null) {
lib/core/address_resolver/wellknown/wellknown_record.dart
+4 -4
@@ -20,9 +20,9 @@ class WellKnownRecord {
20 static const _jsonLocation = {CryptoCurrency.nano: 'nano-currency'};
21
22 static Future<WellKnownRecord?> fetch(
23 - String username,
24 - CryptoCurrency currency,
25 - ) async {
23 + String username,
24 + CryptoCurrency currency,
25 + ) async {
26 final location = _jsonLocation[currency];
27 if (location == null) {
28 printV('well-known: unsupported coin $currency');
@@ -75,4 +75,4 @@ class WellKnownRecord {
75 }
76 return null;
77 }
78 -}
\ No newline at end of file
78 +}
lib/core/address_resolver/yat/yat_record.dart
+1 -1
@@ -16,4 +16,4 @@ class YatRecord {
16
17 @override
18 String toString() => 'YatRecord(tag: $tag, address: $address)';
19 -}
\ No newline at end of file
19 +}
lib/core/address_resolver/yat/yat_service.dart
+6 -9
@@ -11,8 +11,7 @@ class YatService {
11 static const apiReleaseUrl = "https://a.y.at";
12 static const apiDevUrl = 'https://a.yat.fyi';
13
14 - static String lookupEmojiUrl(String emojiId) =>
15 - "$apiUrl/emoji_id/$emojiId/payment";
14 + static String lookupEmojiUrl(String emojiId) => "$apiUrl/emoji_id/$emojiId/payment";
15
16 static const String MONERO_SUB_ADDRESS = '0x1002';
17 static const String MONERO_STD_ADDRESS = '0x1001';
@@ -23,9 +22,9 @@ class YatService {
22 };
23
24 static Future<List<YatRecord>> fetchYatAddress(
26 - String emojiId,
27 - String ticker,
28 - ) async {
25 + String emojiId,
26 + String ticker,
27 + ) async {
28 final tagQuery = tags[ticker.toUpperCase()];
29 if (tagQuery == null) return const [];
30
@@ -48,9 +47,7 @@ class YatService {
47 records.add(YatRecord.fromJson(data, tag.toString()));
48 }
49 });
51 - }
52 -
53 - else if (res is List) {
50 + } else if (res is List) {
51 for (final item in res) {
52 if (item is Map<String, dynamic>) {
53 final tag = item['tag']?.toString() ?? '';
@@ -64,4 +61,4 @@ class YatService {
61 return const [];
62 }
63 }
67 -}
\ No newline at end of file
64 +}
lib/core/address_resolver/yat/yat_store.dart
+30 -34
@@ -25,29 +25,28 @@ class YatLink {
25 static const requestReleaseUrl = ''; //'https://a.y.at/emoji_id/';
26 static const startFlowUrl = ''; // 'https://www.y03btrk.com/4RQSJ/6JHXF/';
27 static const isDevMode = true;
28 - static const tags = <String, List<String>>{"XMR" : ['0x1001', '0x1002'],
29 - "BTC" : ['0x1003'], "LTC" : ['0x1019']};
28 + static const tags = <String, List<String>>{
29 + "XMR": ['0x1001', '0x1002'],
30 + "BTC": ['0x1003'],
31 + "LTC": ['0x1019']
32 + };
33
31 - static String get apiUrl => YatLink.isDevMode
32 - ? YatLink.apiDevUrl
33 - : YatLink.apiReleaseUrl;
34 + static String get apiUrl => YatLink.isDevMode ? YatLink.apiDevUrl : YatLink.apiReleaseUrl;
35
36 static String get emojiIdUrl => apiUrl + '/emoji_id/';
37
37 - static String get baseUrl => YatLink.isDevMode
38 - ? YatLink.baseDevUrl
39 - : YatLink.baseReleaseUrl;
38 + static String get baseUrl => YatLink.isDevMode ? YatLink.baseDevUrl : YatLink.baseReleaseUrl;
39 }
40
41 Future<List<String>> fetchYatAddress(String emojiId, String ticker) async {
42 throw Exception();
43 //final url = YatLink.emojiIdUrl + emojiId + '/payment';
44 //final response = await get(url);
46 -
45 +
46 //if (response.statusCode != 200) {
47 // throw YatException(text: response.body.toString());
48 //}
50 -
49 +
50 //final addresses = <String>[];
51 //final currency = ticker.toUpperCase();
52 //final responseJSON = json.decode(response.body) as Map<String, dynamic>;
@@ -55,7 +54,7 @@ Future<List<String>> fetchYatAddress(String emojiId, String ticker) async {
54 //result.forEach((dynamic key, dynamic value) {
55 // final tag = key as String ?? '';
56 // final record = value as Map<String, dynamic>;
58 -
57 +
58 // if (YatLink.tags[currency]?.contains(tag) ?? false) {
59 // final address = record['address'] as String;
60 // if (address?.isNotEmpty ?? false) {
@@ -80,11 +79,11 @@ Future<String> fetchYatAccessToken(String refreshToken) async {
79 // 'Accept': '*/*'
80 // },
81 // body: bodyJson);
83 -
82 +
83 // if (response.statusCode != 200) {
84 // throw YatException(text: response.body.toString());
85 // }
87 -
86 +
87 // final responseJSON = json.decode(response.body) as Map<String, dynamic>;
88 // return responseJSON['access_token'] as String;
89 //}catch(_) {
@@ -110,7 +109,7 @@ Future<String> fetchYatApiKey(String accessKey) async {
109 // if (response.statusCode != 200) {
110 // throw YatException(text: response.body.toString());
111 // }
113 -
112 +
113 // final responseJSON = json.decode(response.body) as Map<String, dynamic>;
114 // return responseJSON['api_key'] as String;
115 //}catch(_) {
@@ -119,7 +118,8 @@ Future<String> fetchYatApiKey(String accessKey) async {
118 return '';
119 }
120
122 -Future<void> updateEmojiIdAddress(String emojiId, String address, String apiKey, WalletType type) async {
121 +Future<void> updateEmojiIdAddress(
122 + String emojiId, String address, String apiKey, WalletType type) async {
123 throw Exception();
124 //final url = YatLink.emojiIdUrl + emojiId;
125 //final cur = walletTypeToCryptoCurrency(type);
@@ -166,15 +166,13 @@ Future<String> visualisationForEmojiId(String emojiId) async {
166 class YatStore = YatStoreBase with _$YatStore;
167
168 abstract class YatStoreBase with Store {
169 - YatStoreBase({
170 - required this.appStore,
171 - required this.secureStorage})
172 - : _wallet = appStore.wallet,
173 - emoji = appStore.wallet?.walletInfo?.yatEmojiId ?? '',
174 - refreshToken = '',
175 - accessToken = '',
176 - apiKey = '',
177 - emojiIncommingSC = StreamController<String>.broadcast() {
169 + YatStoreBase({required this.appStore, required this.secureStorage})
170 + : _wallet = appStore.wallet,
171 + emoji = appStore.wallet?.walletInfo?.yatEmojiId ?? '',
172 + refreshToken = '',
173 + accessToken = '',
174 + apiKey = '',
175 + emojiIncommingSC = StreamController<String>.broadcast() {
176 //reaction((_) => appStore.wallet, _onWalletChange);
177 //reaction((_) => emoji, (String _) => _onEmojiChange());
178 //reaction((_) => refreshToken, (String _) => _onRefreshTokenChange());
@@ -209,24 +207,22 @@ abstract class YatStoreBase with Store {
207 Stream<String> get emojiIncommingStream => emojiIncommingSC.stream;
208
209 @observable
212 - WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>?
213 - _wallet;
210 + WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo>? _wallet;
211
212 Future<void> init() async {
213 if (_wallet == null) {
214 return;
215 }
216
220 - refreshToken = await secureStorage.read(key: yatRefreshTokenKey(_wallet!.walletInfo.name)) ?? '';
217 + refreshToken =
218 + await secureStorage.read(key: yatRefreshTokenKey(_wallet!.walletInfo.name)) ?? '';
219 accessToken = await secureStorage.read(key: yatAccessTokenKey(_wallet!.walletInfo.name)) ?? '';
220 apiKey = await secureStorage.read(key: yatApiKey(_wallet!.walletInfo.name)) ?? '';
221 }
224 -
222 +
223 @action
224 void _onWalletChange(
227 - WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
228 - TransactionInfo>
229 - wallet) {
225 + WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet) {
226 this._wallet = wallet;
227 emoji = wallet?.walletInfo?.yatEmojiId ?? '';
228 init();
@@ -252,7 +248,7 @@ abstract class YatStoreBase with Store {
248 @action
249 Future<void> _onRefreshTokenChange() async {
250 throw Exception();
255 -
251 +
252 //try {
253 // await secureStorage.write(key: yatRefreshTokenKey(_wallet.walletInfo.name), value: refreshToken);
254 // accessToken = await fetchYatAccessToken(refreshToken);
@@ -269,7 +265,7 @@ abstract class YatStoreBase with Store {
265 //final result = <String, String>{};
266 //final tags = YatLink.tags[_wallet.currency.toString().toUpperCase()];
267 //String tag = tags.first;
272 -
268 +
269 //if (_wallet.type == WalletType.monero
270 // && _wallet.walletAddresses.address.startsWith('4')) {
271 // tag = tags.last;
@@ -277,7 +273,7 @@ abstract class YatStoreBase with Store {
273 //result[tag] = '${_wallet.walletAddresses.address}|${_wallet.name}';
274 //final addressJson = json.encode([result]);
275 //final addressJsonBytes = utf8.encode(addressJson);
280 -
276 +
277 //return base64.encode(addressJsonBytes);
278 return '';
279 }
lib/core/address_resolver/zano/zano_alias_address_provider.dart
-1
@@ -10,7 +10,6 @@ import 'package:cw_core/utils/proxy_wrapper.dart';
10 import 'package:cw_core/wallet_base.dart';
11
12 class ZanoAliasAddressProvider extends AddressLookupProvider {
13 -
13 @override
14 AddressSource get source => AddressSource.zanoAlias;
15
lib/core/address_resolver/zcash/zcash_names_record.dart
+1 -2
@@ -67,8 +67,7 @@ class ZcashNamesRecord {
67 }
68
69 static bool _isValidZcashAddress(String address) {
70 - final pattern =
71 - AddressValidator.getAddressFromStringPattern(CryptoCurrency.zec);
70 + final pattern = AddressValidator.getAddressFromStringPattern(CryptoCurrency.zec);
71 if (pattern == null) return false;
72 return RegExp('^(?:$pattern)\$').hasMatch(address);
73 }
lib/core/address_validator.dart
+28 -29
@@ -12,29 +12,29 @@ const AFTER_REGEX = '(\$|\\s)';
12 class AddressValidator extends TextValidator {
13 AddressValidator({required CryptoCurrency type, bool isTestnet = false})
14 : super(
15 - errorMessage: S.current.error_text_address,
16 - useAdditionalValidation: [CryptoCurrency.btc, CryptoCurrency.ltc].contains(type)
17 - ? (String txt) {
18 - final RegExp lightningInvoiceRegex = RegExp(
19 - r'^(lightning:)?(lnbc|lntb|lnbs|lnbcrt|lnurl)[a-z0-9]+$',
20 - caseSensitive: false);
21 - if (lightningInvoiceRegex.hasMatch(txt)) return true;
15 + errorMessage: S.current.error_text_address,
16 + useAdditionalValidation: [CryptoCurrency.btc, CryptoCurrency.ltc].contains(type)
17 + ? (String txt) {
18 + final RegExp lightningInvoiceRegex = RegExp(
19 + r'^(lightning:)?(lnbc|lntb|lnbs|lnbcrt|lnurl)[a-z0-9]+$',
20 + caseSensitive: false);
21 + if (lightningInvoiceRegex.hasMatch(txt)) return true;
22
23 - return BitcoinAddressUtils.validateAddress(
24 - address: txt,
25 - network: type == CryptoCurrency.btc
26 - ? isTestnet
27 - ? BitcoinNetwork.testnet
28 - : BitcoinNetwork.mainnet
29 - : LitecoinNetwork.mainnet,
30 - );
31 - }
32 - : type == CryptoCurrency.zano
33 - ? zano?.validateAddress
34 - : null,
35 - pattern: getPattern(type, isTestnet: isTestnet),
36 - length: getLength(type),
37 - );
23 + return BitcoinAddressUtils.validateAddress(
24 + address: txt,
25 + network: type == CryptoCurrency.btc
26 + ? isTestnet
27 + ? BitcoinNetwork.testnet
28 + : BitcoinNetwork.mainnet
29 + : LitecoinNetwork.mainnet,
30 + );
31 + }
32 + : type == CryptoCurrency.zano
33 + ? zano?.validateAddress
34 + : null,
35 + pattern: getPattern(type, isTestnet: isTestnet),
36 + length: getLength(type),
37 + );
38
39 static const List<CryptoCurrency> reliableValidateCurrencies = [
40 CryptoCurrency.xmr,
@@ -170,8 +170,7 @@ class AddressValidator extends TextValidator {
170 case CryptoCurrency.hbar:
171 pattern = '[0-9a-zA-Z.]+';
172 case CryptoCurrency.zec:
173 - pattern =
174 - '(?:'
173 + pattern = '(?:'
174 't1[0-9A-Za-z]{33}'
175 '|t3[0-9A-Za-z]{33}'
176 '|zs[a-z0-9]{76}'
@@ -195,7 +194,8 @@ class AddressValidator extends TextValidator {
194 case CryptoCurrency.pivx:
195 pattern = 'D([1-9a-km-zA-HJ-NP-Z]){33}';
196 case CryptoCurrency.btcln:
198 - pattern = r'(lightning:)?(lnbc|lntb|lnbs|lnbcrt|lnurl|LNBC|LNTB|LNBS|LNBCRT|LNURL)[a-zA-Z0-9]+';
197 + pattern =
198 + r'(lightning:)?(lnbc|lntb|lnbs|lnbcrt|lnurl|LNBC|LNTB|LNBS|LNBCRT|LNURL)[a-zA-Z0-9]+';
199 case CryptoCurrency.zano:
200 pattern = r'([1-9A-HJ-NP-Za-km-z]{90,200})|(@[\w\d.-]+)';
201 case CryptoCurrency.doge:
@@ -369,7 +369,7 @@ class AddressValidator extends TextValidator {
369 '|([0-9a-zA-Z]{106})';
370 case CryptoCurrency.btc:
371 pattern =
372 - '${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
372 + '${P2pkhAddress.regex.pattern}|${P2shAddress.regex.pattern}|${P2wpkhAddress.regex.pattern}|${P2trAddress.regex.pattern}|${P2wshAddress.regex.pattern}|${SilentPaymentAddress.regex.pattern}';
373 case CryptoCurrency.ltc:
374 pattern = '([^0-9a-zA-Z]|^)^L[a-zA-Z0-9]{26,33}([^0-9a-zA-Z]|\$)'
375 '|([^0-9a-zA-Z]|^)[LM][a-km-zA-HJ-NP-Z1-9]{26,33}([^0-9a-zA-Z]|\$)'
@@ -394,8 +394,7 @@ class AddressValidator extends TextValidator {
394 case CryptoCurrency.zano:
395 pattern = '([1-9A-HJ-NP-Za-km-z]{90,200})|(@[\w\d.-]+)';
396 case CryptoCurrency.zec:
397 - pattern =
398 - '(?:'
397 + pattern = '(?:'
398 't1[0-9A-Za-z]{33}'
399 '|t3[0-9A-Za-z]{33}'
400 '|zs[a-z0-9]{76}'
@@ -419,4 +418,4 @@ class AddressValidator extends TextValidator {
418
419 return pattern != null ? "($pattern)" : null;
420 }
422 -}
\ No newline at end of file
421 +}
lib/core/amount_validator.dart
+3 -3
@@ -12,9 +12,9 @@ class AmountValidator extends TextValidator {
12 String? minValue,
13 String? maxValue,
14 }) {
15 - symbolsAmountValidator =
16 - SymbolsAmountValidator(isAutovalidate: isAutovalidate);
17 - decimalAmountValidator = DecimalAmountValidator(currency: currency,isAutovalidate: isAutovalidate);
15 + symbolsAmountValidator = SymbolsAmountValidator(isAutovalidate: isAutovalidate);
16 + decimalAmountValidator =
17 + DecimalAmountValidator(currency: currency, isAutovalidate: isAutovalidate);
18
19 amountMinValidator = AmountMinValidator(
20 minValue: minValue,
lib/core/auth_state.dart
-1
@@ -17,4 +17,3 @@ class AuthenticationBanned extends AuthState {
17
18 final String error;
19 }
20 -
lib/core/backup_service.dart
+26 -21
@@ -25,8 +25,8 @@ import 'package:cake_wallet/wallet_types.g.dart';
25 import 'package:cake_backup/backup.dart' as cake_backup;
26
27 class $BackupService {
28 - $BackupService(this._secureStorage, this.transactionDescriptionBox,
29 - this.keyService, this.sharedPreferences)
28 + $BackupService(
29 + this._secureStorage, this.transactionDescriptionBox, this.keyService, this.sharedPreferences)
30 : cipher = Cryptography.instance.chacha20Poly1305Aead(),
31 correctWallets = <WalletInfo>[];
32
@@ -42,7 +42,6 @@ class $BackupService {
42 final KeyService keyService;
43 List<WalletInfo> correctWallets;
44
45 -
45 Future<void> importBackupV1(Uint8List data, String password, {required String nonce}) async {
46 final appDir = await getAppDir();
47 final decryptedData = await _decryptV1(data, password, nonce);
@@ -59,7 +58,8 @@ class $BackupService {
58 } else {
59 Directory('${appDir.path}/' + filename)..create(recursive: true);
60 }
62 - };
61 + }
62 + ;
63
64 await verifyWallets();
65 await _importKeychainDumpV1(password, nonce: nonce);
@@ -101,7 +101,8 @@ class $BackupService {
101 dir.createSync(recursive: true);
102 }
103 }
104 - };
104 + }
105 + ;
106
107 await verifyWallets();
108 await importKeychainDumpV2(password);
@@ -112,7 +113,9 @@ class $BackupService {
113 Future<void> verifyWallets() async {
114 await performHiveMigration(); // for backups made before sqlite migration
115 await performTradeHiveMigration(_secureStorage);
115 - correctWallets = (await WalletInfo.getAll()).where((info) => availableWalletTypes.contains(info.type)).toList();
116 + correctWallets = (await WalletInfo.getAll())
117 + .where((info) => availableWalletTypes.contains(info.type))
118 + .toList();
119
120 if (correctWallets.isEmpty) {
121 printV('Correct wallets not detected');
@@ -133,12 +136,11 @@ class $BackupService {
136 MapEntry(key, TransactionDescription.fromJson(value as Map<String, dynamic>)));
137 var box = transactionDescriptionBox;
138 if (!box.isOpen) {
136 - final transactionDescriptionsBoxKey =
137 - await getEncryptionKey(secureStorage: _secureStorage, forKey: TransactionDescription.boxKey);
138 - box = await CakeHive.openBox<TransactionDescription>(
139 - TransactionDescription.boxName,
140 - encryptionKey: transactionDescriptionsBoxKey);
141 - }
139 + final transactionDescriptionsBoxKey = await getEncryptionKey(
140 + secureStorage: _secureStorage, forKey: TransactionDescription.boxKey);
141 + box = await CakeHive.openBox<TransactionDescription>(TransactionDescription.boxName,
142 + encryptionKey: transactionDescriptionsBoxKey);
143 + }
144 await box.putAll(descriptionsMap);
145 }
146
@@ -152,7 +154,8 @@ class $BackupService {
154
155 final data = json.decode(preferencesFile.readAsStringSync()) as Map<String, dynamic>;
156
155 - try { // shouldn't throw an error but just in case, so it doesn't stop the backup restore
157 + try {
158 + // shouldn't throw an error but just in case, so it doesn't stop the backup restore
159 for (var entry in data.entries) {
160 String key = entry.key;
161 dynamic value = entry.value;
@@ -170,7 +173,8 @@ class $BackupService {
173 await sharedPreferences.setStringList(key, value);
174 } else {
175 if (kDebugMode) {
173 - printV('Skipping individual save for key "$key": Unsupported type (${value.runtimeType}). Value: $value');
176 + printV(
177 + 'Skipping individual save for key "$key": Unsupported type (${value.runtimeType}). Value: $value');
178 }
179 }
180 }
@@ -187,9 +191,7 @@ class $BackupService {
191 currentWalletName = correctWallets.first.name;
192 currentWalletType = serializeToInt(correctWallets.first.type);
193 }
190 - } catch (e) {
191 -
192 - }
194 + } catch (e) {}
195
196 if (DeviceInfo.instance.isDesktop) {
197 await sharedPreferences.setInt(PreferencesKey.currentTheme, ThemeList.darkTheme.raw);
@@ -247,8 +249,8 @@ class $BackupService {
249 for (var key in (keychainJSON['_all'] as Map<String, dynamic>).keys) {
250 try {
251 if (!key.startsWith('MONERO_WALLET_')) continue;
250 - final decodedPassword = decodeWalletPassword(
251 - password: keychainJSON['_all'][key].toString());
252 + final decodedPassword =
253 + decodeWalletPassword(password: keychainJSON['_all'][key].toString());
254 final walletName = key.split('_WALLET_')[1];
255 final walletType = key.split('_WALLET_')[0].toLowerCase();
256 await importWalletKeychainInfo({
@@ -294,8 +296,11 @@ class $BackupService {
296 }));
297 final backupPasswordKey = generateStoreKeyFor(key: SecretStoreKey.backupPassword);
298 final backupPassword = await _secureStorage.read(key: backupPasswordKey);
297 - final data = utf8.encode(
298 - json.encode({'wallets': wallets, backupPasswordKey: backupPassword, '_all': await _secureStorage.readAll()}));
299 + final data = utf8.encode(json.encode({
300 + 'wallets': wallets,
301 + backupPasswordKey: backupPassword,
302 + '_all': await _secureStorage.readAll()
303 + }));
304 final encrypted = await _encryptV2(Uint8List.fromList(data), '$keychainSalt$password');
305
306 return encrypted;
lib/core/backup_service_v3.dart
+33 -30
@@ -73,6 +73,7 @@ class ChunkLength {
73 'plain': plain,
74 };
75 }
76 +
77 @override
78 String toString() {
79 return 'ChunkLength(encrypted: $encrypted, plain: $plain)';
@@ -124,7 +125,9 @@ class BackupMetadata {
125 return BackupMetadata(
126 version: BackupVersion.values[json['version'] as int],
127 sha512sum: json['sha512sum'] as String,
127 - chunks: (json['chunks'] as List<dynamic>).map((chunk) => ChunkDetails.fromJson(chunk as Map<String, dynamic>)).toList(),
128 + chunks: (json['chunks'] as List<dynamic>)
129 + .map((chunk) => ChunkDetails.fromJson(chunk as Map<String, dynamic>))
130 + .toList(),
131 cakeVersion: json['cakeVersion'] as String,
132 );
133 }
@@ -160,7 +163,8 @@ class IncompatibleBackupAppException implements Exception {
163 }
164
165 class BackupServiceV3 extends $BackupService {
163 - BackupServiceV3(super.secureStorage, super.transactionDescriptionBox, super.keyService, super.sharedPreferences);
166 + BackupServiceV3(super.secureStorage, super.transactionDescriptionBox, super.keyService,
167 + super.sharedPreferences);
168
169 static BackupVersion get currentVersion => BackupVersion.v3;
170
@@ -170,12 +174,12 @@ class BackupServiceV3 extends $BackupService {
174
175 BackupVersion getVersionFile(File data) {
176 final raf = data.openSync(mode: FileMode.read);
173 -
177 +
178 try {
179 // Read first 4 bytes to check both version and zip signature
180 final buffer = Uint8List(1);
181 final bytesRead = raf.readIntoSync(buffer);
178 -
182 +
183 if (bytesRead == 0) {
184 throw Exception('Invalid backup file: empty file');
185 }
@@ -231,7 +235,7 @@ class BackupServiceV3 extends $BackupService {
235 }
236
237 Future<void> importBackupFileV3(File file, String password,
234 - {String nonce = secrets.backupSalt,bool checkBackupApp = true}) async{
238 + {String nonce = secrets.backupSalt, bool checkBackupApp = true}) async {
239 // Overall design of v3 backup is the following:
240 // 1. backup.zip - plaintext zip file that user can open with any archive manager
241 // 2. backup.zip/README.txt - text file to let user know what is inside of this file
@@ -259,14 +263,14 @@ class BackupServiceV3 extends $BackupService {
263 throw Exception('Invalid v3 backup: missing data.bin');
264 }
265 final dataStream = dataFile.rawContent!.getStream();
262 -
266 +
267 final decryptedData = File('${file.path}_decrypted'); // decrypted zip file
268 if (decryptedData.existsSync()) {
269 decryptedData.deleteSync();
270 }
271 decryptedData.createSync(recursive: true);
272 decryptedData.writeAsBytesSync(Uint8List(0), mode: FileMode.write, flush: true);
269 -
273 +
274 int chunkIndex = 0;
275 for (var chunk in metadata.chunks) {
276 chunkIndex++;
@@ -275,7 +279,8 @@ class BackupServiceV3 extends $BackupService {
279
280 // readBytes stores position internally, so we don't need to think about it.
281 if (chunk.sha512sum.encrypted != chunkChecksum) {
278 - throw Exception('Invalid v3 backup: chunk (${chunk.length.encrypted} bytes) checksum mismatch at index $chunkIndex\n'
282 + throw Exception(
283 + 'Invalid v3 backup: chunk (${chunk.length.encrypted} bytes) checksum mismatch at index $chunkIndex\n'
284 'expected: ${chunk.sha512sum.encrypted}\n'
285 'got: $chunkChecksum');
286 }
@@ -283,7 +288,6 @@ class BackupServiceV3 extends $BackupService {
288 decryptedData.writeAsBytesSync(decryptedChunk, mode: FileMode.append, flush: true);
289 }
290
286 -
291 final sha512sum = (await sha512.bind(decryptedData.openRead()).first).toString();
292 if (sha512sum.toString() != metadata.sha512sum) {
293 throw Exception('Invalid v3 backup: SHA512 checksum mismatch\n'
@@ -301,7 +305,6 @@ class BackupServiceV3 extends $BackupService {
305 final decryptedDataStream = InputFileStream(decryptedData.path);
306 final backupArchive = zip.decodeStream(decryptedDataStream);
307
304 -
308 final appDir = await getAppDir();
309
310 outer:
@@ -315,8 +318,7 @@ class BackupServiceV3 extends $BackupService {
318 }
319 printV("restoring: $filename");
320 if (file.isFile) {
318 - final output = File('${appDir.path}/' + filename)
319 - ..createSync(recursive: true);
321 + final output = File('${appDir.path}/' + filename)..createSync(recursive: true);
322 final outputStream = OutputFileStream(output.path);
323 file.writeContent(outputStream);
324 outputStream.flush();
@@ -326,7 +328,8 @@ class BackupServiceV3 extends $BackupService {
328 dir.createSync(recursive: true);
329 }
330 }
329 - };
331 + }
332 + ;
333
334 // Continue importing the backup the old way
335 await super.verifyWallets();
@@ -344,10 +347,10 @@ class BackupServiceV3 extends $BackupService {
347 {String keychainSalt = secrets.backupKeychainSalt}) async {
348 final appDir = await getAppDir();
349 final keychainDumpFile = File('${appDir.path}/~_keychain_dump');
347 - final decryptedKeychainDumpFileData = await decryptV2(
348 - keychainDumpFile.readAsBytesSync(), '$keychainSalt$password');
349 - final keychainJSON = json.decode(utf8.decode(decryptedKeychainDumpFileData))
350 - as Map<String, dynamic>;
350 + final decryptedKeychainDumpFileData =
351 + await decryptV2(keychainDumpFile.readAsBytesSync(), '$keychainSalt$password');
352 + final keychainJSON =
353 + json.decode(utf8.decode(decryptedKeychainDumpFileData)) as Map<String, dynamic>;
354 final keychainWalletsInfo = keychainJSON['wallets'] as List;
355
356 final expectedHardwareWallets = keychainWalletsInfo
@@ -358,10 +361,10 @@ class BackupServiceV3 extends $BackupService {
361
362 for (final expectedHardwareWallet in expectedHardwareWallets) {
363 final info = expectedHardwareWallet as Map<String, dynamic>;
361 - final actualWalletInfo = await WalletInfo.get(info['name'] as String, WalletType.values.firstWhere((e) => e.toString() == info['type'] as String));
364 + final actualWalletInfo = await WalletInfo.get(info['name'] as String,
365 + WalletType.values.firstWhere((e) => e.toString() == info['type'] as String));
366 if (actualWalletInfo != null &&
363 - info["hardwareWalletType"] !=
364 - actualWalletInfo.hardwareWalletType?.index) {
367 + info["hardwareWalletType"] != actualWalletInfo.hardwareWalletType?.index) {
368 actualWalletInfo.hardwareWalletType =
369 HardwareWalletType.values[info["hardwareWalletType"] as int];
370 await actualWalletInfo.save();
@@ -390,7 +393,8 @@ class BackupServiceV3 extends $BackupService {
393 final transactionDescriptionDumpFile =
394 File('${tmpDir.path}/~_transaction_descriptions_dump_TMP');
395
393 - final transactionDescriptionData = super.transactionDescriptionBox
396 + final transactionDescriptionData = super
397 + .transactionDescriptionBox
398 .toMap()
399 .map((key, value) => MapEntry(key.toString(), value.toJson()));
400 final transactionDescriptionDump = jsonEncode(transactionDescriptionData);
@@ -443,15 +447,14 @@ class BackupServiceV3 extends $BackupService {
447 int chunkIndex = 0;
448 final stopwatch = Stopwatch()..start();
449 printV("Starting backup encryption...");
446 -
450 +
451 metadata.sha512sum = (await sha512.bind(dataBinUnencrypted.openRead()).first).toString();
452
453 final raf = await dataBinUnencrypted.open();
454
451 -
455 while (true) {
456 printV("Reading chunk ${chunkIndex++}");
454 -
457 +
458 stopwatch.reset();
459 final chunk = await raf.read(chunkSize);
460 printV("Chunk read completed in ${stopwatch.elapsed}");
@@ -459,13 +462,14 @@ class BackupServiceV3 extends $BackupService {
462 if (chunk.length == 0) {
463 break;
464 }
462 -
465 +
466 stopwatch.reset();
467 final encryptedChunk = await cake_backup.encrypt(password, chunk);
468 printV("Encryption completed in ${stopwatch.elapsed}");
469
470 stopwatch.reset();
468 - final sha512sumEncryptedChunk = await sha512.bind(Stream.fromIterable([encryptedChunk])).first;
471 + final sha512sumEncryptedChunk =
472 + await sha512.bind(Stream.fromIterable([encryptedChunk])).first;
473 final sha512sumUnencryptedChunk = await sha512.bind(Stream.fromIterable([chunk])).first;
474 printV("Hashing completed in ${stopwatch.elapsed}");
475
@@ -481,7 +485,7 @@ class BackupServiceV3 extends $BackupService {
485 plain: chunk.length,
486 ),
487 ));
484 -
488 +
489 await dataBinWriter.flush();
490 printV("Writing completed in ${stopwatch.elapsed}");
491 }
@@ -495,7 +499,8 @@ class BackupServiceV3 extends $BackupService {
499
500 metadataFile.writeAsStringSync(JsonEncoder.withIndent(' ').convert(metadata.toJson()));
501 final readmeFile = File('${tmpDir.path}/README.txt');
498 - readmeFile.writeAsStringSync('''This is a ${packageInfo.appName} backup. Do not modify this archive.
502 + readmeFile
503 + .writeAsStringSync('''This is a ${packageInfo.appName} backup. Do not modify this archive.
504
505 App version: ${packageInfo.version}
506
@@ -524,11 +529,9 @@ This backup was created on ${DateTime.now().toIso8601String()}
529 final sourceAppName = _extractBackupAppName(readmeString);
530 if (sourceAppName == null) return;
531
527 -
532 final currentAppName = (await PackageInfo.fromPlatform()).appName;
533 if (sourceAppName == currentAppName) return;
534
531 -
535 throw IncompatibleBackupAppException(
536 sourceAppName: sourceAppName,
537 currentAppName: currentAppName,
lib/core/csv_export_service.dart
+4 -7
@@ -73,12 +73,8 @@ class CsvExportService {
73
74 // Prefer tx.to/tx.from; fall back to address lists for chains that don't populate them.
75 final address = tx.direction == TransactionDirection.incoming
76 - ? (tx.from?.isNotEmpty == true
77 - ? tx.from!
78 - : (tx.inputAddresses?.firstOrNull ?? ''))
79 - : (tx.to?.isNotEmpty == true
80 - ? tx.to!
81 - : (tx.outputAddresses?.firstOrNull ?? ''));
76 + ? (tx.from?.isNotEmpty == true ? tx.from! : (tx.inputAddresses?.firstOrNull ?? ''))
77 + : (tx.to?.isNotEmpty == true ? tx.to! : (tx.outputAddresses?.firstOrNull ?? ''));
78
79 final fee = tx.fee != null && !tx.fee!.isZero ? tx.fee.toString() : '';
80
@@ -213,7 +209,8 @@ class CsvExportService {
209 String _isoDate(DateTime dt) => dt.toUtc().toIso8601String();
210
211 Future<void> exportToCsv(List<ActionListItem> items, BuildContext context) async {
216 - final dataItems = items.whereType<ActionListItem>().where((e) => e is! DateSectionItem).toList();
212 + final dataItems =
213 + items.whereType<ActionListItem>().where((e) => e is! DateSectionItem).toList();
214
215 if (dataItems.isEmpty) {
216 await showBar<void>(context, S.current.csv_nothing_to_export);
lib/core/email_validator.dart
+1 -2
@@ -5,7 +5,6 @@ class EmailValidator extends TextValidator {
5 EmailValidator()
6 : super(
7 errorMessage: 'Invalid email address',
8 - pattern:
9 - '^[^@]+@[^@]+\.[^@]+',
8 + pattern: '^[^@]+@[^@]+\.[^@]+',
9 );
10 }
lib/core/execution_state.dart
+1 -1
@@ -25,4 +25,4 @@ class AwaitingConfirmationState extends ExecutionState {
25 final String? message;
26 final Function()? onConfirm;
27 final Function()? onCancel;
28 -}
\ No newline at end of file
28 +}
lib/core/fiat_conversion_service.dart
+6 -12
@@ -10,7 +10,6 @@ const _fiatApiOnionAuthority = '46wisoe2uwipcj2j4og6smiq7hbmj34fkkrquwlzbbsqtgat
10 const _fiatApiPath = '/v2/rates';
11
12 Future<double> _fetchPrice(String crypto, String fiat, bool torOnly) async {
13 -
13 final Map<String, String> queryParams = {
14 'interval_count': '1',
15 'base': crypto.split(".").first,
@@ -23,14 +22,10 @@ Future<double> _fetchPrice(String crypto, String fiat, bool torOnly) async {
22 final onionUri = Uri.http(_fiatApiOnionAuthority, _fiatApiPath, queryParams);
23 final clearnetUri = Uri.https(_fiatApiClearNetAuthority, _fiatApiPath, queryParams);
24
26 - final response = await ProxyWrapper().get(
27 - onionUri: onionUri,
28 - clearnetUri: torOnly ? onionUri : clearnetUri,
29 - headers: {
30 - "x-api-key": secrets.fiatApiKey,
31 - }
32 - );
33 -
25 + final response = await ProxyWrapper()
26 + .get(onionUri: onionUri, clearnetUri: torOnly ? onionUri : clearnetUri, headers: {
27 + "x-api-key": secrets.fiatApiKey,
28 + });
29
30 if (response.statusCode != 200) {
31 return 0.0;
@@ -52,9 +47,8 @@ Future<double> _fetchPrice(String crypto, String fiat, bool torOnly) async {
47 /// Override specific [CryptoCurrency] to fix its price to the price of another
48 /// e.g. nDEPS should have the same price as DEPS, but only DEPS is tracked
49 CryptoCurrency _overrideCryptoCurrency(CryptoCurrency crypto) {
55 - if (crypto.title == CryptoCurrency.ndeps.title)
56 - return CryptoCurrency.deps;
57 - return crypto;
50 + if (crypto.title == CryptoCurrency.ndeps.title) return CryptoCurrency.deps;
51 + return crypto;
52 }
53
54 class FiatConversionService {
lib/core/mnemonic_length.dart
+1 -1
@@ -14,4 +14,4 @@ int mnemonicLength(WalletType type) {
14 default:
15 return 0;
16 }
17 -}
\ No newline at end of file
17 +}
lib/core/monero_account_label_validator.dart
+4 -4
@@ -4,8 +4,8 @@ import 'package:cake_wallet/core/validator.dart';
4 class MoneroLabelValidator extends TextValidator {
5 MoneroLabelValidator()
6 : super(
7 - errorMessage: S.current.error_text_account_name,
8 - pattern: '^[a-zA-Z0-9_ ]{1,15}\$',
9 - minLength: 1,
10 - maxLength: 15);
7 + errorMessage: S.current.error_text_account_name,
8 + pattern: '^[a-zA-Z0-9_ ]{1,15}\$',
9 + minLength: 1,
10 + maxLength: 15);
11 }
lib/core/open_crypto_pay/open_cryptopay_service.dart
+8 -14
@@ -9,8 +9,7 @@ import 'package:cw_core/utils/proxy_wrapper.dart';
9
10 class OpenCryptoPayService {
11 static bool isOpenCryptoPayQR(String value) =>
12 - value.toLowerCase().contains("lightning=lnurl") ||
13 - value.toLowerCase().startsWith("lnurl");
12 + value.toLowerCase().contains("lightning=lnurl") || value.toLowerCase().startsWith("lnurl");
13
14 static bool requiresClientCommit(CryptoCurrency currency) =>
15 [CryptoCurrency.xmr, CryptoCurrency.zano, CryptoCurrency.sol].contains(currency) ||
@@ -71,8 +70,8 @@ class OpenCryptoPayService {
70 );
71 }
72
74 - Future<(_OpenCryptoPayQuote, Map<String, List<OpenCryptoPayQuoteAsset>>)>
75 - _getOpenCryptoPayParams(Uri uri) async {
73 + Future<(_OpenCryptoPayQuote, Map<String, List<OpenCryptoPayQuoteAsset>>)> _getOpenCryptoPayParams(
74 + Uri uri) async {
75 final response = await ProxyWrapper().get(clearnetUri: uri);
76
77 if (response.statusCode == 200) {
@@ -90,18 +89,15 @@ class OpenCryptoPayService {
89 final method = transferAmount['method'] as String;
90 methods[method] = [];
91 for (final assetJson in transferAmount['assets'] as List) {
93 - final asset = OpenCryptoPayQuoteAsset.fromJson(
94 - assetJson as Map<String, dynamic>);
92 + final asset = OpenCryptoPayQuoteAsset.fromJson(assetJson as Map<String, dynamic>);
93 methods[method]?.add(asset);
94 }
95 }
96
97 log(responseBody.toString());
98
101 - final quote = _OpenCryptoPayQuote.fromJson(
102 - responseBody['callback'] as String,
103 - responseBody['displayName'] as String?,
104 - responseBody['quote'] as Map<String, dynamic>);
99 + final quote = _OpenCryptoPayQuote.fromJson(responseBody['callback'] as String,
100 + responseBody['displayName'] as String?, responseBody['quote'] as Map<String, dynamic>);
101
102 return (quote, methods);
103 } else {
@@ -110,8 +106,7 @@ class OpenCryptoPayService {
106 }
107 }
108
113 - Future<Uri> getOpenCryptoPayAddress(
114 - OpenCryptoPayRequest request, CryptoCurrency asset) async {
109 + Future<Uri> getOpenCryptoPayAddress(OpenCryptoPayRequest request, CryptoCurrency asset) async {
110 final uri = Uri.parse(request.callbackUrl);
111 final queryParams = Map.of(uri.queryParameters);
112
@@ -135,8 +130,7 @@ class OpenCryptoPayService {
130
131 if (result.queryParameters['amount'] != null) return result;
132
138 - final newQueryParameters =
139 - Map<String, dynamic>.from(result.queryParameters);
133 + final newQueryParameters = Map<String, dynamic>.from(result.queryParameters);
134
135 newQueryParameters['amount'] = _getAmountByAsset(request, asset);
136 return Uri(
lib/core/seed_validator.dart
+2 -3
@@ -22,8 +22,7 @@ class SeedValidator extends Validator<MnemonicItem> {
22 final String language;
23 final List<String> _words;
24
25 - static List<String> getWordList(
26 - {required WalletType type, required String language}) {
25 + static List<String> getWordList({required WalletType type, required String language}) {
26 switch (type) {
27 case WalletType.bitcoin:
28 return getBitcoinWordList(language);
@@ -49,7 +48,7 @@ class SeedValidator extends Validator<MnemonicItem> {
48 case WalletType.tron:
49 return tron!.getTronWordList(language);
50 case WalletType.wownero:
52 - return wownero!.getWowneroWordList(language);
51 + return wownero!.getWowneroWordList(language);
52 case WalletType.zano:
53 return zano!.getWordList(language);
54 case WalletType.decred:
lib/core/selectable_option.dart
-3
@@ -5,7 +5,6 @@ abstract class SelectableItem {
5
6 class OptionTitle extends SelectableItem {
7 OptionTitle({required String title}) : super(title: title);
8 -
8 }
9
10 abstract class SelectableOption extends SelectableItem {
@@ -43,5 +42,3 @@ abstract class SelectableOption extends SelectableItem {
42
43 set isOptionSelected(bool isSelected) => false;
44 }
46 -
47 -
lib/core/socks_proxy_node_address_validator.dart
+2 -3
@@ -4,7 +4,6 @@ import 'package:cake_wallet/generated/i18n.dart';
4 class SocksProxyNodeAddressValidator extends TextValidator {
5 SocksProxyNodeAddressValidator()
6 : super(
7 - errorMessage: S.current.error_text_node_proxy_address,
8 - pattern:
9 - '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]+\$');
7 + errorMessage: S.current.error_text_node_proxy_address,
8 + pattern: '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]+\$');
9 }
lib/core/template_validator.dart
+5 -6
@@ -4,9 +4,8 @@ import 'package:cake_wallet/generated/i18n.dart';
4 class TemplateValidator extends TextValidator {
5 TemplateValidator()
6 : super(
7 - minLength: 0,
8 - maxLength: 0,
9 - pattern: '''^[^`,'"]{1,20}\$''',
10 - errorMessage: S.current.error_text_template
11 - );
12 -}
\ No newline at end of file
7 + minLength: 0,
8 + maxLength: 0,
9 + pattern: '''^[^`,'"]{1,20}\$''',
10 + errorMessage: S.current.error_text_template);
11 +}
lib/core/universal_address_detector.dart
+1 -1
@@ -132,7 +132,7 @@ class UniversalAddressDetector {
132 pattern: RegExp(r'^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'),
133 currency: CryptoCurrency.btcln,
134 ),
135 -
135 +
136 // Lightning Address (LNURL format)
137 _DetectionPattern(
138 pattern: RegExp(r'^(lightning:)?(lnurl)[a-z0-9]+$', caseSensitive: false),
lib/core/utilities.dart
+1 -2
@@ -8,8 +8,7 @@ extension EnhancedList<T> on Iterable<T> {
8 }
9 }
10
11 -
11 String middleTruncate(String s, int head, int tail) {
12 if (s.length <= head + tail + 3) return s;
13 return s.substring(0, head) + '...' + s.substring(s.length - tail);
15 -}
\ No newline at end of file
14 +}
lib/core/validator.dart
+3 -7
@@ -18,9 +18,7 @@ class TextValidator extends Validator<String> {
18 String errorMessage = '',
19 this.length,
20 this.isAutovalidate = false,
21 - }) : super(
22 - errorMessage: errorMessage,
23 - useAdditionalValidation: useAdditionalValidation);
21 + }) : super(errorMessage: errorMessage, useAdditionalValidation: useAdditionalValidation);
22
23 final int? minLength;
24 final int? maxLength;
@@ -40,8 +38,7 @@ class TextValidator extends Validator<String> {
38 final lengthMatched = length?.contains(value.length) ?? true;
39 if (!lengthMatched) return false;
40
43 - final lowerThanMaxLength =
44 - (maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true;
41 + final lowerThanMaxLength = (maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true;
42 if (!lowerThanMaxLength) return false;
43
44 if (pattern == null) return true;
@@ -54,6 +51,5 @@ class TextValidator extends Validator<String> {
51 return valueValidated;
52 }
53
57 - bool match(String value) =>
58 - pattern != null ? RegExp(pattern!).hasMatch(value) : false;
54 + bool match(String value) => pattern != null ? RegExp(pattern!).hasMatch(value) : false;
55 }
lib/core/wallet_creation_service.dart
+2 -1
@@ -35,7 +35,8 @@ class WalletCreationService {
35
36 Future<bool> exists(String name) async {
37 final walletName = name.toLowerCase();
38 - return (await WalletInfo.getAll()).any((walletInfo) => walletInfo.name.toLowerCase() == walletName);
38 + return (await WalletInfo.getAll())
39 + .any((walletInfo) => walletInfo.name.toLowerCase() == walletName);
40 }
41
42 Future<bool> typeExists(WalletType type) async {
lib/core/wallet_creation_state.dart
+1 -1
@@ -10,4 +10,4 @@ class WalletCreationFailure extends WalletCreationState {
10 WalletCreationFailure({required this.error});
11
12 final String error;
13 -}
\ No newline at end of file
13 +}
lib/core/wallet_loading_service.dart
+43 -38
@@ -58,10 +58,12 @@ class WalletLoadingService {
58 }
59 }
60
61 - Future<WalletBase> load(WalletType type, String name, {String? password, bool isBackground = false}) async {
61 + Future<WalletBase> load(WalletType type, String name,
62 + {String? password, bool isBackground = false}) async {
63 try {
64 if (!isBackground) {
64 - await sharedPreferences.setString(PreferencesKey.backgroundSyncLastTrigger(name), DateTime.now().toIso8601String());
65 + await sharedPreferences.setString(
66 + PreferencesKey.backgroundSyncLastTrigger(name), DateTime.now().toIso8601String());
67 }
68 final walletService = walletServiceFactory.call(type);
69 final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name));
@@ -75,10 +77,14 @@ class WalletLoadingService {
77 } catch (error, stack) {
78 String corruptedWalletsSeeds = "Corrupted wallets seeds (if retrievable, empty otherwise):";
79
78 - if(error is WalletDeprecationException) {
79 - if(navigatorKey.currentContext != null) {
80 + if (error is WalletDeprecationException) {
81 + if (navigatorKey.currentContext != null) {
82 showModalBottomSheet(
81 - context: navigatorKey.currentContext!, builder: (context)=>WalletDeprecationPopup(type: type, seed: error.seed,));
83 + context: navigatorKey.currentContext!,
84 + builder: (context) => WalletDeprecationPopup(
85 + type: type,
86 + seed: error.seed,
87 + ));
88 }
89 } else {
90 await ExceptionHandler.resetLastPopupDate();
@@ -106,8 +112,7 @@ class WalletLoadingService {
112 await updateMoneroWalletPassword(wallet);
113 }
114
109 - await sharedPreferences.setString(
110 - PreferencesKey.currentWalletName, wallet.name);
115 + await sharedPreferences.setString(PreferencesKey.currentWalletName, wallet.name);
116 await sharedPreferences.setInt(
117 PreferencesKey.currentWalletType, serializeToInt(wallet.type));
118
@@ -130,22 +135,22 @@ class WalletLoadingService {
135 // if all user's wallets are corrupted throw exception
136 final msg = error.toString() + "\n" + corruptedWalletsSeeds;
137 if (navigatorKey.currentContext != null) {
133 - await showPopUp<void>(
134 - context: navigatorKey.currentContext!,
135 - builder: (BuildContext context) {
136 - return AlertWithTwoActions(
137 - alertTitle: "Corrupted seeds",
138 - alertContent: S.of(context).corrupted_seed_notice,
139 - leftButtonText: S.of(context).cancel,
140 - rightButtonText: S.of(context).show_seed,
141 - actionLeftButton: () {
142 - if (context.mounted && Navigator.of(context).canPop()) {
143 - Navigator.of(context).pop();
144 - }
145 - },
146 - actionRightButton: () => showSeedsPopup(context, msg),
147 - );
148 - });
138 + await showPopUp<void>(
139 + context: navigatorKey.currentContext!,
140 + builder: (BuildContext context) {
141 + return AlertWithTwoActions(
142 + alertTitle: "Corrupted seeds",
143 + alertContent: S.of(context).corrupted_seed_notice,
144 + leftButtonText: S.of(context).cancel,
145 + rightButtonText: S.of(context).show_seed,
146 + actionLeftButton: () {
147 + if (context.mounted && Navigator.of(context).canPop()) {
148 + Navigator.of(context).pop();
149 + }
150 + },
151 + actionRightButton: () => showSeedsPopup(context, msg),
152 + );
153 + });
154 } else {
155 throw msg;
156 }
@@ -159,21 +164,21 @@ class WalletLoadingService {
164 Future<void> showSeedsPopup(BuildContext context, String message) async {
165 Navigator.of(context).pop();
166 await showPopUp<void>(
162 - context: context,
163 - builder: (BuildContext context) {
164 - return AlertWithTwoActions(
165 - alertTitle: "Corrupted seeds",
166 - alertContent: message,
167 - leftButtonText: S.of(context).copy,
168 - rightButtonText: S.of(context).ok,
169 - actionLeftButton: () async {
170 - await Clipboard.setData(ClipboardData(text: message));
171 - },
172 - actionRightButton: () async {
173 - Navigator.of(context).pop();
174 - },
175 - );
176 - });
167 + context: context,
168 + builder: (BuildContext context) {
169 + return AlertWithTwoActions(
170 + alertTitle: "Corrupted seeds",
171 + alertContent: message,
172 + leftButtonText: S.of(context).copy,
173 + rightButtonText: S.of(context).ok,
174 + actionLeftButton: () async {
175 + await Clipboard.setData(ClipboardData(text: message));
176 + },
177 + actionRightButton: () async {
178 + Navigator.of(context).pop();
179 + },
180 + );
181 + });
182 }
183
184 Future<void> updateMoneroWalletPassword(WalletBase wallet) async {
lib/di.dart
+226 -248
@@ -379,7 +379,6 @@ Future<void> setup({
379 return;
380 }
381
382 -
382 getIt.registerSingleton(AuthenticationStore());
383 getIt.registerSingleton<WalletListStore>(WalletListStore());
384 // getIt.registerSingleton(NodeListStoreBase.instance);
@@ -390,13 +389,12 @@ Future<void> setup({
389 settingsStore: getIt.get<SettingsStore>(),
390 // nodeListStore: getIt.get<NodeListStore>(),
391 themeStore: getIt.get<ThemeStore>()));
393 - getIt.registerSingleton<TradesStore>(
394 - TradesStore(appStore: getIt.get<AppStore>()));
392 + getIt.registerSingleton<TradesStore>(TradesStore(appStore: getIt.get<AppStore>()));
393 getIt.registerSingleton<OrdersStore>(
394 OrdersStore(ordersSource: _ordersSource, settingsStore: getIt.get<SettingsStore>()));
395 getIt.registerSingleton<BridgeTransfersStore>(BridgeTransfersStore());
398 - getIt.registerFactory(() =>
399 - PayjoinTransactionsStore(payjoinSessionSource: _payjoinSessionSource));
396 + getIt
397 + .registerFactory(() => PayjoinTransactionsStore(payjoinSessionSource: _payjoinSessionSource));
398 getIt.registerSingleton<TradeFilterStore>(TradeFilterStore());
399 getIt.registerSingleton<OrderFilterStore>(OrderFilterStore());
400 getIt.registerSingleton<TransactionFilterStore>(TransactionFilterStore(getIt.get<AppStore>()));
@@ -411,15 +409,19 @@ Future<void> setup({
409 getIt.registerSingleton<SeedSettingsStore>(SeedSettingsStore());
410
411 getIt.registerFactoryParam<HardwareWalletViewModel, HardwareWalletType, void>((type, _) {
414 - switch(type) {
415 - case HardwareWalletType.bitbox: return getIt<BitboxViewModel>();
416 - case HardwareWalletType.ledger: return getIt<LedgerViewModel>();
417 - case HardwareWalletType.trezor: return getIt<TrezorConnectViewModel>();
412 + switch (type) {
413 + case HardwareWalletType.bitbox:
414 + return getIt<BitboxViewModel>();
415 + case HardwareWalletType.ledger:
416 + return getIt<LedgerViewModel>();
417 + case HardwareWalletType.trezor:
418 + return getIt<TrezorConnectViewModel>();
419 case HardwareWalletType.cupcake:
420 case HardwareWalletType.coldcard:
421 case HardwareWalletType.seedsigner:
422 case HardwareWalletType.keystone:
422 - throw Exception("This should not have happened, because airgapped Wallets don't need View Models");
423 + throw Exception(
424 + "This should not have happened, because airgapped Wallets don't need View Models");
425 }
426 });
427
@@ -427,20 +429,19 @@ Future<void> setup({
429
430 getIt.registerLazySingleton(() => BitboxViewModel());
431
430 - getIt.registerLazySingleton(() => TrezorConnect("cakewallet://trezor_connect",
431 - appName: "Cake Wallet"));
432 + getIt.registerLazySingleton(
433 + () => TrezorConnect("cakewallet://trezor_connect", appName: "Cake Wallet"));
434 getIt.registerLazySingleton(() => TrezorConnectViewModel(getIt<TrezorConnect>()));
435
434 -
436 getIt.registerFactory<KeyService>(() => KeyService(getIt.get<SecureStorage>()));
437
437 - getIt.registerFactoryParam<WalletCreationService, WalletType, void>((type, _) =>
438 - WalletCreationService(
439 - initialType: type,
440 - keyService: getIt.get<KeyService>(),
441 - sharedPreferences: getIt.get<SharedPreferences>(),
442 - settingsStore: getIt.get<SettingsStore>(),
443 - ));
438 + getIt.registerFactoryParam<WalletCreationService, WalletType, void>(
439 + (type, _) => WalletCreationService(
440 + initialType: type,
441 + keyService: getIt.get<KeyService>(),
442 + sharedPreferences: getIt.get<SharedPreferences>(),
443 + settingsStore: getIt.get<SettingsStore>(),
444 + ));
445
446 getIt.registerFactoryParam<AdvancedPrivacySettingsViewModel, WalletType, void>(
447 (type, _) => AdvancedPrivacySettingsViewModel(type, getIt.get<SettingsStore>()));
@@ -451,14 +452,13 @@ Future<void> setup({
452 (WalletType type) => getIt.get<WalletService>(param1: type)));
453
454 getIt.registerFactoryParam<WalletNewVM, NewWalletArguments, void>(
454 - (newWalletArgs, _) => WalletNewVM(
455 - getIt.get<AppStore>(),
456 - getIt.get<WalletCreationService>(param1:newWalletArgs.type),
457 - getIt.get<AdvancedPrivacySettingsViewModel>(param1: newWalletArgs.type),
458 - getIt.get<SeedSettingsViewModel>(),
459 - newWalletArguments: newWalletArgs,
460 - ));
461 -
455 + (newWalletArgs, _) => WalletNewVM(
456 + getIt.get<AppStore>(),
457 + getIt.get<WalletCreationService>(param1: newWalletArgs.type),
458 + getIt.get<AdvancedPrivacySettingsViewModel>(param1: newWalletArgs.type),
459 + getIt.get<SeedSettingsViewModel>(),
460 + newWalletArguments: newWalletArgs,
461 + ));
462
463 final walletList = await WalletInfo.getAll();
464
@@ -479,62 +479,52 @@ Future<void> setup({
479 );
480
481 getIt.registerFactoryParam<WalletUnlockPage, WalletUnlockArguments, bool>((args, closable) {
482 - return WalletUnlockPage(
483 - getIt.get<WalletUnlockLoadableViewModel>(param1: args),
484 - args.callback,
485 - args.authPasswordHandler,
486 - closable: closable);
482 + return WalletUnlockPage(getIt.get<WalletUnlockLoadableViewModel>(param1: args), args.callback,
483 + args.authPasswordHandler,
484 + closable: closable);
485 }, instanceName: 'wallet_unlock_loadable');
486
487 getIt.registerFactory<WalletUnlockPage>(
490 - () => getIt.get<WalletUnlockPage>(
491 - param1: WalletUnlockArguments(
492 - callback: (bool successful, _) {
493 - if (successful) {
494 - final authStore = getIt.get<AuthenticationStore>();
495 - authStore.allowed();
496 - }}),
497 - param2: false,
498 - instanceName: 'wallet_unlock_loadable'),
499 - instanceName: 'wallet_password_login');
488 + () => getIt.get<WalletUnlockPage>(
489 + param1: WalletUnlockArguments(callback: (bool successful, _) {
490 + if (successful) {
491 + final authStore = getIt.get<AuthenticationStore>();
492 + authStore.allowed();
493 + }
494 + }),
495 + param2: false,
496 + instanceName: 'wallet_unlock_loadable'),
497 + instanceName: 'wallet_password_login');
498
499 getIt.registerFactoryParam<WalletUnlockPage, WalletUnlockArguments, bool>((args, closable) {
502 - return WalletUnlockPage(
503 - getIt.get<WalletUnlockVerifiableViewModel>(param1: args),
504 - args.callback,
505 - args.authPasswordHandler,
506 - closable: closable);
500 + return WalletUnlockPage(getIt.get<WalletUnlockVerifiableViewModel>(param1: args), args.callback,
501 + args.authPasswordHandler,
502 + closable: closable);
503 }, instanceName: 'wallet_unlock_verifiable');
504
505 getIt.registerFactoryParam<WalletUnlockLoadableViewModel, WalletUnlockArguments, void>((args, _) {
510 - final currentWalletName = getIt
511 - .get<SharedPreferences>()
512 - .getString(PreferencesKey.currentWalletName) ?? '';
506 + final currentWalletName =
507 + getIt.get<SharedPreferences>().getString(PreferencesKey.currentWalletName) ?? '';
508 final currentWalletTypeRaw =
514 - getIt.get<SharedPreferences>()
515 - .getInt(PreferencesKey.currentWalletType) ?? 0;
509 + getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType) ?? 0;
510 final currentWalletType = deserializeFromInt(currentWalletTypeRaw);
511
518 - return WalletUnlockLoadableViewModel(
519 - getIt.get<AppStore>(),
520 - getIt.get<WalletLoadingService>(),
521 - walletName: args.walletName ?? currentWalletName,
522 - walletType: args.walletType ?? currentWalletType);
512 + return WalletUnlockLoadableViewModel(getIt.get<AppStore>(), getIt.get<WalletLoadingService>(),
513 + walletName: args.walletName ?? currentWalletName,
514 + walletType: args.walletType ?? currentWalletType);
515 });
516
525 - getIt.registerFactoryParam<WalletUnlockVerifiableViewModel, WalletUnlockArguments, void>((args, _) {
526 - final currentWalletName = getIt
527 - .get<SharedPreferences>()
528 - .getString(PreferencesKey.currentWalletName) ?? '';
517 + getIt.registerFactoryParam<WalletUnlockVerifiableViewModel, WalletUnlockArguments, void>(
518 + (args, _) {
519 + final currentWalletName =
520 + getIt.get<SharedPreferences>().getString(PreferencesKey.currentWalletName) ?? '';
521 final currentWalletTypeRaw =
530 - getIt.get<SharedPreferences>()
531 - .getInt(PreferencesKey.currentWalletType) ?? 0;
522 + getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType) ?? 0;
523 final currentWalletType = deserializeFromInt(currentWalletTypeRaw);
524
534 - return WalletUnlockVerifiableViewModel(
535 - getIt.get<AppStore>(),
536 - walletName: args.walletName ?? currentWalletName,
537 - walletType: args.walletType ?? currentWalletType);
525 + return WalletUnlockVerifiableViewModel(getIt.get<AppStore>(),
526 + walletName: args.walletName ?? currentWalletName,
527 + walletType: args.walletType ?? currentWalletType);
528 });
529
530 getIt.registerFactoryParam<WalletHardwareRestoreViewModel, WalletType, HardwareWalletViewModel>(
@@ -577,29 +567,30 @@ Future<void> setup({
567 );
568
569 getIt.registerFactory(() => DashboardViewModel(
580 - tradeMonitor: getIt.get<TradeMonitor>(),
581 - balanceViewModel: getIt.get<BalanceViewModel>(),
582 - appStore: getIt.get<AppStore>(),
583 - tradesStore: getIt.get<TradesStore>(),
584 - ordersStore: getIt.get<OrdersStore>(),
585 - tradeFilterStore: getIt.get<TradeFilterStore>(),
586 - orderFilterStore: getIt.get<OrderFilterStore>(),
587 - transactionFilterStore: getIt.get<TransactionFilterStore>(),
588 - settingsStore: settingsStore,
589 - yatStore: getIt.get<YatStore>(),
590 - anonpayTransactionsStore: getIt.get<AnonpayTransactionsStore>(),
591 - payjoinTransactionsStore: getIt.get<PayjoinTransactionsStore>(),
592 - sharedPreferences: getIt.get<SharedPreferences>(),
593 - keyService: getIt.get<KeyService>()));
570 + tradeMonitor: getIt.get<TradeMonitor>(),
571 + balanceViewModel: getIt.get<BalanceViewModel>(),
572 + appStore: getIt.get<AppStore>(),
573 + tradesStore: getIt.get<TradesStore>(),
574 + ordersStore: getIt.get<OrdersStore>(),
575 + tradeFilterStore: getIt.get<TradeFilterStore>(),
576 + orderFilterStore: getIt.get<OrderFilterStore>(),
577 + transactionFilterStore: getIt.get<TransactionFilterStore>(),
578 + settingsStore: settingsStore,
579 + yatStore: getIt.get<YatStore>(),
580 + anonpayTransactionsStore: getIt.get<AnonpayTransactionsStore>(),
581 + payjoinTransactionsStore: getIt.get<PayjoinTransactionsStore>(),
582 + sharedPreferences: getIt.get<SharedPreferences>(),
583 + keyService: getIt.get<KeyService>()));
584
585 getIt.registerFactoryParam<CardCustomizerBloc, bool, BitcoinAmountDisplayMode?>(
586 (lightningMode, displayMode) {
597 - final wallet = getIt.get<AppStore>().wallet!;
598 - return CardCustomizerBloc(wallet,
599 - lightningMode: lightningMode,
600 - displaySats: wallet.type == WalletType.bitcoin && (displayMode == BitcoinAmountDisplayMode.satoshi ||
601 - (displayMode == BitcoinAmountDisplayMode.satoshiForLightning && lightningMode)));
602 - });
587 + final wallet = getIt.get<AppStore>().wallet!;
588 + return CardCustomizerBloc(wallet,
589 + lightningMode: lightningMode,
590 + displaySats: wallet.type == WalletType.bitcoin &&
591 + (displayMode == BitcoinAmountDisplayMode.satoshi ||
592 + (displayMode == BitcoinAmountDisplayMode.satoshiForLightning && lightningMode)));
593 + });
594
595 getIt.registerFactory<AccountCreationModal>(() => AccountCreationModal(
596 accountEditOrCreateViewModel: getIt.get<MoneroAccountEditOrCreateViewModel>()));
@@ -608,7 +599,7 @@ Future<void> setup({
599 () => LightningUsernameBloc(getIt.get<AppStore>().wallet!));
600
601 getIt.registerFactory<AuthService>(
611 - () => AuthService(
602 + () => AuthService(
603 secureStorage: getIt.get<SecureStorage>(),
604 sharedPreferences: getIt.get<SharedPreferences>(),
605 settingsStore: getIt.get<SettingsStore>(),
@@ -781,11 +772,14 @@ Future<void> setup({
772 ));
773
774 getIt.registerFactory<NewDashboard>(() => NewDashboard(
784 - dashboardViewModel: getIt.get<DashboardViewModel>(),
785 - bottomSheetService: getIt.get<BottomSheetService>(),
786 - ));
775 + dashboardViewModel: getIt.get<DashboardViewModel>(),
776 + bottomSheetService: getIt.get<BottomSheetService>(),
777 + ));
778
788 - getIt.registerFactory<NewHomePage>(()=>NewHomePage(dashboardViewModel: getIt.get<DashboardViewModel>(),nftViewModel: getIt.get<NFTViewModel>(),));
779 + getIt.registerFactory<NewHomePage>(() => NewHomePage(
780 + dashboardViewModel: getIt.get<DashboardViewModel>(),
781 + nftViewModel: getIt.get<NFTViewModel>(),
782 + ));
783
784 getIt.registerFactory<DesktopSidebarWrapper>(() {
785 final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();
@@ -878,9 +872,8 @@ Future<void> setup({
872 walletAddressEditOrCreateViewModel:
873 getIt.get<WalletAddressEditOrCreateViewModel>(param1: item)));
874
881 - getIt.registerFactoryParam<AddressInfoPopup, dynamic, void>((dynamic item, _) =>
882 - AddressInfoPopup(
883 - walletAddressEditOrCreateViewModel:
875 + getIt.registerFactoryParam<AddressInfoPopup, dynamic, void>((dynamic item, _) => AddressInfoPopup(
876 + walletAddressEditOrCreateViewModel:
877 getIt.get<WalletAddressEditOrCreateViewModel>(param1: item)));
878
879 getIt.registerFactoryParam<ReceiveLabelModal, dynamic, void>((dynamic item, _) =>
@@ -896,21 +889,20 @@ Future<void> setup({
889
890 getIt.registerFactoryParam<SendViewModel, UnspentCoinType?, void>(
891 (coinTypeToSpendFrom, _) => SendViewModel(
899 - getIt.get<AppStore>(),
900 - getIt.get<SendTemplateViewModel>(),
901 - getIt.get<FiatConversionStore>(),
902 - getIt.get<AddressResolverService>(),
903 - getIt.get<BalanceViewModel>(),
904 - getIt.get<ContactListViewModel>(),
905 - _transactionDescriptionBox,
906 - getIt.get<AppStore>().wallet!.isHardwareWallet
907 - ? getIt<HardwareWalletViewModel>(
908 - param1: getIt.get<AppStore>().wallet!.hardwareWalletType!)
909 - : null,
910 - coinTypeToSpendFrom: coinTypeToSpendFrom ?? UnspentCoinType.nonMweb,
911 - getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom),
912 - getIt.get<FeesViewModel>()
913 - ),
892 + getIt.get<AppStore>(),
893 + getIt.get<SendTemplateViewModel>(),
894 + getIt.get<FiatConversionStore>(),
895 + getIt.get<AddressResolverService>(),
896 + getIt.get<BalanceViewModel>(),
897 + getIt.get<ContactListViewModel>(),
898 + _transactionDescriptionBox,
899 + getIt.get<AppStore>().wallet!.isHardwareWallet
900 + ? getIt<HardwareWalletViewModel>(
901 + param1: getIt.get<AppStore>().wallet!.hardwareWalletType!)
902 + : null,
903 + coinTypeToSpendFrom: coinTypeToSpendFrom ?? UnspentCoinType.nonMweb,
904 + getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom),
905 + getIt.get<FeesViewModel>()),
906 );
907
908 getIt.registerFactoryParam<SendPage, PaymentRequest?, UnspentCoinType?>(
@@ -973,7 +965,6 @@ Future<void> setup({
965 );
966
967 getIt.registerFactoryParam<WalletEditPage, WalletEditPageArguments, void>((arguments, _) {
976 -
968 return WalletEditPage(
969 pageArguments: WalletEditPageArguments(
970 walletEditViewModel: getIt.get<WalletEditViewModel>(param1: arguments.walletListViewModel),
@@ -1003,7 +994,7 @@ Future<void> setup({
994 if (wallet.type == WalletType.monero ||
995 wallet.type == WalletType.wownero ||
996 wallet.type == WalletType.haven) {
1006 - return MoneroAccountListViewModel(wallet,getIt.get<SettingsStore>());
997 + return MoneroAccountListViewModel(wallet, getIt.get<SettingsStore>());
998 }
999 throw Exception(
1000 'Unexpected wallet type: ${wallet.type} for generate Monero AccountListViewModel');
@@ -1054,8 +1045,8 @@ Future<void> setup({
1045 nanoAccountCreationViewModel:
1046 getIt.get<NanoAccountEditOrCreateViewModel>(param1: account)));
1047
1057 - getIt.registerFactory(() =>
1058 - DisplaySettingsViewModel(getIt.get<AppStore>(), getIt.get<ThemeStore>()));
1048 + getIt.registerFactory(
1049 + () => DisplaySettingsViewModel(getIt.get<AppStore>(), getIt.get<ThemeStore>()));
1050
1051 getIt.registerFactory(() =>
1052 SilentPaymentsSettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!));
@@ -1063,24 +1054,24 @@ Future<void> setup({
1054 getIt.registerFactory(
1055 () => MwebSettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!));
1056
1066 - getIt.registerFactory(() =>
1067 - PrivacySettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!));
1057 + getIt.registerFactory(
1058 + () => PrivacySettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!));
1059
1060 getIt.registerFactory(() => TrocadorExchangeProvider());
1061
1062 getIt.registerFactory(() => TrocadorProvidersViewModel(
1063 getIt.get<SettingsStore>(), getIt.get<TrocadorExchangeProvider>()));
1064
1074 - getIt.registerFactory(() =>
1075 - OtherSettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!,
1076 - getIt.get<SendViewModel>()));
1065 + getIt.registerFactory(() => OtherSettingsViewModel(
1066 + getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!, getIt.get<SendViewModel>()));
1067
1078 - getIt.registerFactory(() =>
1079 - SecuritySettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AuthService>()));
1068 + getIt.registerFactory(
1069 + () => SecuritySettingsViewModel(getIt.get<SettingsStore>(), getIt.get<AuthService>()));
1070
1071 getIt.registerFactory(() => WalletSeedViewModel(getIt.get<AppStore>().wallet!));
1072
1083 - getIt.registerFactory<SeedSettingsViewModel>(() => SeedSettingsViewModel(getIt.get<AppStore>(), getIt.get<SeedSettingsStore>()));
1073 + getIt.registerFactory<SeedSettingsViewModel>(
1074 + () => SeedSettingsViewModel(getIt.get<AppStore>(), getIt.get<SeedSettingsStore>()));
1075
1076 getIt.registerFactory(() => DevMoneroBackgroundSync(getIt.get<AppStore>().wallet!));
1077
@@ -1097,13 +1088,11 @@ Future<void> setup({
1088
1089 getIt.registerFactory(() => AnimatedURModel(getIt.get<AppStore>()));
1090
1100 - getIt.registerFactoryParam<AnimatedURPage, Map<String, String>, void>((Map<String, String> urQr, _) =>
1101 - AnimatedURPage(getIt.get<AnimatedURModel>(), urQr: urQr));
1091 + getIt.registerFactoryParam<AnimatedURPage, Map<String, String>, void>(
1092 + (Map<String, String> urQr, _) => AnimatedURPage(getIt.get<AnimatedURModel>(), urQr: urQr));
1093
1103 - getIt.registerFactoryParam<ContactViewModel, ContactRecord?, void>(
1104 - (ContactRecord? contact, _) => ContactViewModel(_contactSource,
1105 - getIt.get<AppStore>(),
1106 - getIt.get<AddressResolverService>(),
1094 + getIt.registerFactoryParam<ContactViewModel, ContactRecord?, void>((ContactRecord? contact, _) =>
1095 + ContactViewModel(_contactSource, getIt.get<AppStore>(), getIt.get<AddressResolverService>(),
1096 contact: contact));
1097
1098 getIt.registerFactoryParam<ContactListViewModel, CryptoCurrency?, void>(
@@ -1128,14 +1117,15 @@ Future<void> setup({
1117 });
1118
1119 getIt.registerFactoryParam<NewAddressesPage, bool, void>(
1131 - (showHidden, _) => NewAddressesPage(
1120 + (showHidden, _) => NewAddressesPage(
1121 showHidden: showHidden,
1122 addressListViewModel: getIt<WalletAddressListViewModel>(),
1123 dashboardViewModel: getIt<DashboardViewModel>(),
1124 ),
1125 );
1126
1138 - getIt.registerFactory(() => ConnectionSyncViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!));
1127 + getIt.registerFactory(
1128 + () => ConnectionSyncViewModel(getIt.get<SettingsStore>(), getIt.get<AppStore>().wallet!));
1129
1130 getIt.registerFactory(() => ConnectionSyncPage(getIt.get<ConnectionSyncViewModel>()));
1131
@@ -1163,7 +1153,7 @@ Future<void> setup({
1153
1154 getIt.registerFactory(() => OtherSettingsPage(getIt.get<OtherSettingsViewModel>()));
1155
1166 - getIt.registerFactory(()=> AboutPage(appVersion: getIt.get<SettingsStore>().appVersion));
1156 + getIt.registerFactory(() => AboutPage(appVersion: getIt.get<SettingsStore>().appVersion));
1157
1158 getIt.registerFactory(() => NanoChangeRepPage(
1159 settingsStore: getIt.get<AppStore>().settingsStore,
@@ -1172,31 +1162,28 @@ Future<void> setup({
1162
1163 getIt.registerFactoryParam<NodeCreateOrEditViewModel, Map<String, dynamic>, void>(
1164 (Map<String, dynamic> args, _) {
1175 - final WalletType type = args['type'] as WalletType? ?? getIt.get<AppStore>().wallet!.type;
1176 - final bool isPow = args['isPow'] as bool? ?? false;
1177 - final Node? editingNode = args['editingNode'] as Node?;
1178 - return NodeCreateOrEditViewModel(
1179 - isPow,
1180 - type,
1181 - getIt.get<SettingsStore>(),
1182 - editingNode: editingNode
1183 - );
1184 - }
1185 - );
1165 + final WalletType type = args['type'] as WalletType? ?? getIt.get<AppStore>().wallet!.type;
1166 + final bool isPow = args['isPow'] as bool? ?? false;
1167 + final Node? editingNode = args['editingNode'] as Node?;
1168 + return NodeCreateOrEditViewModel(isPow, type, getIt.get<SettingsStore>(),
1169 + editingNode: editingNode);
1170 + });
1171
1172 getIt.registerFactoryParam<NodeCreateOrEditPage, Node?, bool?>(
1173 (Node? editingNode, bool? isSelected) {
1189 - final vm = getIt.get<NodeCreateOrEditViewModel>(param1: {'isPow' : false,'editingNode': editingNode});
1190 - return NodeCreateOrEditPage(
1191 - nodeCreateOrEditViewModel: vm,
1192 - editingNode: editingNode,
1193 - isSelected: isSelected,
1194 - type: getIt.get<AppStore>().wallet!.type);
1195 - });
1174 + final vm =
1175 + getIt.get<NodeCreateOrEditViewModel>(param1: {'isPow': false, 'editingNode': editingNode});
1176 + return NodeCreateOrEditPage(
1177 + nodeCreateOrEditViewModel: vm,
1178 + editingNode: editingNode,
1179 + isSelected: isSelected,
1180 + type: getIt.get<AppStore>().wallet!.type);
1181 + });
1182
1183 getIt.registerFactoryParam<PowNodeCreateOrEditPage, Node?, bool?>(
1184 (Node? editingNode, bool? isSelected) => PowNodeCreateOrEditPage(
1199 - nodeCreateOrEditViewModel: getIt.get<NodeCreateOrEditViewModel>(param1: {'isPow' : true, 'editingNode': editingNode}),
1185 + nodeCreateOrEditViewModel: getIt
1186 + .get<NodeCreateOrEditViewModel>(param1: {'isPow': true, 'editingNode': editingNode}),
1187 editingNode: editingNode,
1188 isSelected: isSelected));
1189
@@ -1225,12 +1212,12 @@ Future<void> setup({
1212 ));
1213
1214 getIt.registerFactory<MeldBuyProvider>(() => MeldBuyProvider(
1228 - wallet: getIt.get<AppStore>().wallet!,
1229 - ));
1215 + wallet: getIt.get<AppStore>().wallet!,
1216 + ));
1217
1218 getIt.registerFactory<KryptonimBuyProvider>(() => KryptonimBuyProvider(
1232 - wallet: getIt.get<AppStore>().wallet!,
1233 - ));
1219 + wallet: getIt.get<AppStore>().wallet!,
1220 + ));
1221
1222 getIt.registerFactoryParam<WebViewPage, String, Uri>((title, uri) => WebViewPage(title, uri));
1223
@@ -1253,10 +1240,8 @@ Future<void> setup({
1240
1241 getIt.registerFactoryParam<ExchangePage, PaymentRequest?, void>(
1242 (PaymentRequest? paymentRequest, __) {
1256 - return ExchangePage(getIt.get<ExchangeViewModel>(),
1257 - getIt.get<AuthService>(),
1258 - getIt.get<AddressResolverService>(),
1259 - paymentRequest);
1243 + return ExchangePage(getIt.get<ExchangeViewModel>(), getIt.get<AuthService>(),
1244 + getIt.get<AddressResolverService>(), paymentRequest);
1245 });
1246
1247 getIt.registerFactoryParam<NewSwapPage, PaymentRequest?, CryptoCurrency?>(
@@ -1276,8 +1261,8 @@ Future<void> setup({
1261 getIt.registerFactory(
1262 () => ExchangeTradePage(exchangeTradeViewModel: getIt.get<ExchangeTradeViewModel>()));
1263
1279 - getIt.registerFactory(
1280 - () => ExchangeTradeExternalSendPage(exchangeTradeViewModel: getIt.get<ExchangeTradeViewModel>()));
1264 + getIt.registerFactory(() =>
1265 + ExchangeTradeExternalSendPage(exchangeTradeViewModel: getIt.get<ExchangeTradeViewModel>()));
1266
1267 getIt.registerFactory(() => BackgroundSyncPage(getIt.get<DashboardViewModel>()));
1268
@@ -1298,13 +1283,13 @@ Future<void> setup({
1283 );
1284
1285 getIt.registerFactory(() => PaymentViewModel(
1301 - appStore: getIt.get<AppStore>(),
1302 - ));
1286 + appStore: getIt.get<AppStore>(),
1287 + ));
1288
1289 getIt.registerFactory(() => WalletSwitcherViewModel(
1305 - appStore: getIt.get<AppStore>(),
1306 - walletLoadingService: getIt.get<WalletLoadingService>(),
1307 - ));
1290 + appStore: getIt.get<AppStore>(),
1291 + walletLoadingService: getIt.get<WalletLoadingService>(),
1292 + ));
1293
1294 getIt.registerFactoryParam<WalletService, WalletType, void>((WalletType param1, __) {
1295 switch (param1) {
@@ -1328,9 +1313,11 @@ Future<void> setup({
1313 case WalletType.bsc:
1314 return evm!.createEVMWalletService(param1, SettingsStoreBase.walletPasswordDirectInput);
1315 case WalletType.bitcoinCash:
1331 - return bitcoinCash!.createBitcoinCashWalletService(_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
1316 + return bitcoinCash!.createBitcoinCashWalletService(
1317 + _unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
1318 case WalletType.dogecoin:
1333 - return dogecoin!.createDogeCoinWalletService(_unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
1319 + return dogecoin!.createDogeCoinWalletService(
1320 + _unspentCoinsInfoSource, SettingsStoreBase.walletPasswordDirectInput);
1321 case WalletType.nano:
1322 case WalletType.banano:
1323 return nano!.createNanoWalletService(SettingsStoreBase.walletPasswordDirectInput);
@@ -1354,19 +1341,16 @@ Future<void> setup({
1341 });
1342
1343 getIt.registerFactoryParam<SetupPinCodeViewModel, bool?, void>(
1357 - (isDuressPin, _) => SetupPinCodeViewModel(
1344 + (isDuressPin, _) => SetupPinCodeViewModel(
1345 getIt.get<AuthService>(),
1346 getIt.get<SettingsStore>(),
1347 isDuressPin: isDuressPin ?? false,
1348 ),
1349 );
1350
1364 -
1365 - getIt.registerFactoryParam<
1366 - SetupPinCodePage,
1367 - void Function(PinCodeState<PinCodeWidget>, String),
1351 + getIt.registerFactoryParam<SetupPinCodePage, void Function(PinCodeState<PinCodeWidget>, String),
1352 bool?>(
1369 - (onSuccessfulPinSetup, isDuressPin) => SetupPinCodePage(
1353 + (onSuccessfulPinSetup, isDuressPin) => SetupPinCodePage(
1354 getIt.get<SetupPinCodeViewModel>(param1: isDuressPin),
1355 onSuccessfulPinSetup: onSuccessfulPinSetup,
1356 isDuressPin: isDuressPin ?? false,
@@ -1386,17 +1370,14 @@ Future<void> setup({
1370 final restoredWallet = additionalParams?['restoredWallet'] as RestoredWallet?;
1371 final hardwareWalletType = additionalParams?['hardwareWalletType'] as HardwareWalletType?;
1372
1389 - return WalletRestoreViewModel(
1390 - getIt.get<AppStore>(),
1391 - getIt.get<WalletCreationService>(param1: type),
1392 - getIt.get<SeedSettingsViewModel>(),
1393 - type: type,
1394 - restoredWallet: restoredWallet,
1395 - hardwareWalletType: hardwareWalletType);
1373 + return WalletRestoreViewModel(getIt.get<AppStore>(),
1374 + getIt.get<WalletCreationService>(param1: type), getIt.get<SeedSettingsViewModel>(),
1375 + type: type, restoredWallet: restoredWallet, hardwareWalletType: hardwareWalletType);
1376 });
1377
1398 - getIt.registerFactoryParam<WalletRestorePage, WalletType, Map<String, dynamic>?>((type, additionalParams) =>
1399 - WalletRestorePage(getIt.get<WalletRestoreViewModel>(param1: type, param2: additionalParams),
1378 + getIt.registerFactoryParam<WalletRestorePage, WalletType, Map<String, dynamic>?>(
1379 + (type, additionalParams) => WalletRestorePage(
1380 + getIt.get<WalletRestoreViewModel>(param1: type, param2: additionalParams),
1381 getIt.get<SeedSettingsViewModel>()));
1382
1383 getIt.registerFactoryParam<WalletRestoreChooseDerivationViewModel, List<DerivationInfo>, void>(
@@ -1408,22 +1389,20 @@ Future<void> setup({
1389 param1: derivations,
1390 )));
1391
1411 - getIt.registerFactoryParam<TransactionDetailsViewModel, List<dynamic>, void>(
1412 - (params, _) {
1413 - final transactionInfo = params[0] as TransactionInfo;
1414 - final canReplaceByFee = params[1] as bool? ?? false;
1415 - final wallet = getIt.get<AppStore>().wallet!;
1416 -
1417 - return TransactionDetailsViewModel(
1418 - transactionInfo: transactionInfo,
1419 - transactionDescriptionBox: _transactionDescriptionBox,
1420 - wallet: wallet,
1421 - appStore: getIt.get<AppStore>(),
1422 - sendViewModel: getIt.get<SendViewModel>(),
1423 - canReplaceByFee: canReplaceByFee,
1424 - );
1425 - }
1426 - );
1392 + getIt.registerFactoryParam<TransactionDetailsViewModel, List<dynamic>, void>((params, _) {
1393 + final transactionInfo = params[0] as TransactionInfo;
1394 + final canReplaceByFee = params[1] as bool? ?? false;
1395 + final wallet = getIt.get<AppStore>().wallet!;
1396 +
1397 + return TransactionDetailsViewModel(
1398 + transactionInfo: transactionInfo,
1399 + transactionDescriptionBox: _transactionDescriptionBox,
1400 + wallet: wallet,
1401 + appStore: getIt.get<AppStore>(),
1402 + sendViewModel: getIt.get<SendViewModel>(),
1403 + canReplaceByFee: canReplaceByFee,
1404 + );
1405 + });
1406
1407 getIt.registerFactoryParam<TransactionDetailsModal, TransactionInfo, bool?>(
1408 (transactionInfo, highlightNoteField) => TransactionDetailsModal(
@@ -1433,22 +1412,20 @@ Future<void> setup({
1412 ));
1413
1414 getIt.registerFactoryParam<TransactionDetailsPage, TransactionInfo, void>(
1436 - (TransactionInfo transactionInfo, _) => TransactionDetailsPage(
1437 - transactionDetailsViewModel: getIt.get<TransactionDetailsViewModel>(
1438 - param1: [transactionInfo, false])));
1439 -
1440 - getIt.registerFactoryParam<RBFDetailsPage, List<dynamic>, void>(
1441 - (params, _) {
1442 - final transactionInfo = params[0] as TransactionInfo;
1443 - final txHex = params[1] as String;
1444 - return RBFDetailsPage(
1445 - transactionDetailsViewModel: getIt.get<TransactionDetailsViewModel>(
1446 - param1: [transactionInfo, true],
1447 - ),
1448 - rawTransaction: txHex,
1449 - );
1450 - }
1451 - );
1415 + (TransactionInfo transactionInfo, _) => TransactionDetailsPage(
1416 + transactionDetailsViewModel:
1417 + getIt.get<TransactionDetailsViewModel>(param1: [transactionInfo, false])));
1418 +
1419 + getIt.registerFactoryParam<RBFDetailsPage, List<dynamic>, void>((params, _) {
1420 + final transactionInfo = params[0] as TransactionInfo;
1421 + final txHex = params[1] as String;
1422 + return RBFDetailsPage(
1423 + transactionDetailsViewModel: getIt.get<TransactionDetailsViewModel>(
1424 + param1: [transactionInfo, true],
1425 + ),
1426 + rawTransaction: txHex,
1427 + );
1428 + });
1429
1430 getIt.registerFactoryParam<NewWalletTypePage, NewWalletTypeArguments, void>(
1431 (newWalletTypeArguments, _) {
@@ -1460,22 +1437,19 @@ Future<void> setup({
1437 getIt.registerFactory<PreSeedPage>(() => PreSeedPage());
1438
1439 getIt.registerFactoryParam<TransactionSuccessPage, String, void>(
1463 - (content, _) => TransactionSuccessPage(content: content));
1440 + (content, _) => TransactionSuccessPage(content: content));
1441
1442 getIt.registerFactoryParam<TradeDetailsViewModel, Trade, void>(
1443 (trade, _) => TradeDetailsViewModel(tradeForDetails: trade, appStore: getIt.get<AppStore>()));
1444
1445 getIt.registerFactory(() => CakeFeaturesViewModel(getIt.get<CakePayService>()));
1446
1470 -
1447 getIt.registerFactory(() => CakeFeaturesPage(
1448 dashboardViewModel: getIt.get<DashboardViewModel>(),
1449 cakeFeaturesViewModel: getIt.get<CakeFeaturesViewModel>()));
1450
1451 getIt.registerFactory(() => BackupServiceV3(getIt.get<SecureStorage>(),
1476 - _transactionDescriptionBox,
1477 - getIt.get<KeyService>(), getIt.get<SharedPreferences>()));
1478 -
1452 + _transactionDescriptionBox, getIt.get<KeyService>(), getIt.get<SharedPreferences>()));
1453
1454 getIt.registerFactory(() => BackupPage(getIt.get<BackupViewModel>()));
1455
@@ -1483,8 +1457,8 @@ Future<void> setup({
1457 () => EditBackupPasswordViewModel(getIt.get<SecureStorage>()),
1458 );
1459
1486 - getIt.registerFactory(() => BackupViewModel(
1487 - getIt.get<SecureStorage>(),getIt.get<BackupServiceV3>(), getIt.get<EditBackupPasswordViewModel>()));
1460 + getIt.registerFactory(() => BackupViewModel(getIt.get<SecureStorage>(),
1461 + getIt.get<BackupServiceV3>(), getIt.get<EditBackupPasswordViewModel>()));
1462
1463 getIt.registerFactory(() => EditBackupPasswordPage(getIt.get<EditBackupPasswordViewModel>()));
1464
@@ -1502,22 +1476,22 @@ Future<void> setup({
1476
1477 getIt.registerFactory(() => BuySellViewModel(getIt.get<AppStore>()));
1478
1505 - getIt.registerFactory(() => BuySellPage(getIt.get<BuySellViewModel>(), getIt.get<AddressResolverService>()));
1479 + getIt.registerFactory(
1480 + () => BuySellPage(getIt.get<BuySellViewModel>(), getIt.get<AddressResolverService>()));
1481
1482 getIt.registerFactoryParam<BuyOptionsPage, List<dynamic>, void>((List<dynamic> args, _) {
1483 final items = args.first as List<SelectableItem>;
1484 final pickAnOption = args[1] as void Function(SelectableOption option)?;
1485 final confirmOption = args[2] as void Function(BuildContext contex)?;
1511 - return BuyOptionsPage(
1512 - items: items, pickAnOption: pickAnOption, confirmOption: confirmOption);
1486 + return BuyOptionsPage(items: items, pickAnOption: pickAnOption, confirmOption: confirmOption);
1487 });
1488
1515 - getIt.registerFactoryParam<PaymentMethodOptionsPage, List<dynamic>, void>((List<dynamic> args, _) {
1489 + getIt
1490 + .registerFactoryParam<PaymentMethodOptionsPage, List<dynamic>, void>((List<dynamic> args, _) {
1491 final items = args.first as List<SelectableOption>;
1492 final pickAnOption = args[1] as void Function(SelectableOption option)?;
1493
1519 - return PaymentMethodOptionsPage(
1520 - items: items, pickAnOption: pickAnOption);
1494 + return PaymentMethodOptionsPage(items: items, pickAnOption: pickAnOption);
1495 });
1496
1497 getIt.registerFactory(() {
@@ -1578,11 +1552,11 @@ Future<void> setup({
1552 getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom)));
1553
1554 getIt.registerFactoryParam<NewCoinControlPage, UnspentCoinType?, bool?>(
1581 - (coinTypeToSpendFrom, canEdit) => NewCoinControlPage(
1582 - unspentCoinsListViewModel:
1583 - getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom), canEdit: canEdit ?? true,)
1584 -
1585 - );
1555 + (coinTypeToSpendFrom, canEdit) => NewCoinControlPage(
1556 + unspentCoinsListViewModel:
1557 + getIt.get<UnspentCoinsListViewModel>(param1: coinTypeToSpendFrom),
1558 + canEdit: canEdit ?? true,
1559 + ));
1560
1561 getIt.registerFactoryParam<UnspentCoinsDetailsViewModel, UnspentCoinsItem,
1562 UnspentCoinsListViewModel>(
@@ -1601,7 +1575,7 @@ Future<void> setup({
1575 getIt.registerFactory(() => YatService());
1576
1577 getIt.registerFactory<AddressResolverService>(
1604 - () => AddressResolverService(settingsStore: getIt.get<SettingsStore>()),
1578 + () => AddressResolverService(settingsStore: getIt.get<SettingsStore>()),
1579 );
1580
1581 getIt.registerFactoryParam<FullscreenQRPage, QrViewData, void>(
@@ -1614,15 +1588,15 @@ Future<void> setup({
1588 getIt.registerFactory<CakePayService>(
1589 () => CakePayService(getIt.get<SecureStorage>(), getIt.get<CakePayApi>()));
1590
1617 - getIt.registerFactory(
1618 - () => CakePayCardsListViewModel(cakePayService: getIt.get<CakePayService>(),
1619 - settingsStore: getIt.get<SettingsStore>()));
1591 + getIt.registerFactory(() => CakePayCardsListViewModel(
1592 + cakePayService: getIt.get<CakePayService>(), settingsStore: getIt.get<SettingsStore>()));
1593
1594 getIt.registerFactory(() => CakePayAuthViewModel(cakePayService: getIt.get<CakePayService>()));
1595
1596 getIt.registerFactoryParam<CakePayBuyCardViewModel, CakePayVendor, void>(
1597 (CakePayVendor vendor, _) {
1625 - return CakePayBuyCardViewModel(vendor: vendor,
1598 + return CakePayBuyCardViewModel(
1599 + vendor: vendor,
1600 cakePayService: getIt.get<CakePayService>(),
1601 sendViewModel: getIt.get<SendViewModel>(),
1602 orders: _ordersSource);
@@ -1666,8 +1640,7 @@ Future<void> setup({
1640 ));
1641
1642 getIt.registerFactoryParam<PayjoinDetailsViewModel, String, TransactionInfo?>(
1669 - (String sessionId, TransactionInfo? transactionInfo) =>
1670 - PayjoinDetailsViewModel(
1643 + (String sessionId, TransactionInfo? transactionInfo) => PayjoinDetailsViewModel(
1644 sessionId,
1645 transactionInfo,
1646 payjoinSessionSource: _payjoinSessionSource,
@@ -1684,8 +1657,8 @@ Future<void> setup({
1657
1658 getIt.registerFactoryParam<PayjoinDetailsPage, String, TransactionInfo?>(
1659 (String sessionId, TransactionInfo? transactionInfo) => PayjoinDetailsPage(
1687 - payjoinDetailsViewModel: getIt.get<PayjoinDetailsViewModel>(
1688 - param1: sessionId, param2: transactionInfo)));
1660 + payjoinDetailsViewModel:
1661 + getIt.get<PayjoinDetailsViewModel>(param1: sessionId, param2: transactionInfo)));
1662
1663 getIt.registerFactoryParam<HomeSettingsPage, BalanceViewModel, void>((balanceViewModel, _) =>
1664 HomeSettingsPage(getIt.get<HomeSettingsViewModel>(param1: balanceViewModel)));
@@ -1702,7 +1675,9 @@ Future<void> setup({
1675 );
1676
1677 getIt.registerFactoryParam<ManageNodesPage, bool, void>((bool isPow, _) {
1705 - return ManageNodesPage(isPow, nodeListViewModel: getIt.get<NodeListViewModel>(param1: isPow), dashboardViewModel: getIt.get<DashboardViewModel>());
1678 + return ManageNodesPage(isPow,
1679 + nodeListViewModel: getIt.get<NodeListViewModel>(param1: isPow),
1680 + dashboardViewModel: getIt.get<DashboardViewModel>());
1681 });
1682
1683 getIt.registerFactory(
@@ -1738,9 +1713,12 @@ Future<void> setup({
1713 getIt.registerFactory(() => DevQRToolsPage());
1714
1715 getIt.registerFactory(() => ExchangeProviderLogsViewModel());
1741 - getIt.registerFactory(() => DevExchangeProviderLogsPage(getIt.get<ExchangeProviderLogsViewModel>()));
1716 + getIt.registerFactory(
1717 + () => DevExchangeProviderLogsPage(getIt.get<ExchangeProviderLogsViewModel>()));
1718
1743 - getIt.registerFactory(() => StartTorPage(StartTorViewModel(),));
1719 + getIt.registerFactory(() => StartTorPage(
1720 + StartTorViewModel(),
1721 + ));
1722
1723 getIt.registerFactory(() => DEuroViewModel(
1724 getIt<AppStore>(),
@@ -1782,9 +1760,9 @@ Future<void> setup({
1760 ));
1761
1762 getIt.registerLazySingleton(() => NodeSwitchingService(
1785 - appStore: getIt.get<AppStore>(),
1786 - settingsStore: getIt.get<SettingsStore>(),
1787 - ));
1763 + appStore: getIt.get<AppStore>(),
1764 + settingsStore: getIt.get<SettingsStore>(),
1765 + ));
1766
1767 getIt.registerFactoryParam<BridgeAmountPage, CryptoCurrency, void>(
1768 (CryptoCurrency initialToken, _) => BridgeAmountPage(
lib/dogecoin/cw_dogecoin.dart
+2 -3
@@ -1,10 +1,9 @@
1 part of 'dogecoin.dart';
2
3 -
3 class CWDogeCoin extends DogeCoin {
5 -
4 @override
7 - WalletService createDogeCoinWalletService(Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
5 + WalletService createDogeCoinWalletService(
6 + Box<UnspentCoinsInfo> unspentCoinSource, bool isDirect) {
7 return DogeCoinWalletService(unspentCoinSource, isDirect);
8 }
9
lib/entities/auto_generate_subaddress_status.dart
+5 -7
@@ -1,13 +1,11 @@
1 -
2 -enum AutoGenerateSubaddressStatus {
3 - initialized(1),
4 - enabled(2),
1 +enum AutoGenerateSubaddressStatus {
2 + initialized(1),
3 + enabled(2),
4 disabled(3);
5
6 const AutoGenerateSubaddressStatus(this.value);
7 final int value;
8
10 - static AutoGenerateSubaddressStatus deserialize({required int raw}) =>
9 + static AutoGenerateSubaddressStatus deserialize({required int raw}) =>
10 AutoGenerateSubaddressStatus.values.firstWhere((e) => e.value == raw);
12 -
13 -}
\ No newline at end of file
11 +}
lib/entities/balance_display_mode.dart
+3 -6
@@ -11,12 +11,9 @@ class BalanceDisplayMode extends EnumerableItem<int> with Serializable<int> {
11 BalanceDisplayMode.displayableBalance,
12 ];
13 static const fullBalance = BalanceDisplayMode(raw: 0, title: 'Full Balance');
14 - static const availableBalance =
15 - BalanceDisplayMode(raw: 1, title: 'Available Balance');
16 - static const hiddenBalance =
17 - BalanceDisplayMode(raw: 2, title: 'Hidden Balance');
18 - static const displayableBalance =
19 - BalanceDisplayMode(raw: 3, title: 'Displayable Balance');
14 + static const availableBalance = BalanceDisplayMode(raw: 1, title: 'Available Balance');
15 + static const hiddenBalance = BalanceDisplayMode(raw: 2, title: 'Hidden Balance');
16 + static const displayableBalance = BalanceDisplayMode(raw: 3, title: 'Displayable Balance');
17
18 static BalanceDisplayMode deserialize({required int raw}) {
19 switch (raw) {
lib/entities/biometric_auth.dart
+1 -1
@@ -27,4 +27,4 @@ class BiometricAuth {
27
28 return canAuthenticate;
29 }
30 -}
\ No newline at end of file
30 +}
lib/entities/bitcoin_amount_display_mode.dart
+1 -2
@@ -9,8 +9,7 @@ class BitcoinAmountDisplayMode extends EnumerableItem<int> with Serializable<int
9 BitcoinAmountDisplayMode.satoshiForLightning,
10 BitcoinAmountDisplayMode.bitcoin,
11 ];
12 - static const satoshiForLightning =
13 - BitcoinAmountDisplayMode(raw: 0, title: 'sats (LN)');
12 + static const satoshiForLightning = BitcoinAmountDisplayMode(raw: 0, title: 'sats (LN)');
13 static const bitcoin = BitcoinAmountDisplayMode(raw: 1, title: 'BTC');
14 static const satoshi = BitcoinAmountDisplayMode(raw: 2, title: 'sats');
15
lib/entities/calculate_fiat_amount.dart
+2 -2
@@ -16,7 +16,7 @@ String calculateFiatAmount({double? price, String? cryptoAmount, bool raw = fals
16 return '0.00';
17 }
18
19 - if(raw) {
19 + if (raw) {
20 return result.toStringAsFixed(2);
21 }
22
@@ -48,7 +48,7 @@ String formatWithCommas(String? number) {
48 (Match match) => ',',
49 );
50
51 - if(decimalPart.length == 1) {
51 + if (decimalPart.length == 1) {
52 decimalPart = "${decimalPart}0";
53 }
54
lib/entities/calculate_fiat_amount_raw.dart
+1 -1
@@ -12,4 +12,4 @@ String calculateFiatAmountRaw({required double cryptoAmount, double? price}) {
12 }
13
14 return result > 0.01 ? formatWithCommas(result.toStringAsFixed(2)) : '< 0.01';
15 -}
\ No newline at end of file
15 +}
lib/entities/contact.dart
+6 -1
@@ -7,7 +7,12 @@ part 'contact.part.dart';
7
8 // @HiveType(typeId: Contact.typeId)
9 class Contact extends HiveObject with Keyable {
10 - Contact({required this.name, required this.address, CryptoCurrency? type, DateTime? lastChange, this.displayName = ""})
10 + Contact(
11 + {required this.name,
12 + required this.address,
13 + CryptoCurrency? type,
14 + DateTime? lastChange,
15 + this.displayName = ""})
16 : lastChange = lastChange ?? DateTime.now() {
17 if (type != null) {
18 raw = type.raw;
lib/entities/contact.part.dart
+1 -3
@@ -46,7 +46,5 @@ class ContactAdapter extends TypeAdapter<Contact> {
46 @override
47 bool operator ==(Object other) =>
48 identical(this, other) ||
49 - other is ContactAdapter &&
50 - runtimeType == other.runtimeType &&
51 - typeId == other.typeId;
49 + other is ContactAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
50 }
lib/entities/contact_base.dart
+1 -1
@@ -10,4 +10,4 @@ abstract class ContactBase {
10 String displayName;
11
12 CryptoCurrency type;
13 -}
\ No newline at end of file
13 +}
lib/entities/country.dart
+4 -3
@@ -11,7 +11,8 @@ class Country extends EnumerableItem<String> with Serializable<String> {
11 static List<Country> get all => _all.values.toList();
12
13 static List<Country> get allForCakePay => _all.values
14 - .where((element) => element.countryCode != 'EU' && element.countryCode != 'AQ').toList();
14 + .where((element) => element.countryCode != 'EU' && element.countryCode != 'AQ')
15 + .toList();
16
17 static const afghanistan = Country(code: 'afg', countryCode: 'AF', fullName: "Afghanistan");
18 static const andorra = Country(code: 'and', countryCode: 'AD', fullName: "Andorra");
@@ -366,9 +367,9 @@ class Country extends EnumerableItem<String> with Serializable<String> {
367 return _all.values.firstWhereOrNull((element) => element.raw == countryCode.toLowerCase());
368 }
369
369 -
370 static Country? fromCountryCode(String countryCode) {
371 - return _all.values.firstWhereOrNull((element) => element.countryCode == countryCode.toUpperCase());
371 + return _all.values
372 + .firstWhereOrNull((element) => element.countryCode == countryCode.toUpperCase());
373 }
374
375 @override
lib/entities/default_settings_migration.dart
+15 -18
@@ -283,7 +283,7 @@ Future<void> defaultSettingsMigration(
283 // await insecureStorageMigration(secureStorage: secureStorage, sharedPreferences: sharedPreferences);
284 break;
285 case 27:
286 - await addWalletNodeList( type: WalletType.solana);
286 + await addWalletNodeList(type: WalletType.solana);
287 await _changeDefaultNode(
288 sharedPreferences: sharedPreferences,
289 type: WalletType.solana,
@@ -516,7 +516,7 @@ Future<void> defaultSettingsMigration(
516 currentNodePreferenceKey: PreferencesKey.currentBaseNodeIdKey,
517 );
518 break;
519 - case 53:
519 + case 53:
520 await addWalletNodeList(type: WalletType.arbitrum);
521 await _changeDefaultNode(
522 sharedPreferences: sharedPreferences,
@@ -662,13 +662,13 @@ Future<void> _changeDefaultNode({
662 shouldReplace = true;
663 } else {
664 final currentNode = nodes.firstWhereOrNull((node) => node.id == currentNodeId);
665 - shouldReplace = currentNode == null || (oldUri?.any((e) => currentNode!.uriRaw.contains(e)) ?? true);
665 + shouldReplace =
666 + currentNode == null || (oldUri?.any((e) => currentNode!.uriRaw.contains(e)) ?? true);
667 }
668
669 if (shouldReplace) {
670 newDefaultUri ??= (await getDefaultNodeFromFiles(type)).uriRaw;
670 - var newNodeId =
671 - nodes.firstWhereOrNull((element) => element.uriRaw == newDefaultUri)?.id;
671 + var newNodeId = nodes.firstWhereOrNull((element) => element.uriRaw == newDefaultUri)?.id;
672
673 // new node doesn't exist, then add it
674 if (newNodeId == null) {
@@ -734,8 +734,7 @@ Future<void> updateNanoNodeList() async {
734 }
735
736 // update the nautilus node:
737 - final nautilusNode =
738 - nodes.firstWhereOrNull((element) => element.uriRaw == "node.perish.co");
737 + final nautilusNode = nodes.firstWhereOrNull((element) => element.uriRaw == "node.perish.co");
738 if (nautilusNode != null) {
739 nautilusNode.uriRaw = "node.nautilus.io";
740 nautilusNode.path = "/api";
@@ -855,9 +854,9 @@ Future<void> validateBitcoinSavedTransactionPriority(SharedPreferences sharedPre
854 Future<void> replaceNodesMigration() async {
855 final replaceNodes = <String, Node>{
856 'eu-node.cakewallet.io:18081':
858 - Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
857 + Node(uri: 'xmr-node-eu.cakewallet.com:18081', type: WalletType.monero),
858 'node.cakewallet.io:18081':
860 - Node(uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
859 + Node(uri: 'xmr-node-usa-east.cakewallet.com:18081', type: WalletType.monero),
860 'node.xmr.ru:13666': Node(uri: 'node.monero.net:18081', type: WalletType.monero)
861 };
862
@@ -874,11 +873,10 @@ Future<void> replaceNodesMigration() async {
873 });
874 }
875
877 -Future<Node?> getBitcoinTestnetDefaultElectrumServer()async {
876 +Future<Node?> getBitcoinTestnetDefaultElectrumServer() async {
877 final nodes = await Node.getAll();
878
880 - return nodes
881 - .firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ??
879 + return nodes.firstWhereOrNull((Node node) => node.uriRaw == publicBitcoinTestnetElectrumUri) ??
880 nodes.firstWhereOrNull((node) => node.type == WalletType.bitcoin);
881 }
882
@@ -1086,8 +1084,8 @@ Future<void> resetBitcoinElectrumServer(SharedPreferences sharedPreferences) asy
1084 sharedPreferences.getInt(PreferencesKey.currentBitcoinElectrumSererIdKey);
1085 final oldElectrumServer = nodeSource
1086 .firstWhereOrNull((node) => node.uri.toString().contains('electrumx.cakewallet.com'));
1089 - var cakeWalletNode = nodeSource
1090 - .firstWhereOrNull((node) => node.uriRaw.toString() == cakeWalletBitcoinElectrumUri);
1087 + var cakeWalletNode =
1088 + nodeSource.firstWhereOrNull((node) => node.uriRaw.toString() == cakeWalletBitcoinElectrumUri);
1089
1090 if (cakeWalletNode == null) {
1091 cakeWalletNode = Node(
@@ -1147,8 +1145,7 @@ Future<void> addWalletNodeList({required WalletType type}) async {
1145 }
1146 }
1147
1150 -Future<void> removeMoneroWorld(
1151 - {required SharedPreferences sharedPreferences}) async {
1148 +Future<void> removeMoneroWorld({required SharedPreferences sharedPreferences}) async {
1149 final nodes = await Node.getAll();
1150 const cakeWalletMoneroNodeUriPattern = '.moneroworld.com';
1151 final currentMoneroNodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
@@ -1218,14 +1215,13 @@ Future<void> migrateExistingNodesToUseAutoSwitching() async {
1215
1216 final powNodes = await Node.getAllPow();
1217
1221 - for(var node in powNodes) {
1218 + for (var node in powNodes) {
1219 if (listOfDefaultNodesWithAutoSwitching.contains(node.uriRaw)) {
1220 node.isEnabledForAutoSwitching = true;
1221 node.isPow = true;
1222 await node.save();
1223 }
1224 }
1228 -
1225 }
1226
1227 Future<void> _addXautTokenToExistingEthereumWallets() async {
@@ -1264,6 +1260,7 @@ Future<void> _addXautTokenToExistingEthereumWallets() async {
1260 printV('Error in XAUT migration: $e');
1261 }
1262 }
1263 +
1264 Future<void> _addXaut0TokenToExistingSolanaWallets() async {
1265 try {
1266 final xaut0Token = SPLToken(
lib/entities/emoji_string_extension.dart
+4 -4
@@ -16,11 +16,11 @@ extension Emoji on String {
16
17 bool _hasOnlyEmojis() {
18 final parsedText = this.replaceAll(' ', '');
19 - if(parsedText.isEmpty) return false;
20 - for (final c in Characters(parsedText))
21 - if (!REGEX_EMOJI.hasMatch(c)) return false;
19 + if (parsedText.isEmpty) return false;
20 + for (final c in Characters(parsedText)) if (!REGEX_EMOJI.hasMatch(c)) return false;
21 return true;
22 }
24 - /// Returns true if the given text contains only emojis.
23 +
24 + /// Returns true if the given text contains only emojis.
25 bool get hasOnlyEmojis => _hasOnlyEmojis();
26 }
lib/entities/evm_transaction_error_fees_handler.dart
+11 -7
@@ -54,7 +54,9 @@ class EVMTransactionErrorFeesHandler {
54 // Pattern 2: "balance X, queued cost Y, tx cost Z, overshot W" format (most specific)
55 ErrorPattern(
56 name: 'balance_queued_txcost_overshot',
57 - regex: RegExp(r'balance\s+(\d+),\s*queued\s+cost\s+(\d+),\s*tx\s+cost\s+(\d+),\s*overshot\s+(\d+)', caseSensitive: false),
57 + regex: RegExp(
58 + r'balance\s+(\d+),\s*queued\s+cost\s+(\d+),\s*tx\s+cost\s+(\d+),\s*overshot\s+(\d+)',
59 + caseSensitive: false),
60 extractor: (match) => {
61 'balance': match.group(1)!,
62 'txCost': match.group(3)!, // Skip queued cost, use tx cost
@@ -70,7 +72,8 @@ class EVMTransactionErrorFeesHandler {
72 // Pattern 3: "balance X, tx cost Y, overshot Z" format
73 ErrorPattern(
74 name: 'balance_txcost_overshot',
73 - regex: RegExp(r'balance\s+(\d+),\s*tx\s+cost\s+(\d+),\s*overshot\s+(\d+)', caseSensitive: false),
75 + regex: RegExp(r'balance\s+(\d+),\s*tx\s+cost\s+(\d+),\s*overshot\s+(\d+)',
76 + caseSensitive: false),
77 extractor: (match) => {
78 'balance': match.group(1)!,
79 'txCost': match.group(2)!,
@@ -86,7 +89,8 @@ class EVMTransactionErrorFeesHandler {
89 // Pattern 4: Individual field matching (legacy fallback)
90 ErrorPattern(
91 name: 'individual_fields',
89 - regex: RegExp(r'balance\s+(\d+).*tx\s+cost\s+(\d+).*overshot\s+(\d+)', caseSensitive: false),
92 + regex:
93 + RegExp(r'balance\s+(\d+).*tx\s+cost\s+(\d+).*overshot\s+(\d+)', caseSensitive: false),
94 extractor: (match) => {
95 'balance': match.group(1)!,
96 'txCost': match.group(2)!,
@@ -102,7 +106,8 @@ class EVMTransactionErrorFeesHandler {
106 // Pattern 5: Generic "insufficient funds for gas * price + value" (least specific - must be last)
107 ErrorPattern(
108 name: 'generic_insufficient_funds',
105 - regex: RegExp(r'insufficient\s+funds\s+for\s+gas\s*\*\s*price\s*\+\s*value', caseSensitive: false),
109 + regex: RegExp(r'insufficient\s+funds\s+for\s+gas\s*\*\s*price\s*\+\s*value',
110 + caseSensitive: false),
111 extractor: (match) => {
112 'balance': '0', // We don't have specific values, so use 0
113 'txCost': '0',
@@ -142,9 +147,8 @@ class EVMTransactionErrorFeesHandler {
147 final txCostWei = BigInt.parse(values['txCostWei']!);
148 final overshotWei = BigInt.parse(values['overshotWei']!);
149
145 - final isGenericError = balanceWei == BigInt.zero &&
146 - txCostWei == BigInt.zero &&
147 - overshotWei == BigInt.zero;
150 + final isGenericError =
151 + balanceWei == BigInt.zero && txCostWei == BigInt.zero && overshotWei == BigInt.zero;
152
153 if (isGenericError) {
154 return genericInsufficientFunds();
lib/entities/exchange_api_mode.dart
+1 -1
@@ -36,4 +36,4 @@ class ExchangeApiMode extends EnumerableItem<int> with Serializable<int> {
36 return '';
37 }
38 }
39 -}
\ No newline at end of file
39 +}
lib/entities/fiat_currency.dart
+20 -10
@@ -85,15 +85,18 @@ class FiatCurrency extends EnumerableItem<String> with Serializable<String> impl
85 static const eur = FiatCurrency(symbol: 'EUR', countryCode: "eur", fullName: "Euro");
86 static const gbp = FiatCurrency(symbol: 'GBP', countryCode: "gbr", fullName: "Pound Sterling");
87 static const ghs = FiatCurrency(symbol: 'GHS', countryCode: "gha", fullName: "Ghanaian Cedi");
88 - static const gtq = FiatCurrency(symbol: 'GTQ', countryCode: "gtm", fullName: "Guatemalan Quetzal");
88 + static const gtq =
89 + FiatCurrency(symbol: 'GTQ', countryCode: "gtm", fullName: "Guatemalan Quetzal");
90 static const hkd = FiatCurrency(symbol: 'HKD', countryCode: "hkg", fullName: "Hong Kong Dollar");
91 static const hrk = FiatCurrency(symbol: 'HRK', countryCode: "hrv", fullName: "Croatian Kuna");
92 static const huf = FiatCurrency(symbol: 'HUF', countryCode: "hun", fullName: "Hungarian Forint");
93 static const idr = FiatCurrency(symbol: 'IDR', countryCode: "idn", fullName: "Indonesian Rupiah");
93 - static const ils = FiatCurrency(symbol: 'ILS', countryCode: "isr", fullName: "Israeli New Shekel");
94 + static const ils =
95 + FiatCurrency(symbol: 'ILS', countryCode: "isr", fullName: "Israeli New Shekel");
96 static const inr = FiatCurrency(symbol: 'INR', countryCode: "ind", fullName: "Indian Rupee");
97 static const irr = FiatCurrency(symbol: 'IRR', countryCode: "irn", fullName: "Iranian Rial");
96 - static const isk = FiatCurrency(symbol: 'ISK', countryCode: "isl", fullName: "Icelandic Krona Króna");
98 + static const isk =
99 + FiatCurrency(symbol: 'ISK', countryCode: "isl", fullName: "Icelandic Krona Króna");
100 static const jpy = FiatCurrency(symbol: 'JPY', countryCode: "jpn", fullName: "Japanese Yen");
101 static const krw = FiatCurrency(symbol: 'KRW', countryCode: "kor", fullName: "South Korean Won");
102 static const mad = FiatCurrency(symbol: 'MAD', countryCode: "mar", fullName: "Moroccan Dirham");
@@ -101,22 +104,29 @@ class FiatCurrency extends EnumerableItem<String> with Serializable<String> impl
104 static const myr = FiatCurrency(symbol: 'MYR', countryCode: "mys", fullName: "Malaysian Ringgit");
105 static const ngn = FiatCurrency(symbol: 'NGN', countryCode: "nga", fullName: "Nigerian Naira");
106 static const nok = FiatCurrency(symbol: 'NOK', countryCode: "nor", fullName: "Norwegian Krone");
104 - static const nzd = FiatCurrency(symbol: 'NZD', countryCode: "nzl", fullName: "New Zealand Dollar");
107 + static const nzd =
108 + FiatCurrency(symbol: 'NZD', countryCode: "nzl", fullName: "New Zealand Dollar");
109 static const php = FiatCurrency(symbol: 'PHP', countryCode: "phl", fullName: "Philippine Peso");
110 static const pkr = FiatCurrency(symbol: 'PKR', countryCode: "pak", fullName: "Pakistani Rupee");
107 - static const pln = FiatCurrency(symbol: 'PLN', countryCode: "pol", fullName: "Poland Zloty złoty");
111 + static const pln =
112 + FiatCurrency(symbol: 'PLN', countryCode: "pol", fullName: "Poland Zloty złoty");
113 static const ron = FiatCurrency(symbol: 'RON', countryCode: "rou", fullName: "Romanian Leu");
114 static const rub = FiatCurrency(symbol: 'RUB', countryCode: "rus", fullName: "Russian Ruble");
115 static const sar = FiatCurrency(symbol: 'SAR', countryCode: "sau", fullName: "Saudi Riyal");
116 static const sek = FiatCurrency(symbol: 'SEK', countryCode: "swe", fullName: "Swedish Krona");
117 static const sgd = FiatCurrency(symbol: 'SGD', countryCode: "sgp", fullName: "Singapore Dollar");
113 - static const thb = FiatCurrency(symbol: 'THB', countryCode: "tha", fullName: "New Thaiwan Dollar");
118 + static const thb =
119 + FiatCurrency(symbol: 'THB', countryCode: "tha", fullName: "New Thaiwan Dollar");
120 static const twd = FiatCurrency(symbol: 'TWD', countryCode: "twn", fullName: "Thai Baht");
121 static const uah = FiatCurrency(symbol: 'UAH', countryCode: "ukr", fullName: "Ukrainian Hryvnia");
116 - static const usd = FiatCurrency(symbol: 'USD', countryCode: "usa", fullName: "United States Dollar");
117 - static const vef = FiatCurrency(symbol: 'VEF', countryCode: "ven", fullName: "Venezuelan Bolivar Bolívar");
118 - static const vnd = FiatCurrency(symbol: 'VND', countryCode: "vnm", fullName: "Vietnamese Dong đồng");
119 - static const zar = FiatCurrency(symbol: 'ZAR', countryCode: "saf", fullName: "South African Rand");
122 + static const usd =
123 + FiatCurrency(symbol: 'USD', countryCode: "usa", fullName: "United States Dollar");
124 + static const vef =
125 + FiatCurrency(symbol: 'VEF', countryCode: "ven", fullName: "Venezuelan Bolivar Bolívar");
126 + static const vnd =
127 + FiatCurrency(symbol: 'VND', countryCode: "vnm", fullName: "Vietnamese Dong đồng");
128 + static const zar =
129 + FiatCurrency(symbol: 'ZAR', countryCode: "saf", fullName: "South African Rand");
130 static const tur = FiatCurrency(symbol: 'TRY', countryCode: "tur", fullName: "Turkish Lira");
131 static const kes = FiatCurrency(symbol: 'KES', countryCode: "ken", fullName: "Kenyan Shillings");
132
lib/entities/format_amount.dart
+3 -3
@@ -1,10 +1,10 @@
1 import 'calculate_fiat_amount.dart';
2
3 String formatAmount(String amount) {
4 - if ((!amount.contains('.'))&&(!amount.contains(','))) {
4 + if ((!amount.contains('.')) && (!amount.contains(','))) {
5 return formatWithCommas(amount + '.00');
6 - } else if ((amount.endsWith('.'))||(amount.endsWith(','))) {
6 + } else if ((amount.endsWith('.')) || (amount.endsWith(','))) {
7 return formatWithCommas(amount + '00');
8 }
9 return formatWithCommas(amount);
10 -}
\ No newline at end of file
10 +}
lib/entities/hardware_wallet/require_hardware_wallet_connection.dart
+2 -5
@@ -5,11 +5,8 @@ import 'package:cw_core/wallet_type.dart';
5 import 'package:shared_preferences/shared_preferences.dart';
6
7 Future<bool> requireHardwareWalletConnection() async {
8 - final name = getIt
9 - .get<SharedPreferences>()
10 - .getString(PreferencesKey.currentWalletName);
11 - final typeRaw =
12 - getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType);
8 + final name = getIt.get<SharedPreferences>().getString(PreferencesKey.currentWalletName);
9 + final typeRaw = getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType);
10
11 if (typeRaw == null) {
12 return false;
lib/entities/haven_seed_store.part.dart
+1 -3
@@ -38,7 +38,5 @@ class HavenSeedStoreAdapter extends TypeAdapter<HavenSeedStore> {
38 @override
39 bool operator ==(Object other) =>
40 identical(this, other) ||
41 - other is HavenSeedStoreAdapter &&
42 - runtimeType == other.runtimeType &&
43 - typeId == other.typeId;
41 + other is HavenSeedStoreAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
42 }
lib/entities/ios_legacy_helper.dart
+6 -12
@@ -3,23 +3,17 @@ import 'dart:typed_data';
3 import 'package:flutter/foundation.dart';
4 import 'package:flutter/services.dart';
5
6 -const platform =
7 - const MethodChannel('com.cakewallet.cakewallet/legacy_wallet_migration');
6 +const platform = const MethodChannel('com.cakewallet.cakewallet/legacy_wallet_migration');
7
9 -Future<String> decrypt(Uint8List bytes,
10 - {required String key, required String salt}) async =>
11 - (await platform
12 - .invokeMethod<String>('decrypt', {'bytes': bytes, 'key': key, 'salt': salt}))!;
8 +Future<String> decrypt(Uint8List bytes, {required String key, required String salt}) async =>
9 + (await platform.invokeMethod<String>('decrypt', {'bytes': bytes, 'key': key, 'salt': salt}))!;
10
11 Future<dynamic> readUserDefaults(String key, {required String type}) async =>
15 - await platform
16 - .invokeMethod<dynamic>('read_user_defaults', {'key': key, 'type': type});
12 + await platform.invokeMethod<dynamic>('read_user_defaults', {'key': key, 'type': type});
13
14 Future<String?> getString(String key) async =>
15 await readUserDefaults(key, type: 'string') as String?;
16
21 -Future<bool?> getBool(String key) async =>
22 - await readUserDefaults(key, type: 'bool') as bool?;
17 +Future<bool?> getBool(String key) async => await readUserDefaults(key, type: 'bool') as bool?;
18
24 -Future<int?> getInt(String key) async =>
25 - await readUserDefaults(key, type: 'int') as int?;
19 +Future<int?> getInt(String key) async => await readUserDefaults(key, type: 'int') as int?;
lib/entities/new_ui_entities/list_item/list_item.dart
+3 -3
@@ -15,7 +15,7 @@ abstract class ListItem {
15 final bool isLastInSection;
16
17 BorderRadius get radius => BorderRadius.vertical(
18 - top: Radius.circular(isFirstInSection ? 16 : 0),
19 - bottom: Radius.circular(isLastInSection ? 16 : 0),
20 - );
18 + top: Radius.circular(isFirstInSection ? 16 : 0),
19 + bottom: Radius.circular(isLastInSection ? 16 : 0),
20 + );
21 }
lib/entities/new_ui_entities/list_item/list_item_selector.dart
+1 -1
@@ -13,4 +13,4 @@ class ListItemSelector extends ListItem {
13 final String? trailingText;
14 final VoidCallback onTap;
15 final List<String> options;
16 -}
\ No newline at end of file
16 +}
lib/entities/new_ui_entities/list_item/list_item_text_field.dart
+8 -11
@@ -2,21 +2,18 @@ import 'package:cake_wallet/entities/new_ui_entities/list_item/list_item.dart';
2 import 'package:flutter/material.dart';
3
4 class ListItemTextField extends ListItem {
5 - const ListItemTextField({
6 - required super.keyValue,
7 - required super.label,
8 - this.initialValue,
9 - this.validator,
10 - this.onChanged,
11 - this.onFieldSubmitted,
12 - this.focusNode
13 - });
5 + const ListItemTextField(
6 + {required super.keyValue,
7 + required super.label,
8 + this.initialValue,
9 + this.validator,
10 + this.onChanged,
11 + this.onFieldSubmitted,
12 + this.focusNode});
13
14 final String? initialValue;
15 final FormFieldValidator<String>? validator;
16 final ValueChanged<String>? onChanged;
17 final ValueChanged<String>? onFieldSubmitted;
18 final FocusNode? focusNode;
20 -
21 -
19 }
lib/entities/node_check.dart
+12 -11
@@ -31,19 +31,21 @@ const Map<WalletType, String> powNodePreferenceKeys = {
31 WalletType.nano: PreferencesKey.currentNanoPowNodeIdKey
32 };
33
34 -Future<void> checkNodeForWalletType(SharedPreferences sharedPreferences, SettingsStore settingsStore, WalletType type, bool isPow) async {
34 +Future<void> checkNodeForWalletType(SharedPreferences sharedPreferences,
35 + SettingsStore settingsStore, WalletType type, bool isPow) async {
36 final preferenceKey = isPow ? powNodePreferenceKeys[type] : nodePreferenceKeys[type];
37
37 - if(preferenceKey == null) {
38 + if (preferenceKey == null) {
39 return;
40 }
41
42 final currentId = await sharedPreferences.getInt(preferenceKey);
43
43 - final nodes = isPow ? await Node.getAllForWalletTypePow(type) : await Node.getAllForWalletType(type);
44 - final currentNode = nodes.firstWhereOrNull((item)=>item.id == currentId);
44 + final nodes =
45 + isPow ? await Node.getAllForWalletTypePow(type) : await Node.getAllForWalletType(type);
46 + final currentNode = nodes.firstWhereOrNull((item) => item.id == currentId);
47
46 - if(currentNode == null) {
48 + if (currentNode == null) {
49 final newNode = (isPow
50 ? await Node.getDefaultPowForWalletType(type)
51 : await Node.getDefaultForWalletType(type)) ??
@@ -54,16 +56,15 @@ Future<void> checkNodeForWalletType(SharedPreferences sharedPreferences, Setting
56 } else {
57 settingsStore.nodes[type] = currentNode;
58 }
57 -
59 }
60
60 -
61 -Future<void> checkCurrentNodes(SharedPreferences sharedPreferences, SettingsStore settingsStore) async {
62 - for(final walletType in nodePreferenceKeys.keys) {
61 +Future<void> checkCurrentNodes(
62 + SharedPreferences sharedPreferences, SettingsStore settingsStore) async {
63 + for (final walletType in nodePreferenceKeys.keys) {
64 await checkNodeForWalletType(sharedPreferences, settingsStore, walletType, false);
65 }
66
66 - for(final walletType in powNodePreferenceKeys.keys) {
67 + for (final walletType in powNodePreferenceKeys.keys) {
68 await checkNodeForWalletType(sharedPreferences, settingsStore, walletType, true);
69 }
69 -}
\ No newline at end of file
70 +}
lib/entities/node_list.dart
+1
@@ -0,0 +1 @@
1 +
lib/entities/pin_code_required_duration.dart
+1 -1
@@ -11,7 +11,7 @@ enum PinCodeRequiredDuration {
11
12 final int value;
13
14 - static PinCodeRequiredDuration deserialize({required int raw}) =>
14 + static PinCodeRequiredDuration deserialize({required int raw}) =>
15 PinCodeRequiredDuration.values.firstWhere((e) => e.value == raw);
16
17 @override
lib/entities/preferences_key.dart
+2 -1
@@ -137,7 +137,8 @@ class PreferencesKey {
137 static const walletConnectPairingTopicsList = 'wallet_connect_pairing_topics_list';
138 static String walletConnectPairingTopicsListForWallet(String publicKey) =>
139 '${PreferencesKey.walletConnectPairingTopicsList}_${publicKey}';
140 - static String backgroundSyncLastTrigger(String walletId) => 'background_sync_last_trigger_${walletId}';
140 + static String backgroundSyncLastTrigger(String walletId) =>
141 + 'background_sync_last_trigger_${walletId}';
142 static const backgroundSyncNotificationsEnabled = 'background_sync_notifications_enabled';
143 static const enableAutomaticNodeSwitching = 'enable_automatic_node_switching';
144 static const syncStatusDisplayMode = 'sync_status_display_mode';
lib/entities/provider_types.dart
+13 -13
@@ -47,20 +47,20 @@ extension ProviderTypeName on ProviderType {
47
48 class ProvidersHelper {
49 static List<ProviderType> getAvailableBuyProviderTypes() => [
50 - ProviderType.robinhood,
51 - ProviderType.dfx,
52 - ProviderType.onramper,
53 - ProviderType.moonpay,
54 - ProviderType.kriptonim
55 - ];
50 + ProviderType.robinhood,
51 + ProviderType.dfx,
52 + ProviderType.onramper,
53 + ProviderType.moonpay,
54 + ProviderType.kriptonim
55 + ];
56
57 static List<ProviderType> getAvailableSellProviderTypes() => [
58 - // ProviderType.robinhood, // ToDo: (Konsti) Enable once fixed in Exchange Helper, but still waiting for new Docs
59 - ProviderType.dfx,
60 - ProviderType.onramper,
61 - ProviderType.moonpay,
62 - ProviderType.kriptonim
63 - ];
58 + // ProviderType.robinhood, // ToDo: (Konsti) Enable once fixed in Exchange Helper, but still waiting for new Docs
59 + ProviderType.dfx,
60 + ProviderType.onramper,
61 + ProviderType.moonpay,
62 + ProviderType.kriptonim
63 + ];
64
65 static BuyProvider getProviderByType(ProviderType type) {
66 switch (type) {
@@ -76,6 +76,6 @@ class ProvidersHelper {
76 return getIt.get<MeldBuyProvider>();
77 case ProviderType.kriptonim:
78 return getIt.get<KryptonimBuyProvider>();
79 - }
79 + }
80 }
81 }
lib/entities/qr_scanner.dart
+2 -1
@@ -14,7 +14,8 @@ import 'package:ur/ur_decoder.dart';
14
15 var isQrScannerShown = false;
16
17 -Future<String?> presentQRScanner(BuildContext context, {bool showHelp = false, bool showManualInput = true, bool useModal = false}) async {
17 +Future<String?> presentQRScanner(BuildContext context,
18 + {bool showHelp = false, bool showManualInput = true, bool useModal = false}) async {
19 isQrScannerShown = true;
20 try {
21 final result = useModal
lib/entities/qr_view_data.dart
+1 -1
@@ -5,7 +5,7 @@ class QrViewData {
5 required this.data,
6 this.embeddedImagePath,
7 });
8 -
8 +
9 final int? version;
10 final String? heroTag;
11 final String data;
lib/entities/seed_phrase_length.dart
+1 -2
@@ -1,4 +1,3 @@
1 -
1 enum SeedPhraseLength {
2 twelveWords(12),
3 twentyFourWords(24);
@@ -22,4 +21,4 @@ enum SeedPhraseLength {
21 }
22 return label;
23 }
25 -}
\ No newline at end of file
24 +}
lib/entities/seed_type.dart
+2 -1
@@ -12,7 +12,8 @@ class MoneroSeedType extends EnumerableItem<int> with Serializable<int> {
12 static const defaultSeedType = polyseed;
13
14 static const legacy = MoneroSeedType(raw: 0, title: 'Legacy (25 words)', shortTitle: "Legacy");
15 - static const polyseed = MoneroSeedType(raw: 1, title: 'Polyseed (16 words)', shortTitle: "Polyseed");
15 + static const polyseed =
16 + MoneroSeedType(raw: 1, title: 'Polyseed (16 words)', shortTitle: "Polyseed");
17 static const wowneroSeed = MoneroSeedType(raw: 2, title: 'Wownero');
18 static const bip39 = MoneroSeedType(raw: 3, title: 'BIP39 (12 words)', shortTitle: "BIP39");
19
lib/entities/service_status.dart
+1 -2
@@ -28,8 +28,7 @@ class ServicesResponse {
28
29 ServicesResponse(this.servicesStatus, this.hasUpdates, this.currentSha);
30
31 - factory ServicesResponse.fromJson(
32 - Map<String, dynamic> json, bool hasUpdates, String currentSha) {
31 + factory ServicesResponse.fromJson(Map<String, dynamic> json, bool hasUpdates, String currentSha) {
32 return ServicesResponse(
33 (json['notices'] as List? ?? [])
34 .map((e) => ServiceStatus.fromJson(e as Map<String, dynamic>))
lib/entities/sort_balance_types.dart
+1 -1
@@ -16,4 +16,4 @@ enum SortBalanceBy {
16 return S.current.alphabetical;
17 }
18 }
19 -}
\ No newline at end of file
19 +}
lib/entities/template.part.dart
+1 -3
@@ -56,7 +56,5 @@ class TemplateAdapter extends TypeAdapter<Template> {
56 @override
57 bool operator ==(Object other) =>
58 identical(this, other) ||
59 - other is TemplateAdapter &&
60 - runtimeType == other.runtimeType &&
61 - typeId == other.typeId;
59 + other is TemplateAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
60 }
lib/entities/transaction_creation_credentials.dart
+1 -1
@@ -1 +1 @@
1 -abstract class TransactionCreationCredentials {}
\ No newline at end of file
1 +abstract class TransactionCreationCredentials {}
lib/entities/transaction_description.dart
+7 -6
@@ -5,7 +5,8 @@ part 'transaction_description.part.dart';
5
6 // @HiveType(typeId: TransactionDescription.typeId)
7 class TransactionDescription extends HiveObject {
8 - TransactionDescription({required this.id, this.recipientAddress, this.transactionNote, this.transactionKey});
8 + TransactionDescription(
9 + {required this.id, this.recipientAddress, this.transactionNote, this.transactionKey});
10
11 static const typeId = TRANSACTION_TYPE_ID;
12 static const boxName = 'TransactionDescriptions';
@@ -26,11 +27,11 @@ class TransactionDescription extends HiveObject {
27 String get note => transactionNote ?? '';
28
29 Map<String, dynamic> toJson() => {
29 - 'id': id,
30 - 'recipientAddress': recipientAddress,
31 - 'transactionNote': transactionNote,
32 - 'transactionKey': transactionKey,
33 - };
30 + 'id': id,
31 + 'recipientAddress': recipientAddress,
32 + 'transactionNote': transactionNote,
33 + 'transactionKey': transactionKey,
34 + };
35
36 factory TransactionDescription.fromJson(Map<String, dynamic> json) {
37 return TransactionDescription(
lib/entities/transaction_description.part.dart
+1 -2
@@ -6,8 +6,7 @@ part of 'transaction_description.dart';
6 // TypeAdapterGenerator
7 // **************************************************************************
8
9 -class TransactionDescriptionAdapter
10 - extends TypeAdapter<TransactionDescription> {
9 +class TransactionDescriptionAdapter extends TypeAdapter<TransactionDescription> {
10 @override
11 final int typeId = 2;
12
lib/entities/transaction_history.dart
+1 -2
@@ -2,8 +2,7 @@ import 'package:mobx/mobx.dart';
2 import 'package:cw_core/transaction_info.dart';
3
4 abstract class TransactionHistory {
5 - TransactionHistory()
6 - : transactions = Observable<List<TransactionInfo>>([]);
5 + TransactionHistory() : transactions = Observable<List<TransactionInfo>>([]);
6
7 Observable<List<TransactionInfo>> transactions;
8 Future<List<TransactionInfo>> getAll();
lib/entities/wallet_description.dart
+2 -2
@@ -2,7 +2,7 @@ import 'package:cw_core/wallet_type.dart';
2
3 class WalletDescription {
4 WalletDescription({required this.name, required this.type});
5 -
5 +
6 final String name;
7 final WalletType type;
8 -}
\ No newline at end of file
8 +}
lib/entities/wallet_manager.dart
+4 -4
@@ -165,11 +165,11 @@ class WalletManager {
165
166 String? getGroupName(WalletInfo walletInfo) {
167 try {
168 - final groupKey = _resolveGroupKey(walletInfo);
169 - final group = walletGroups.firstWhere((g) => g.groupKey == groupKey);
170 - return group.groupName;
168 + final groupKey = _resolveGroupKey(walletInfo);
169 + final group = walletGroups.firstWhere((g) => g.groupKey == groupKey);
170 + return group.groupName;
171 } catch (_) {
172 - return null;
172 + return null;
173 }
174 }
175 }
lib/entities/wallet_nft_response.dart
+1 -3
@@ -43,8 +43,7 @@ class NFTAssetModel {
43 name: json['name'] as String?,
44 symbol: json['symbol'] as String?,
45 normalizedMetadata: json['normalized_metadata'] != null
46 - ? new NormalizedMetadata.fromJson(
47 - json['normalized_metadata'] as Map<String, dynamic>)
46 + ? new NormalizedMetadata.fromJson(json['normalized_metadata'] as Map<String, dynamic>)
47 : null,
48 );
49 }
@@ -66,7 +65,6 @@ class NormalizedMetadata {
65 description: json['description'] as String?,
66 image: json['image'] as String?,
67 );
69 -
68 }
69
70 String? get imageUrl {
lib/exchange/exchange_provider_description.dart
+85 -33
@@ -2,47 +2,99 @@ import 'package:cw_core/enumerable_item.dart';
2
3 class ExchangeProviderDescription extends EnumerableItem<int> with Serializable<int> {
4 const ExchangeProviderDescription(
5 - {required String title, required int raw, required this.image, this.horizontalLogo = false, required this.isCentralized})
5 + {required String title,
6 + required int raw,
7 + required this.image,
8 + this.horizontalLogo = false,
9 + required this.isCentralized})
10 : super(title: title, raw: raw);
11
12 final bool horizontalLogo;
13 final String image;
14 final bool isCentralized;
15
12 - static const xmrto =
13 - ExchangeProviderDescription(title: 'XMR.TO', raw: 0, image: 'assets/new-ui/trade_providers/xmrto.svg', isCentralized: true);
14 - static const changeNow =
15 - ExchangeProviderDescription(title: 'ChangeNOW', raw: 1, image: 'assets/new-ui/trade_providers/changenow.svg', isCentralized: true);
16 - static const morphToken =
17 - ExchangeProviderDescription(title: 'MorphToken', raw: 2, image: 'assets/new-ui/trade_providers/morph.svg', isCentralized: true);
18 - static const sideShift =
19 - ExchangeProviderDescription(title: 'SideShift', raw: 3, image: 'assets/new-ui/trade_providers/sideshift.svg', isCentralized: true);
20 - static const simpleSwap =
21 - ExchangeProviderDescription(title: 'SimpleSwap', raw: 4, image: 'assets/new-ui/trade_providers/simpleswap.svg', isCentralized: true);
22 - static const trocador =
23 - ExchangeProviderDescription(title: 'Trocador', raw: 5, image: 'assets/new-ui/trade_providers/trocador.svg', isCentralized: true);
24 - static const exolix =
25 - ExchangeProviderDescription(title: 'Exolix', raw: 6, image: 'assets/new-ui/trade_providers/exolix.svg', isCentralized: true);
16 + static const xmrto = ExchangeProviderDescription(
17 + title: 'XMR.TO',
18 + raw: 0,
19 + image: 'assets/new-ui/trade_providers/xmrto.svg',
20 + isCentralized: true);
21 + static const changeNow = ExchangeProviderDescription(
22 + title: 'ChangeNOW',
23 + raw: 1,
24 + image: 'assets/new-ui/trade_providers/changenow.svg',
25 + isCentralized: true);
26 + static const morphToken = ExchangeProviderDescription(
27 + title: 'MorphToken',
28 + raw: 2,
29 + image: 'assets/new-ui/trade_providers/morph.svg',
30 + isCentralized: true);
31 + static const sideShift = ExchangeProviderDescription(
32 + title: 'SideShift',
33 + raw: 3,
34 + image: 'assets/new-ui/trade_providers/sideshift.svg',
35 + isCentralized: true);
36 + static const simpleSwap = ExchangeProviderDescription(
37 + title: 'SimpleSwap',
38 + raw: 4,
39 + image: 'assets/new-ui/trade_providers/simpleswap.svg',
40 + isCentralized: true);
41 + static const trocador = ExchangeProviderDescription(
42 + title: 'Trocador',
43 + raw: 5,
44 + image: 'assets/new-ui/trade_providers/trocador.svg',
45 + isCentralized: true);
46 + static const exolix = ExchangeProviderDescription(
47 + title: 'Exolix',
48 + raw: 6,
49 + image: 'assets/new-ui/trade_providers/exolix.svg',
50 + isCentralized: true);
51 static const all =
52 ExchangeProviderDescription(title: 'All trades', raw: 7, image: '', isCentralized: true);
28 - static const thorChain =
29 - ExchangeProviderDescription(title: 'ThorChain', raw: 8, image: 'assets/new-ui/trade_providers/thorchain.svg', isCentralized: true);
30 - static const swapTrade =
31 - ExchangeProviderDescription(title: 'SwapTrade', raw: 9, image: 'assets/new-ui/trade_providers/swaptrade.svg', isCentralized: true);
32 - static const letsExchange =
33 - ExchangeProviderDescription(title: 'LetsExchange', raw: 10, image: 'assets/new-ui/trade_providers/letsexchange.svg', isCentralized: true);
34 - static const stealthEx =
35 - ExchangeProviderDescription(title: 'StealthEx', raw: 11, image: 'assets/new-ui/trade_providers/stealthex.svg', isCentralized: true);
36 - static const chainflip =
37 - ExchangeProviderDescription(title: 'Chainflip', raw: 12, image: 'assets/new-ui/trade_providers/chainflip.svg', isCentralized: false);
38 - static const xoSwap =
39 - ExchangeProviderDescription(title: 'XOSwap', raw: 13, image: 'assets/new-ui/trade_providers/xoswap.svg', isCentralized: true);
40 - static const swapsXyz =
41 - ExchangeProviderDescription(title: 'Swaps.XYZ', raw: 14, image: 'assets/new-ui/trade_providers/swaps_xyz.svg', isCentralized: true);
42 - static const nearIntents =
43 - ExchangeProviderDescription(title: 'Near Intents', raw: 15, image: 'assets/new-ui/trade_providers/near-intents.svg', isCentralized: false);
44 - static const jupiter =
45 - ExchangeProviderDescription(title: 'Jupiter', raw: 16, image: 'assets/new-ui/trade_providers/jupiter.svg', isCentralized: false);
53 + static const thorChain = ExchangeProviderDescription(
54 + title: 'ThorChain',
55 + raw: 8,
56 + image: 'assets/new-ui/trade_providers/thorchain.svg',
57 + isCentralized: true);
58 + static const swapTrade = ExchangeProviderDescription(
59 + title: 'SwapTrade',
60 + raw: 9,
61 + image: 'assets/new-ui/trade_providers/swaptrade.svg',
62 + isCentralized: true);
63 + static const letsExchange = ExchangeProviderDescription(
64 + title: 'LetsExchange',
65 + raw: 10,
66 + image: 'assets/new-ui/trade_providers/letsexchange.svg',
67 + isCentralized: true);
68 + static const stealthEx = ExchangeProviderDescription(
69 + title: 'StealthEx',
70 + raw: 11,
71 + image: 'assets/new-ui/trade_providers/stealthex.svg',
72 + isCentralized: true);
73 + static const chainflip = ExchangeProviderDescription(
74 + title: 'Chainflip',
75 + raw: 12,
76 + image: 'assets/new-ui/trade_providers/chainflip.svg',
77 + isCentralized: false);
78 + static const xoSwap = ExchangeProviderDescription(
79 + title: 'XOSwap',
80 + raw: 13,
81 + image: 'assets/new-ui/trade_providers/xoswap.svg',
82 + isCentralized: true);
83 + static const swapsXyz = ExchangeProviderDescription(
84 + title: 'Swaps.XYZ',
85 + raw: 14,
86 + image: 'assets/new-ui/trade_providers/swaps_xyz.svg',
87 + isCentralized: true);
88 + static const nearIntents = ExchangeProviderDescription(
89 + title: 'Near Intents',
90 + raw: 15,
91 + image: 'assets/new-ui/trade_providers/near-intents.svg',
92 + isCentralized: false);
93 + static const jupiter = ExchangeProviderDescription(
94 + title: 'Jupiter',
95 + raw: 16,
96 + image: 'assets/new-ui/trade_providers/jupiter.svg',
97 + isCentralized: false);
98
99 static ExchangeProviderDescription deserialize({required int raw}) {
100 switch (raw) {
lib/exchange/provider/chainflip_exchange_provider.dart
+35 -40
@@ -31,7 +31,7 @@ class ChainflipExchangeProvider extends ExchangeProvider {
31 CryptoCurrency.usdtArb,
32 CryptoCurrency.trx,
33 CryptoCurrency.usdttrc20,
34 - ];
34 + ];
35
36 static const _baseURL = 'chainflip-broker.io';
37 static const _assetsPath = '/assets';
@@ -57,8 +57,7 @@ class ChainflipExchangeProvider extends ExchangeProvider {
57 bool get supportsMemoOrDestinationTag => false;
58
59 @override
60 - ExchangeProviderDescription get description =>
61 - ExchangeProviderDescription.chainflip;
60 + ExchangeProviderDescription get description => ExchangeProviderDescription.chainflip;
61
62 @override
63 Future<bool> checkIsAvailable() async => true;
@@ -68,25 +67,23 @@ class ChainflipExchangeProvider extends ExchangeProvider {
67 {required CryptoCurrency from,
68 required CryptoCurrency to,
69 required bool isFixedRateMode}) async {
71 -
70 try {
73 -
74 - if(!_supported.contains(from) || !_supported.contains(to)) {
71 + if (!_supported.contains(from) || !_supported.contains(to)) {
72 throw Exception('No rates found for $from to $to');
73 }
74
78 - final assetId = _normalizeCurrency(from);
75 + final assetId = _normalizeCurrency(from);
76
80 - final assetsResponse = await _getAssets();
81 - final assets = assetsResponse['assets'] as List<dynamic>;
77 + final assetsResponse = await _getAssets();
78 + final assets = assetsResponse['assets'] as List<dynamic>;
79
83 - final minAmount = assets.firstWhere(
84 - (asset) => asset['id'] == assetId,
85 - orElse: () => null)?['minimalAmountNative'] ?? '0';
80 + final minAmount = assets.firstWhere((asset) => asset['id'] == assetId,
81 + orElse: () => null)?['minimalAmountNative'] ??
82 + '0';
83
87 - if (minAmount == '0') throw Exception('No rates found for $from to $to');
84 + if (minAmount == '0') throw Exception('No rates found for $from to $to');
85
89 - return Limits(min: _amountFromNative(minAmount.toString(), from));
86 + return Limits(min: _amountFromNative(minAmount.toString(), from));
87 } catch (e) {
88 printV(e.toString());
89 throw Exception('Chainflip failed to fetch limits');
@@ -94,20 +91,18 @@ class ChainflipExchangeProvider extends ExchangeProvider {
91 }
92
93 @override
97 - Future<double> fetchRate({
98 - required CryptoCurrency from,
99 - required CryptoCurrency to,
100 - required double amount,
101 - required bool isFixedRateMode,
102 - required bool isReceiveAmount
103 - }) async {
94 + Future<double> fetchRate(
95 + {required CryptoCurrency from,
96 + required CryptoCurrency to,
97 + required double amount,
98 + required bool isFixedRateMode,
99 + required bool isReceiveAmount}) async {
100 // TODO: It seems this rate is getting cached, and re-used for different amounts, can we not do this?
101
102 try {
103 if (amount == 0) return 0.0;
104
109 - if(!_supported.contains(from) || !_supported.contains(to)) return 0.0;
110 -
105 + if (!_supported.contains(from) || !_supported.contains(to)) return 0.0;
106
107 final quoteParams = {
108 'apiKey': _affiliateKey,
@@ -119,8 +114,7 @@ class ChainflipExchangeProvider extends ExchangeProvider {
114
115 final quoteResponse = await _getSwapQuote(quoteParams);
116
122 - final expectedAmountOut =
123 - quoteResponse['egressAmountNative'] as String? ?? '0';
117 + final expectedAmountOut = quoteResponse['egressAmountNative'] as String? ?? '0';
118
119 final rate = _amountFromNative(expectedAmountOut, to) / amount;
120
@@ -194,7 +188,8 @@ class ChainflipExchangeProvider extends ExchangeProvider {
188 'retryDurationInBlocks': '150'
189 };
190
197 - if (quoteResponse.containsKey('numberOfChunks') && quoteResponse.containsKey('chunkIntervalBlocks')) {
191 + if (quoteResponse.containsKey('numberOfChunks') &&
192 + quoteResponse.containsKey('chunkIntervalBlocks')) {
193 swapParams.addAll({
194 'numberOfChunks': quoteResponse['numberOfChunks'].toString(),
195 'chunkIntervalBlocks': quoteResponse['chunkIntervalBlocks'].toString(),
@@ -203,7 +198,8 @@ class ChainflipExchangeProvider extends ExchangeProvider {
198
199 final swapResponse = await _openDepositChannel(swapParams);
200
206 - final id = '${swapResponse['issuedBlock']}-${swapResponse['network'].toString()}-${swapResponse['channelId']}';
201 + final id =
202 + '${swapResponse['issuedBlock']}-${swapResponse['network'].toString()}-${swapResponse['channelId']}';
203
204 ExchangeProviderLogger.logSuccess(
205 provider: description,
@@ -280,8 +276,7 @@ class ChainflipExchangeProvider extends ExchangeProvider {
276
277 final statusResponse = await _getStatus(statusParams);
278
283 - if (statusResponse == null)
284 - throw Exception('Trade not found for id: $id');
279 + if (statusResponse == null) throw Exception('Trade not found for id: $id');
280
281 final status = statusResponse['status'];
282 final currentState = _determineState(status['state'].toString());
@@ -294,7 +289,7 @@ class ChainflipExchangeProvider extends ExchangeProvider {
289
290 final from = status['sourceAsset'].toString();
291 final to = status['destinationAsset'].toString();
297 -
292 +
293 final newTrade = Trade(
294 id: id,
295 from: _toCurrency(from),
@@ -304,8 +299,7 @@ class ChainflipExchangeProvider extends ExchangeProvider {
299 receiveAmount: amount,
300 state: currentState,
301 payoutAddress: status['destinationAddress'].toString(),
307 - outputTransaction:
308 - status['swapEgress']?['transactionReference']?.toString(),
302 + outputTransaction: status['swapEgress']?['transactionReference']?.toString(),
303 isRefund: isRefund,
304 );
305
@@ -331,7 +325,7 @@ class ChainflipExchangeProvider extends ExchangeProvider {
325 return '$title.$tag';
326 }
327
334 - String _normalizeNetworkName (String name) {
328 + String _normalizeNetworkName(String name) {
329 final networkName = switch (name) {
330 'BITCOIN' => 'Bitcoin',
331 'ETHEREUM' => 'Ethereum',
@@ -344,7 +338,6 @@ class ChainflipExchangeProvider extends ExchangeProvider {
338 return networkName;
339 }
340
347 -
341 CryptoCurrency? _toCurrency(String name) {
342 final currency = switch (name) {
343 'btc.btc' => CryptoCurrency.btc,
@@ -372,8 +365,7 @@ class ChainflipExchangeProvider extends ExchangeProvider {
365 double _amountFromNative(String amount, CryptoCurrency currency) =>
366 double.parse(amount) / pow(10, currency.decimals);
367
375 - Future<Map<String, dynamic>> _getAssets() async =>
376 - _getRequest(_assetsPath, {});
368 + Future<Map<String, dynamic>> _getAssets() async => _getRequest(_assetsPath, {});
369
370 Future<Map<String, dynamic>> _openDepositChannel(Map<String, String> params) async =>
371 _getRequest(_swapPath, params);
@@ -384,7 +376,8 @@ class ChainflipExchangeProvider extends ExchangeProvider {
376 final response = await ProxyWrapper().get(clearnetUri: uri);
377
378 if ((response.statusCode != 200) || (response.body.contains('error'))) {
387 - throw Exception('Unexpected response: ${response.statusCode} / ${uri.toString()} / ${response.body}');
379 + throw Exception(
380 + 'Unexpected response: ${response.statusCode} / ${uri.toString()} / ${response.body}');
381 }
382
383 return json.decode(response.body) as Map<String, dynamic>;
@@ -396,12 +389,13 @@ class ChainflipExchangeProvider extends ExchangeProvider {
389 final response = await ProxyWrapper().get(clearnetUri: uri);
390
391 if ((response.statusCode != 200) || (response.body.contains('error'))) {
399 - throw Exception('Unexpected response: ${response.statusCode} / ${uri.toString()} / ${response.body}');
392 + throw Exception(
393 + 'Unexpected response: ${response.statusCode} / ${uri.toString()} / ${response.body}');
394 }
395
396 final List<dynamic> jsonList = json.decode(response.body) as List<dynamic>;
397 final List<Map<String, dynamic>> quotes =
404 - jsonList.map((e) => e as Map<String, dynamic>).toList();
398 + jsonList.map((e) => e as Map<String, dynamic>).toList();
399
400 Map<String, dynamic> highestQuote = quotes.reduce((current, next) {
401 double currentAmount = current['egressAmount'] as double;
@@ -421,7 +415,8 @@ class ChainflipExchangeProvider extends ExchangeProvider {
415 if (response.statusCode == 404) return null;
416
417 if ((response.statusCode != 200) || (response.body.contains('error'))) {
424 - throw Exception('Unexpected response: ${response.statusCode} / ${uri.toString()} / ${response.body}');
418 + throw Exception(
419 + 'Unexpected response: ${response.statusCode} / ${uri.toString()} / ${response.body}');
420 }
421
422 return json.decode(response.body) as Map<String, dynamic>;
lib/exchange/provider/exolix_exchange_provider.dart
+21 -25
@@ -69,8 +69,7 @@ class ExolixExchangeProvider extends ExchangeProvider {
69 for (int i = 0; i < 2; i++) {
70 final uri = Uri.https(apiBaseUrl, ratePath, params);
71 final response = await ProxyWrapper().get(clearnetUri: uri);
72 -
73 -
72 +
73 if (response.statusCode == 200) {
74 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
75 final minAmount = responseJSON['minAmount'];
@@ -92,13 +91,12 @@ class ExolixExchangeProvider extends ExchangeProvider {
91 }
92
93 @override
95 - Future<double> fetchRate({
96 - required CryptoCurrency from,
97 - required CryptoCurrency to,
98 - required double amount,
99 - required bool isFixedRateMode,
100 - required bool isReceiveAmount
101 - }) async {
94 + Future<double> fetchRate(
95 + {required CryptoCurrency from,
96 + required CryptoCurrency to,
97 + required double amount,
98 + required bool isFixedRateMode,
99 + required bool isReceiveAmount}) async {
100 try {
101 if (amount == 0) return 0.0;
102
@@ -118,12 +116,12 @@ class ExolixExchangeProvider extends ExchangeProvider {
116
117 final uri = Uri.https(apiBaseUrl, ratePath, params);
118 final response = await ProxyWrapper().get(clearnetUri: uri);
121 -
119 +
120 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
121
122 if (response.statusCode != 200) {
123 final message = responseJSON['message'] as String?;
126 -
124 +
125 ExchangeProviderLogger.logError(
126 provider: description,
127 function: 'fetchRate',
@@ -139,7 +137,7 @@ class ExolixExchangeProvider extends ExchangeProvider {
137 'url': uri.toString(),
138 },
139 );
142 -
140 +
141 throw Exception(message);
142 }
143
@@ -194,12 +192,12 @@ class ExolixExchangeProvider extends ExchangeProvider {
192 final headers = {'Content-Type': 'application/json'};
193 final body = {
194 'coinFrom': _normalizeCurrency(_overrideFromCryptoCurrency(request.fromCurrency)),
197 - 'coinTo': _normalizeCurrency(_overrideToCryptoCurrency(request.toCurrency, request.toAddress)),
195 + 'coinTo':
196 + _normalizeCurrency(_overrideToCryptoCurrency(request.toCurrency, request.toAddress)),
197 'networkFrom': _networkFor(request.fromCurrency),
198 'networkTo': _networkFor(request.toCurrency),
199 'withdrawalAddress': await _normalizeAddress(request.toAddress),
201 - if (request.toAddressExtraId.isNotEmpty)
202 - 'withdrawalExtraId': request.toAddressExtraId,
200 + if (request.toAddressExtraId.isNotEmpty) 'withdrawalExtraId': request.toAddressExtraId,
201 'refundAddress': await _normalizeAddress(request.refundAddress),
202 'rateType': _getRateType(isFixedRateMode),
203 'apiToken': apiKey,
@@ -221,7 +219,7 @@ class ExolixExchangeProvider extends ExchangeProvider {
219 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
220 final errors = responseJSON['error'] as Map<String, String>;
221 final errorMessage = errors.values.join(', ');
224 -
222 +
223 ExchangeProviderLogger.logError(
224 provider: description,
225 function: 'createTrade',
@@ -240,7 +238,7 @@ class ExolixExchangeProvider extends ExchangeProvider {
238 'url': uri.toString(),
239 },
240 );
243 -
241 +
242 throw Exception(errorMessage);
243 }
244
@@ -326,7 +324,7 @@ class ExolixExchangeProvider extends ExchangeProvider {
324 final findTradeByIdPath = '$transactionsPath/$id';
325 final uri = Uri.https(apiBaseUrl, findTradeByIdPath);
326 final response = await ProxyWrapper().get(clearnetUri: uri);
329 -
327 +
328 if (response.statusCode == 404) throw TradeNotFoundException(id, provider: description);
329
330 if (response.statusCode == 400) {
@@ -346,7 +344,8 @@ class ExolixExchangeProvider extends ExchangeProvider {
344 final coinFrom = responseJSON['coinFrom']['coinCode'] as String;
345 final coinFromNetwork = responseJSON['coinFrom']['network'] as String?;
346 final _normalizedFromNetwork = _normalizeNetworkType(coinFromNetwork ?? '');
349 - final fromTag = coinFrom.toUpperCase() == _normalizedFromNetwork.toUpperCase() ? null : coinFromNetwork;
347 + final fromTag =
348 + coinFrom.toUpperCase() == _normalizedFromNetwork.toUpperCase() ? null : coinFromNetwork;
349 final from = CryptoCurrency.safeParseCurrencyFromString(coinFrom, tag: fromTag);
350
351 // Parsing 'to' currency
@@ -438,7 +437,7 @@ class ExolixExchangeProvider extends ExchangeProvider {
437 switch (tag) {
438 case 'POLY':
439 return 'Polygon';
441 - case 'ARB':
440 + case 'ARB':
441 return 'Arbitrum';
442 default:
443 return tag;
@@ -446,17 +445,14 @@ class ExolixExchangeProvider extends ExchangeProvider {
445 }
446
447 Future<String> _normalizeAddress(String address) async {
449 - if (address.startsWith('bitcoincash:'))
450 - return address.replaceFirst('bitcoincash:', '');
448 + if (address.startsWith('bitcoincash:')) return address.replaceFirst('bitcoincash:', '');
449
450 // Lightning addresses
453 - if(address.contains("@"))
454 - return await getBolt11FromLightingAddress(address) ?? address;
451 + if (address.contains("@")) return await getBolt11FromLightingAddress(address) ?? address;
452
453 return address;
454 }
455
459 -
456 static double? _toDouble(dynamic value) {
457 if (value is int) {
458 return value.toDouble();
lib/exchange/provider/jupiter_exchange_provider.dart
+1 -2
@@ -226,8 +226,7 @@ class JupiterExchangeProvider extends ExchangeProvider {
226 }) async {
227 try {
228 // must support both
229 - if (!_isSolanaCurrency(request.fromCurrency) ||
230 - !_isSolanaCurrency(request.toCurrency)) {
229 + if (!_isSolanaCurrency(request.fromCurrency) || !_isSolanaCurrency(request.toCurrency)) {
230 throw 'not supported currencies';
231 }
232
lib/exchange/provider/near_Intents_exchange_provider.dart
+27 -48
@@ -92,8 +92,7 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
92 bool get supportsMemoOrDestinationTag => false;
93
94 @override
95 - ExchangeProviderDescription get description =>
96 - ExchangeProviderDescription.nearIntents;
95 + ExchangeProviderDescription get description => ExchangeProviderDescription.nearIntents;
96
97 @override
98 Future<bool> checkIsAvailable() async => true;
@@ -132,8 +131,8 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
131 throw Exception('fetchRate: Unsupported currency pair');
132 }
133
135 - final formattedAmount = AmountConverter.toBaseUnits(amount.toString(),
136 - isFixedRateMode ? destinationToken.decimals : originToken.decimals);
134 + final formattedAmount = AmountConverter.toBaseUnits(
135 + amount.toString(), isFixedRateMode ? destinationToken.decimals : originToken.decimals);
136
137 final dummyAddrFrom = getNearDummyAddress(from);
138 final dummyAddrTo = getNearDummyAddress(to);
@@ -156,10 +155,8 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
155 }
156
157 final q = quote['quote'] as Map<String, dynamic>;
159 - final amountIn =
160 - double.tryParse(q['amountInFormatted']?.toString() ?? '0') ?? 0.0;
161 - final amountOut =
162 - double.tryParse(q['amountOutFormatted']?.toString() ?? '0') ?? 0.0;
158 + final amountIn = double.tryParse(q['amountInFormatted']?.toString() ?? '0') ?? 0.0;
159 + final amountOut = double.tryParse(q['amountOutFormatted']?.toString() ?? '0') ?? 0.0;
160
161 if (amountIn == 0) return 0.0;
162
@@ -214,24 +211,21 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
211 try {
212 final tokens = await _geSupportedTokens();
213 final originToken = currencyToNearAssetId(request.fromCurrency, tokens);
217 - final destinationToken =
218 - currencyToNearAssetId(request.toCurrency, tokens);
214 + final destinationToken = currencyToNearAssetId(request.toCurrency, tokens);
215
216 if (originToken == null || destinationToken == null) {
217 throw Exception('Unsupported currency pair');
218 }
219
224 - final rawAmountStr =
225 - isFixedRateMode ? request.toAmount : request.fromAmount;
220 + final rawAmountStr = isFixedRateMode ? request.toAmount : request.fromAmount;
221
222 final baseAmount = AmountConverter.toBaseUnits(
223 rawAmountStr,
229 - isFixedRateMode
230 - ? request.toCurrency.decimals
231 - : request.fromCurrency.decimals,
224 + isFixedRateMode ? request.toCurrency.decimals : request.fromCurrency.decimals,
225 );
226
234 - final depositMode = _memoRequiredCurrencies.contains(request.fromCurrency) ? "MEMO" : "SIMPLE";
227 + final depositMode =
228 + _memoRequiredCurrencies.contains(request.fromCurrency) ? "MEMO" : "SIMPLE";
229
230 final quote = await getSwapQuote(
231 dry: false,
@@ -271,11 +265,9 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
265 throw Exception('Failed to parse to currency from assetId: $toAssetId');
266 }
267
274 - final from = CryptoCurrency.safeParseCurrencyFromString(fromCurrency.$1,
275 - tag: fromCurrency.$2);
276 - final to = CryptoCurrency.safeParseCurrencyFromString(toCurrency.$1,
277 - tag: toCurrency.$2);
278 -
268 + final from =
269 + CryptoCurrency.safeParseCurrencyFromString(fromCurrency.$1, tag: fromCurrency.$2);
270 + final to = CryptoCurrency.safeParseCurrencyFromString(toCurrency.$1, tag: toCurrency.$2);
271
272 final trade = Trade(
273 id: depositAddress,
@@ -345,8 +337,7 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
337 final param = {'depositAddress': id};
338 final uri = Uri.https(_baseUrl, '$_versionPath$_statusPath', param);
339
348 - final response =
349 - await ProxyWrapper().get(clearnetUri: uri, headers: _headers);
340 + final response = await ProxyWrapper().get(clearnetUri: uri, headers: _headers);
341
342 if (response.statusCode != 200) {
343 throw Exception(
@@ -358,16 +349,14 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
349 final statusRaw = (data['status'] as String?) ?? 'UNKNOWN';
350
351 final quoteResponse = data['quoteResponse'] as Map<String, dynamic>? ?? {};
361 - final quoteRequest =
362 - quoteResponse['quoteRequest'] as Map<String, dynamic>? ?? {};
352 + final quoteRequest = quoteResponse['quoteRequest'] as Map<String, dynamic>? ?? {};
353
354 final refundTo = quoteRequest['refundTo'] as String? ?? '';
355 final recipient = quoteRequest['recipient'] as String? ?? '';
356
357 // Parsing 'from' currency
358 final originAssetId = quoteRequest['originAsset'] as String? ?? '';
369 - final from =
370 - _nearAssetIdToCurrency(originAssetId, await _geSupportedTokens());
359 + final from = _nearAssetIdToCurrency(originAssetId, await _geSupportedTokens());
360
361 CryptoCurrency? coinFrom;
362 CryptoCurrency? coinTo;
@@ -377,11 +366,9 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
366 }
367
368 // Parsing 'to' currency
380 - final destinationAssetId =
381 - quoteRequest['destinationAsset'] as String? ?? '';
369 + final destinationAssetId = quoteRequest['destinationAsset'] as String? ?? '';
370
383 - final to =
384 - _nearAssetIdToCurrency(destinationAssetId, await _geSupportedTokens());
371 + final to = _nearAssetIdToCurrency(destinationAssetId, await _geSupportedTokens());
372
373 if (to != null) {
374 coinTo = CryptoCurrency.safeParseCurrencyFromString(to.$1, tag: to.$2);
@@ -393,16 +380,13 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
380 final depositAddress = quote['depositAddress'] as String?;
381 final depositMemo = quote['depositMemo'] as String?;
382
396 - final depositAmount = swap['amountInFormatted']?.toString() ??
397 - quote['amountInFormatted']?.toString() ??
398 - '0';
383 + final depositAmount =
384 + swap['amountInFormatted']?.toString() ?? quote['amountInFormatted']?.toString() ?? '0';
385
400 - final receiveAmount = swap['amountOutFormatted']?.toString() ??
401 - quote['amountOutFormatted']?.toString();
386 + final receiveAmount =
387 + swap['amountOutFormatted']?.toString() ?? quote['amountOutFormatted']?.toString();
388
403 - final originTxHash = (swap['originChainTxHashes'] as List?)
404 - ?.firstOrNull?['hash']
405 - ?.toString();
389 + final originTxHash = (swap['originChainTxHashes'] as List?)?.firstOrNull?['hash']?.toString();
390
391 return Trade(
392 id: id,
@@ -487,8 +471,7 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
471 "deadline": _isoUtcDeadline,
472 if (connectedWallets != null) "connectedWallets": connectedWallets,
473 if (sessionId != null) "sessionId": sessionId,
490 - if (virtualChainRecipient != null)
491 - "virtualChainRecipient": virtualChainRecipient,
474 + if (virtualChainRecipient != null) "virtualChainRecipient": virtualChainRecipient,
475 if (virtualChainRefundRecipient != null)
476 "virtualChainRefundRecipient": virtualChainRefundRecipient,
477 if (customRecipientMsg != null) "customRecipientMsg": customRecipientMsg,
@@ -568,24 +551,20 @@ class NearIntentsExchangeProvider extends ExchangeProvider {
551 return token;
552 }
553
571 - (String, String?)? _nearAssetIdToCurrency(
572 - String assetId, List<Token> supported) {
554 + (String, String?)? _nearAssetIdToCurrency(String assetId, List<Token> supported) {
555 if (supported.isEmpty) return null;
556
557 final token = supported.firstWhereOrNull((t) => t.assetId == assetId);
558
559 if (token == null) return null;
560
579 - final title = token.symbol.toUpperCase()
580 - .replaceAll(RegExp(r'\s*\([^)]*\)'), '');
561 + final title = token.symbol.toUpperCase().replaceAll(RegExp(r'\s*\([^)]*\)'), '');
562
563 final normalizedNetwork = _normalizeNearBlockchainToTag(token.blockchain);
564
565 final isNativeAsset = assetId.contains(':native:coin');
566
586 - final tag = isNativeAsset || normalizedNetwork == title
587 - ? null
588 - : normalizedNetwork;
567 + final tag = isNativeAsset || normalizedNetwork == title ? null : normalizedNetwork;
568
569 return (title, tag);
570 }
lib/exchange/provider/sideshift_exchange_provider.dart
+9 -13
@@ -44,7 +44,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
44 const url = apiBaseUrl + permissionPath;
45 final uri = Uri.parse(url);
46 final response = await ProxyWrapper().get(clearnetUri: uri);
47 -
47 +
48 if (response.statusCode == 500) {
49 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
50 final error = responseJSON['error']['message'] as String;
@@ -74,7 +74,6 @@ class SideShiftExchangeProvider extends ExchangeProvider {
74
75 final uri = Uri.parse(url);
76 final response = await ProxyWrapper().get(clearnetUri: uri);
77 -
77
78 if (response.statusCode == 500) {
79 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
@@ -103,13 +102,12 @@ class SideShiftExchangeProvider extends ExchangeProvider {
102 }
103
104 @override
106 - Future<double> fetchRate({
107 - required CryptoCurrency from,
108 - required CryptoCurrency to,
109 - required double amount,
110 - required bool isFixedRateMode,
111 - required bool isReceiveAmount
112 - }) async {
105 + Future<double> fetchRate(
106 + {required CryptoCurrency from,
107 + required CryptoCurrency to,
108 + required double amount,
109 + required bool isFixedRateMode,
110 + required bool isReceiveAmount}) async {
111 try {
112 if (amount == 0) return 0.0;
113
@@ -123,7 +121,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
121
122 final uri = Uri.parse(url);
123 final response = await ProxyWrapper().get(clearnetUri: uri);
126 -
124 +
125 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
126
127 if (response.statusCode == 500) {
@@ -240,7 +238,6 @@ class SideShiftExchangeProvider extends ExchangeProvider {
238 headers: headers,
239 body: json.encode(body),
240 );
243 -
241
242 if (response.statusCode != 201) {
243 if (response.statusCode == 400) {
@@ -346,7 +343,7 @@ class SideShiftExchangeProvider extends ExchangeProvider {
343 final url = apiBaseUrl + orderPath + '/' + id;
344 final uri = Uri.parse(url);
345 final response = await ProxyWrapper().get(clearnetUri: uri);
349 -
346 +
347 if (response.statusCode == 404) {
348 throw TradeNotFoundException(id, provider: description);
349 }
@@ -415,7 +412,6 @@ class SideShiftExchangeProvider extends ExchangeProvider {
412 headers: headers,
413 body: json.encode(body),
414 );
418 -
415
416 if (response.statusCode != 201) {
417 if (response.statusCode == 400) {
lib/exchange/provider/simpleswap_exchange_provider.dart
+9 -16
@@ -17,7 +17,6 @@ import 'package:cake_wallet/utils/exchange_provider_logger.dart';
17 class SimpleSwapExchangeProvider extends ExchangeProvider {
18 SimpleSwapExchangeProvider();
19
20 -
20 static final apiKey =
21 DeviceInfo.instance.isMobile ? secrets.simpleSwapApiKey : secrets.simpleSwapApiKeyDesktop;
22 static const apiAuthority = 'api.simpleswap.io';
@@ -63,7 +62,6 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
62 final uri = Uri.https(apiAuthority, rangePath, params);
63
64 final response = await ProxyWrapper().get(clearnetUri: uri);
66 -
65
66 if (response.statusCode == 500) {
67 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
@@ -84,13 +82,12 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
82 }
83
84 @override
87 - Future<double> fetchRate({
88 - required CryptoCurrency from,
89 - required CryptoCurrency to,
90 - required double amount,
91 - required bool isFixedRateMode,
92 - required bool isReceiveAmount
93 - }) async {
85 + Future<double> fetchRate(
86 + {required CryptoCurrency from,
87 + required CryptoCurrency to,
88 + required double amount,
89 + required bool isFixedRateMode,
90 + required bool isReceiveAmount}) async {
91 try {
92 if (amount == 0) return 0.0;
93
@@ -103,7 +100,6 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
100 };
101 final uri = Uri.https(apiAuthority, getEstimatePath, params);
102 final response = await ProxyWrapper().get(clearnetUri: uri);
106 -
103
104 if (response.body == "null") {
105 ExchangeProviderLogger.logError(
@@ -123,7 +119,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
119 );
120 return 0.00;
121 }
126 -
122 +
123 final data = json.decode(response.body) as String;
124 final rate = double.parse(data) / amount;
125
@@ -190,7 +186,6 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
186 headers: headers,
187 body: json.encode(body),
188 );
193 -
189
190 if (response.statusCode != 200 && response.statusCode != 201) {
191 if (response.statusCode == 400) {
@@ -299,8 +294,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
294 final params = {'api_key': apiKey, 'id': id};
295 final uri = Uri.https(apiAuthority, getExchangePath, params);
296 final response = await ProxyWrapper().get(clearnetUri: uri);
302 -
303 -
297 +
298 if (response.statusCode == 404) {
299 throw TradeNotFoundException(id, provider: description);
300 }
@@ -325,8 +319,7 @@ class SimpleSwapExchangeProvider extends ExchangeProvider {
319 final status = responseJSON['status'] as String;
320 final payoutAddress = responseJSON['address_to'] as String;
321
328 - final fromParsed =
329 - CryptoCurrency.safeParseCurrencyFromString(fromCurrency);
322 + final fromParsed = CryptoCurrency.safeParseCurrencyFromString(fromCurrency);
323 final toParsed = CryptoCurrency.safeParseCurrencyFromString(toCurrency);
324 return Trade(
325 id: id,
lib/exchange/provider/swapsxyz_exchange_provider.dart
+35 -68
@@ -19,7 +19,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
19 static final List<CryptoCurrency> _notSupportedAsSourceToken = [
20 CryptoCurrency.sol,
21 ...CryptoCurrency.all.where(
22 - (c) => (c.tag ?? '').toUpperCase() == 'SOL' || c.tag == CryptoCurrency.bnb.tag,
22 + (c) => (c.tag ?? '').toUpperCase() == 'SOL' || c.tag == CryptoCurrency.bnb.tag,
23 ),
24 ];
25
@@ -58,8 +58,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
58 bool get supportsMemoOrDestinationTag => false;
59
60 @override
61 - ExchangeProviderDescription get description =>
62 - ExchangeProviderDescription.swapsXyz;
61 + ExchangeProviderDescription get description => ExchangeProviderDescription.swapsXyz;
62
63 @override
64 Future<bool> checkIsAvailable() async => true;
@@ -101,8 +100,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
100
101 final body = json.decode(res.body) as Map<String, dynamic>;
102
104 - final paths =
105 - (body['paths'] as List? ?? const []).cast<Map<String, dynamic>>();
103 + final paths = (body['paths'] as List? ?? const []).cast<Map<String, dynamic>>();
104 if (paths.isEmpty) {
105 throw Exception('No paths for ${fromToUse.title} -> ${toToUse.title}');
106 }
@@ -121,18 +119,14 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
119 );
120 }
121
124 - final supportsExactAmountIn =
125 - path['supportsExactAmountIn'] as bool? ?? false;
126 - final supportsExactAmountOut =
127 - path['supportsExactAmountOut'] as bool? ?? false;
122 + final supportsExactAmountIn = path['supportsExactAmountIn'] as bool? ?? false;
123 + final supportsExactAmountOut = path['supportsExactAmountOut'] as bool? ?? false;
124
125 if (isFixedRateMode && !supportsExactAmountOut) {
130 - throw Exception(
131 - 'This route does not support fixed receive (exact-amount-out)');
126 + throw Exception('This route does not support fixed receive (exact-amount-out)');
127 }
128 if (!isFixedRateMode && !supportsExactAmountIn) {
134 - throw Exception(
135 - 'This route does not support exact send (exact-amount-in)');
129 + throw Exception('This route does not support exact send (exact-amount-in)');
130 }
131
132 Map<String, dynamic>? useLimits;
@@ -192,8 +186,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
186 final res = await ProxyWrapper().get(clearnetUri: uri, headers: _headers);
187 if (res.statusCode != 200) return null;
188 final body = json.decode(res.body) as Map<String, dynamic>;
195 - final paths =
196 - (body['paths'] as List?)?.cast<Map<String, dynamic>>() ?? const [];
189 + final paths = (body['paths'] as List?)?.cast<Map<String, dynamic>>() ?? const [];
190 if (paths.isEmpty) return null;
191 final p = paths.first;
192 return _PathInfo(
@@ -210,23 +203,18 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
203 required bool isFixedRateMode,
204 required bool isReceiveAmount}) async {
205 try {
213 -
214 - if(_notSupportedAsSourceToken.contains(from) || _notSupportedAsSourceToken.contains(to)) {
215 - printV(
216 - 'fetchRate: source token ${from.title} is not supported as source token');
206 + if (_notSupportedAsSourceToken.contains(from) || _notSupportedAsSourceToken.contains(to)) {
207 + printV('fetchRate: source token ${from.title} is not supported as source token');
208 return 0.0;
209 }
210
220 -
221 -
211 final chains = await _geSupportedChain();
212 if (chains.isEmpty) return 0.0;
213
214 final srcChain = _findChainByCurrency(from, chains);
215 final dstChain = _findChainByCurrency(to, chains);
216
228 - await _ensureTokensCached(
229 - fromChain: srcChain, toChain: dstChain, from: from, to: to);
217 + await _ensureTokensCached(fromChain: srcChain, toChain: dstChain, from: from, to: to);
218
219 final srcToken = _getTokenAddress(currency: from, chain: srcChain);
220 final dstToken = _getTokenAddress(currency: to, chain: dstChain);
@@ -252,8 +240,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
240 );
241
242 final params = {
255 - 'swapDirection':
256 - isReceiveAmount ? 'exact-amount-out' : 'exact-amount-in',
243 + 'swapDirection': isReceiveAmount ? 'exact-amount-out' : 'exact-amount-in',
244 'srcToken': srcToken,
245 'dstToken': dstToken,
246 'srcChainId': '${srcChain.chainId}',
@@ -262,8 +249,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
249 };
250
251 final uri = Uri.https(_baseUrl, _getQuotePaths, params);
265 - final response =
266 - await ProxyWrapper().get(clearnetUri: uri, headers: _headers);
252 + final response = await ProxyWrapper().get(clearnetUri: uri, headers: _headers);
253
254 if (response.statusCode != 200) {
255 printV('fetchRate failed: ${response.body}');
@@ -289,8 +275,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
275 final sender = request.refundAddress.trim();
276 final recipient = request.toAddress.trim();
277 if (sender.isEmpty || recipient.isEmpty) {
292 - throw Exception(
293 - 'Sender (refundAddress) or recipient (toAddress) is empty');
278 + throw Exception('Sender (refundAddress) or recipient (toAddress) is empty');
279 }
280
281 final chains = await _geSupportedChain();
@@ -305,10 +290,8 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
290 to: request.toCurrency,
291 );
292
308 - final srcToken =
309 - _getTokenAddress(currency: request.fromCurrency, chain: srcChain);
310 - final dstToken =
311 - _getTokenAddress(currency: request.toCurrency, chain: dstChain);
293 + final srcToken = _getTokenAddress(currency: request.fromCurrency, chain: srcChain);
294 + final dstToken = _getTokenAddress(currency: request.toCurrency, chain: dstChain);
295
296 final amountStr = isFixedRateMode ? request.toAmount : request.fromAmount;
297 final rawAmount = double.tryParse(amountStr) ?? 0.0;
@@ -316,9 +299,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
299
300 final formattedAmount = AmountConverter.toBaseUnits(
301 amountStr,
319 - isFixedRateMode
320 - ? request.toCurrency.decimals
321 - : request.fromCurrency.decimals,
302 + isFixedRateMode ? request.toCurrency.decimals : request.fromCurrency.decimals,
303 );
304
305 final params = {
@@ -329,8 +310,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
310 'dstChainId': '${dstChain.chainId}',
311 'dstToken': dstToken,
312 'slippage': '300',
332 - 'swapDirection':
333 - isFixedRateMode ? 'exact-amount-out' : 'exact-amount-in',
313 + 'swapDirection': isFixedRateMode ? 'exact-amount-out' : 'exact-amount-in',
314 'amount': formattedAmount,
315 'recipient': recipient,
316 };
@@ -375,18 +355,16 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
355 final amtIn = (data['amountIn'] as Map?) ?? const {};
356 final amtInMax = (data['amountInMax'] as Map?) ?? const {};
357 final srcTokenAddr = amtIn['address']?.toString();
378 - final srcTokenDecs =
379 - (amtIn['decimals'] as num?)?.toInt() ?? request.fromCurrency.decimals;
380 - final requiresTokenApproval =
381 - data['requiresTokenApproval'] as bool? ?? false;
358 + final srcTokenDecs = (amtIn['decimals'] as num?)?.toInt() ?? request.fromCurrency.decimals;
359 + final requiresTokenApproval = data['requiresTokenApproval'] as bool? ?? false;
360
383 - final reqAmountStr =
384 - (amtInMax['amount'] ?? amtIn['amount'])?.toString() ?? '0';
361 + final reqAmountStr = (amtInMax['amount'] ?? amtIn['amount'])?.toString() ?? '0';
362 final reqAmountRaw = reqAmountStr.replaceAll('n', '');
363
387 - final needToRegisterInSwapXyz =
388 - vmId == 'alt-vm' || bridgeIds.contains('alt-vm')
389 - || chainId == 'solana' || bridgeIds.contains('solana');
364 + final needToRegisterInSwapXyz = vmId == 'alt-vm' ||
365 + bridgeIds.contains('alt-vm') ||
366 + chainId == 'solana' ||
367 + bridgeIds.contains('solana');
368
369 final trade = Trade(
370 id: txId,
@@ -452,8 +430,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
430 final List<dynamic> body = json.decode(res.body) as List<dynamic>;
431 if (body.isEmpty) return false;
432
455 - final isSuccess =
456 - (body[0] as Map<String, dynamic>)['success'] as bool? ?? false;
433 + final isSuccess = (body[0] as Map<String, dynamic>)['success'] as bool? ?? false;
434
435 return isSuccess;
436 } catch (e) {
@@ -482,8 +459,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
459 final error = data['error'] as Map<String, dynamic>?;
460 if (error != null) {
461 final code = error['code']?.toString() ?? 'unknown';
485 - throw Exception(
486 - 'SwapXyzExchangeProvider findTradeById error: ($id) $code');
462 + throw Exception('SwapXyzExchangeProvider findTradeById error: ($id) $code');
463 }
464 }
465
@@ -499,10 +475,8 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
475
476 final payoutAddress = dstTransaction?['toAddress']?.toString();
477
502 - final srcPaymentToken =
503 - (srcTransaction?['paymentToken'] as Map?)?.cast<String, dynamic>();
504 - final dstPaymentToken =
505 - (dstTransaction?['paymentToken'] as Map?)?.cast<String, dynamic>();
478 + final srcPaymentToken = (srcTransaction?['paymentToken'] as Map?)?.cast<String, dynamic>();
479 + final dstPaymentToken = (dstTransaction?['paymentToken'] as Map?)?.cast<String, dynamic>();
480
481 final fromSymbol = (srcPaymentToken?['symbol'] as String?) ?? '';
482 final toSymbol = (dstPaymentToken?['symbol'] as String?) ?? '';
@@ -523,8 +497,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
497 String? receiveAmount;
498 if (dstAmountRaw != null) {
499 final dstAmountMinimal = _stripN(dstAmountRaw);
526 - receiveAmount =
527 - AmountConverter.fromBaseUnits(dstAmountMinimal, dstDecimals);
500 + receiveAmount = AmountConverter.fromBaseUnits(dstAmountMinimal, dstDecimals);
501 }
502
503 final srcAmountMinimal = _stripN(srcAmountRaw);
@@ -537,8 +510,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
510 final timestamp = srcTs ?? dstTs;
511
512 final createdAt = timestamp != null
540 - ? DateTime.fromMillisecondsSinceEpoch(timestamp * 1000, isUtc: true)
541 - .toLocal()
513 + ? DateTime.fromMillisecondsSinceEpoch(timestamp * 1000, isUtc: true).toLocal()
514 : null;
515
516 return Trade(
@@ -581,8 +553,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
553 if (_supportedChainList.isNotEmpty) return _supportedChainList;
554 try {
555 final uri = Uri.https(_baseUrl, _getChainList);
584 - final response =
585 - await ProxyWrapper().get(clearnetUri: uri, headers: _headers);
556 + final response = await ProxyWrapper().get(clearnetUri: uri, headers: _headers);
557 if (response.statusCode != 200) return [];
558
559 final data = json.decode(response.body) as List<dynamic>;
@@ -677,8 +648,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
648 // Case 1: String "all" -> cache empty list to indicate all tokens supported
649 if (tokensField is String) {
650 if (tokensField.toLowerCase() == 'all') {
680 - _tokensCache[pathChainId] =
681 - _tokensCache[pathChainId] ?? <TokenPathInfo>[];
651 + _tokensCache[pathChainId] = _tokensCache[pathChainId] ?? <TokenPathInfo>[];
652 }
653 continue;
654 }
@@ -705,9 +675,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
675 // Merge by symbol, prefer entries that have a non-empty address/decimals
676 void _mergeCache(int chainId, List<TokenPathInfo> incoming) {
677 final existing = _tokensCache[chainId] ?? const <TokenPathInfo>[];
708 - final bySymbol = <String, TokenPathInfo>{
709 - for (final t in existing) t.symbol: t
710 - };
678 + final bySymbol = <String, TokenPathInfo>{for (final t in existing) t.symbol: t};
679
680 for (final t in incoming) {
681 final cur = bySymbol[t.symbol];
@@ -758,8 +726,7 @@ class SwapsXyzExchangeProvider extends ExchangeProvider {
726 return symbol;
727 }
728
761 - Map<String, dynamic>? findTokenBySymbol(
762 - {required String title, required List<dynamic> tokens}) {
729 + Map<String, dynamic>? findTokenBySymbol({required String title, required List<dynamic> tokens}) {
730 final reqSymbol = title.toUpperCase();
731 for (final token in tokens) {
732 final map = token as Map<String, dynamic>;
lib/exchange/provider/swaptrade_exchange_provider.dart
+18 -15
@@ -69,8 +69,8 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
69 final normalized = _normalizeCurrency(from);
70 final coin = coinsInfo.cast<Map<String, dynamic>>().firstWhere(
71 (c) => (c['id']?.toString().toUpperCase() ?? '') == normalized,
72 - orElse: () => <String, dynamic>{},
73 - );
72 + orElse: () => <String, dynamic>{},
73 + );
74
75 if (coin.isEmpty) {
76 // Currency not supported by SwapTrade (e.g. USDC, DOGE).
@@ -88,19 +88,18 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
88 }
89
90 @override
91 - Future<double> fetchRate({
92 - required CryptoCurrency from,
93 - required CryptoCurrency to,
94 - required double amount,
95 - required bool isFixedRateMode,
96 - required bool isReceiveAmount
97 - }) async {
91 + Future<double> fetchRate(
92 + {required CryptoCurrency from,
93 + required CryptoCurrency to,
94 + required double amount,
95 + required bool isFixedRateMode,
96 + required bool isReceiveAmount}) async {
97 try {
98 if (amount == 0) return 0.0;
99 if (isFixedRateMode && !supportsFixedRate) {
100 return 0.0;
101 }
103 - if(from == CryptoCurrency.btcln || to == CryptoCurrency.btcln) return 0;
102 + if (from == CryptoCurrency.btcln || to == CryptoCurrency.btcln) return 0;
103
104 final params = <String, dynamic>{};
105 final body = <String, String>{
@@ -116,7 +115,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
115 body: json.encode(body),
116 headers: _headers,
117 );
119 -
118 +
119 final responseBody = json.decode(response.body) as Map<String, dynamic>;
120
121 if (response.statusCode != 200) {
@@ -140,7 +139,11 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
139
140 final data = responseBody['data'] as Map<String, dynamic>;
141 double rate = double.parse(data['price'].toString());
143 - final calculatedRate = rate > 0 ? isFixedRateMode ? amount / rate : rate / amount : 0.0;
142 + final calculatedRate = rate > 0
143 + ? isFixedRateMode
144 + ? amount / rate
145 + : rate / amount
146 + : 0.0;
147
148 ExchangeProviderLogger.logSuccess(
149 provider: description,
@@ -208,7 +211,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
211 body: json.encode(body),
212 headers: _headers,
213 );
211 -
214 +
215 final responseBody = json.decode(response.body) as Map<String, dynamic>;
216
217 if (response.statusCode == 400 || responseBody["success"] == false) {
@@ -235,7 +238,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
238 'url': uri.toString(),
239 },
240 );
238 -
241 +
242 throw TradeNotCreatedException(description, description: error);
243 }
244
@@ -337,7 +340,7 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
340 body: json.encode(body),
341 headers: _headers,
342 );
340 -
343 +
344 final responseBody = json.decode(response.body) as Map<String, dynamic>;
345
346 if (response.statusCode == 400 || responseBody["success"] == false) {
lib/exchange/provider/thorchain_exchange.provider.dart
+38 -40
@@ -46,13 +46,12 @@ class ThorChainExchangeProvider extends ExchangeProvider {
46 Future<bool> checkIsAvailable() async => true;
47
48 @override
49 - Future<double> fetchRate({
50 - required CryptoCurrency from,
51 - required CryptoCurrency to,
52 - required double amount,
53 - required bool isFixedRateMode,
54 - required bool isReceiveAmount
55 - }) async {
49 + Future<double> fetchRate(
50 + {required CryptoCurrency from,
51 + required CryptoCurrency to,
52 + required double amount,
53 + required bool isFixedRateMode,
54 + required bool isReceiveAmount}) async {
55 try {
56 if (amount == 0) return 0.0;
57
@@ -132,8 +131,6 @@ class ThorChainExchangeProvider extends ExchangeProvider {
131 required bool isFixedRateMode,
132 required bool isSendAll,
133 }) async {
135 -
136 -
134 final formattedFromAmount = double.parse(request.fromAmount);
135
136 final params = {
@@ -143,8 +140,9 @@ class ThorChainExchangeProvider extends ExchangeProvider {
140 'destination': _normalizeAddress(request.toAddress),
141 'affiliate': _affiliateName,
142 'affiliate_bps': _affiliateBps,
146 - 'refund_address':
147 - isRefundAddressSupported.contains(request.fromCurrency) ? _normalizeAddress(request.refundAddress) : '',
143 + 'refund_address': isRefundAddressSupported.contains(request.fromCurrency)
144 + ? _normalizeAddress(request.refundAddress)
145 + : '',
146 };
147
148 final responseJSON = await _getSwapQuote(params);
@@ -203,7 +201,6 @@ class ThorChainExchangeProvider extends ExchangeProvider {
201 final formattedId = id.startsWith('0x') ? id.substring(2) : id;
202 final uri = Uri.https(_baseNodeURL, '$_txInfoPath$formattedId');
203 final response = await ProxyWrapper().get(clearnetUri: uri);
206 -
204
205 if (response.statusCode == 404) {
206 throw Exception('Trade not found for id: $formattedId');
@@ -235,7 +232,8 @@ class ThorChainExchangeProvider extends ExchangeProvider {
232 : '';
233
234 final formattedToChain = CryptoCurrency.safeParseCurrencyFromString(toChain);
238 - final toAssetWithChain = CryptoCurrency.safeParseCurrencyFromString(toAsset, walletCurrency: formattedToChain);
235 + final toAssetWithChain =
236 + CryptoCurrency.safeParseCurrencyFromString(toAsset, walletCurrency: formattedToChain);
237
238 final plannedOutTxs = responseJSON['planned_out_txs'] as List<dynamic>?;
239 final isRefund = plannedOutTxs?.any((tx) => tx['refund'] == true) ?? false;
@@ -257,39 +255,39 @@ class ThorChainExchangeProvider extends ExchangeProvider {
255 static Future<Map<String, String>?>? lookupAddressByName(String name) async {
256 final uri = Uri.https(_baseURL, '$_nameLookUpPath$name');
257 try {
260 - final response = await ProxyWrapper().get(clearnetUri: uri);
261 -
262 - if (response.statusCode != 200) {
263 - return null;
264 - }
265 -
266 - final body = json.decode(response.body) as Map<String, dynamic>;
267 - final entries = body['entries'] as List<dynamic>?;
268 -
269 - if (entries == null || entries.isEmpty) {
270 - return null;
271 - }
272 -
273 - Map<String, String> chainToAddressMap = {};
274 -
275 - for (final entry in entries) {
276 - final chain = entry['chain'] as String;
277 - final address = entry['address'] as String;
278 - chainToAddressMap[chain] = address;
279 - }
280 -
281 - return chainToAddressMap;
282 -} catch (e) {
283 - printV(e.toString());
284 - return null;
285 -}
258 + final response = await ProxyWrapper().get(clearnetUri: uri);
259 +
260 + if (response.statusCode != 200) {
261 + return null;
262 + }
263 +
264 + final body = json.decode(response.body) as Map<String, dynamic>;
265 + final entries = body['entries'] as List<dynamic>?;
266 +
267 + if (entries == null || entries.isEmpty) {
268 + return null;
269 + }
270 +
271 + Map<String, String> chainToAddressMap = {};
272 +
273 + for (final entry in entries) {
274 + final chain = entry['chain'] as String;
275 + final address = entry['address'] as String;
276 + chainToAddressMap[chain] = address;
277 + }
278 +
279 + return chainToAddressMap;
280 + } catch (e) {
281 + printV(e.toString());
282 + return null;
283 + }
284 }
285
286 Future<Map<String, dynamic>> _getSwapQuote(Map<String, String> params) async {
287 Uri uri = Uri.https(_baseNodeURL, _quotePath, params);
288
289 final response = await ProxyWrapper().get(clearnetUri: uri);
292 -
290 +
291 if (response.statusCode != 200) {
292 ExchangeProviderLogger.logError(
293 provider: description,
lib/exchange/provider/xoswap_exchange_provider.dart
+28 -28
@@ -12,6 +12,7 @@ import 'package:cw_core/crypto_currency.dart';
12 import 'package:cw_core/utils/print_verbose.dart';
13 import 'package:cw_core/utils/proxy_wrapper.dart';
14 import 'package:cake_wallet/utils/exchange_provider_logger.dart';
15 +
16 class XOSwapExchangeProvider extends ExchangeProvider {
17 XOSwapExchangeProvider() {
18 _addAppVersionHeader();
@@ -54,7 +55,7 @@ class XOSwapExchangeProvider extends ExchangeProvider {
55 'BASE': 'basemainnet',
56 'ARB': 'arbitrum',
57 };
57 -
58 +
59 static const supportedTags = [
60 'POL',
61 'ETH',
@@ -76,18 +77,21 @@ class XOSwapExchangeProvider extends ExchangeProvider {
77 'ARB',
78 ];
79
79 -
80 String _normalizeXOSwapsNetwork(String string) {
81 final lower = string.toLowerCase();
82
83 - if (lower.endsWith('matic0a883d9b')) return string.replaceFirst(RegExp(r'matic0a883d9b$', caseSensitive: false), 'POL');
84 - if (lower.endsWith('matic86e249c1')) return string.replaceFirst(RegExp(r'matic86e249c1$', caseSensitive: false), 'POL');
85 - if (lower.endsWith('bscddedf0f8')) return string.replaceFirst(RegExp(r'bscddedf0f8$', caseSensitive: false), 'BSC');
86 - if (lower.endsWith('basemainnetb5a52617')) return string.replaceFirst(RegExp(r'basemainnetb5a52617$', caseSensitive: false), 'BASE');
83 + if (lower.endsWith('matic0a883d9b'))
84 + return string.replaceFirst(RegExp(r'matic0a883d9b$', caseSensitive: false), 'POL');
85 + if (lower.endsWith('matic86e249c1'))
86 + return string.replaceFirst(RegExp(r'matic86e249c1$', caseSensitive: false), 'POL');
87 + if (lower.endsWith('bscddedf0f8'))
88 + return string.replaceFirst(RegExp(r'bscddedf0f8$', caseSensitive: false), 'BSC');
89 + if (lower.endsWith('basemainnetb5a52617'))
90 + return string.replaceFirst(RegExp(r'basemainnetb5a52617$', caseSensitive: false), 'BASE');
91
92 return string;
93 }
90 -
94 +
95 @override
96 String get title => 'XOSwap';
97
@@ -116,7 +120,7 @@ class XOSwapExchangeProvider extends ExchangeProvider {
120 {'networks': normalizedNetwork, 'query': currency.title});
121
122 final response = await ProxyWrapper().get(clearnetUri: uri, headers: _headers);
119 -
123 +
124 if (response.statusCode != 200) {
125 throw Exception('Failed to fetch assets for ${currency.title} on ${currency.tag}');
126 }
@@ -125,7 +129,6 @@ class XOSwapExchangeProvider extends ExchangeProvider {
129 if (decoded is! List) throw const FormatException('Unexpected response format');
130 final assets = decoded.map((e) => Map<String, dynamic>.from(e as Map)).toList();
131
128 -
132 final asset = assets.firstWhere(
133 (asset) => removeNonAlphanumeric((asset['symbol'] ?? '').toString()) == currency.title,
134 orElse: () => const {},
@@ -138,7 +141,8 @@ class XOSwapExchangeProvider extends ExchangeProvider {
141 }
142 }
143
141 - String removeNonAlphanumeric(String str) => str.toUpperCase().replaceAll(RegExp(r'[^A-Z0-9]'), '');
144 + String removeNonAlphanumeric(String str) =>
145 + str.toUpperCase().replaceAll(RegExp(r'[^A-Z0-9]'), '');
146
147 Future<List<dynamic>> getRatesForPair({
148 required CryptoCurrency from,
@@ -169,8 +173,8 @@ class XOSwapExchangeProvider extends ExchangeProvider {
173 final rates = await getRatesForPair(from: from, to: to);
174 if (rates.isEmpty) throw Exception('No rates found for $from to $to');
175
172 - double minLimit = double.infinity;
173 - double maxLimit = 0;
176 + double minLimit = double.infinity;
177 + double maxLimit = 0;
178
179 for (var rate in rates) {
180 final double currentMin = double.parse(rate['min']['value'].toString());
@@ -186,13 +190,12 @@ class XOSwapExchangeProvider extends ExchangeProvider {
190 }
191
192 @override
189 - Future<double> fetchRate({
190 - required CryptoCurrency from,
191 - required CryptoCurrency to,
192 - required double amount,
193 - required bool isFixedRateMode,
194 - required bool isReceiveAmount
195 - }) async {
193 + Future<double> fetchRate(
194 + {required CryptoCurrency from,
195 + required CryptoCurrency to,
196 + required double amount,
197 + required bool isFixedRateMode,
198 + required bool isReceiveAmount}) async {
199 try {
200 final rates = await getRatesForPair(from: from, to: to);
201 if (rates.isEmpty) {
@@ -337,7 +340,7 @@ class XOSwapExchangeProvider extends ExchangeProvider {
340 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
341 final error = responseJSON['error'] ?? 'Unknown error';
342 final message = responseJSON['message'] ?? '';
340 -
343 +
344 ExchangeProviderLogger.logError(
345 provider: description,
346 function: 'createTrade',
@@ -356,7 +359,7 @@ class XOSwapExchangeProvider extends ExchangeProvider {
359 'url': uri.toString(),
360 },
361 );
359 -
362 +
363 throw Exception('$error\n$message');
364 }
365 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
@@ -456,7 +459,7 @@ class XOSwapExchangeProvider extends ExchangeProvider {
459 try {
460 final uri = Uri.https(_apiAuthority, '$_apiPath$_orders/$id');
461 final response = await ProxyWrapper().get(clearnetUri: uri, headers: _headers);
459 -
462 +
463 if (response.statusCode != 200) {
464 final responseJSON = json.decode(response.body) as Map<String, dynamic>;
465 if (responseJSON.containsKey('code') && responseJSON['code'] == 'NOT_FOUND') {
@@ -507,10 +510,10 @@ class XOSwapExchangeProvider extends ExchangeProvider {
510 toAssetTag = 'ETH';
511 toAssetBase = 'BASE';
512 }
510 -
511 - final fromCurrency = CryptoCurrency.safeParseCurrencyFromString(fromAssetBase,tag: fromAssetTag);
512 - final toCurrency = CryptoCurrency.safeParseCurrencyFromString(toAssetBase,tag: toAssetTag);
513
514 + final fromCurrency =
515 + CryptoCurrency.safeParseCurrencyFromString(fromAssetBase, tag: fromAssetTag);
516 + final toCurrency = CryptoCurrency.safeParseCurrencyFromString(toAssetBase, tag: toAssetTag);
517
518 final amount = responseJSON['amount'] as Map<String, dynamic>;
519 final toAmount = responseJSON['toAmount'] as Map<String, dynamic>;
@@ -553,9 +556,6 @@ class XOSwapExchangeProvider extends ExchangeProvider {
556
557 // ensure something remains before tag (at least 2 chars)
558 String? _extractTagFromAsset(String asset) {
556 -
557 -
558 -
559 for (final tag in supportedTags) {
560 if (asset.endsWith(tag)) {
561 final prefixLength = asset.length - tag.length;
lib/exchange/trade_legacy.part.dart
+3 -7
@@ -48,12 +48,10 @@ class TradeLegacyAdapter extends TypeAdapter<TradeLegacy> {
48 chainId: fields[34] as int?,
49 fee: fields[35] as double?,
50 )
51 - ..providerRaw =
52 - fields[1] == null ? 0 : fields[1] as int
51 + ..providerRaw = fields[1] == null ? 0 : fields[1] as int
52 ..fromRaw = (fields[2] as int?) ?? -1
53 ..toRaw = (fields[3] as int?) ?? -1
55 - ..stateRaw =
56 - fields[4] == null ? '' : fields[4] as String;
54 + ..stateRaw = fields[4] == null ? '' : fields[4] as String;
55 }
56
57 @override
@@ -140,7 +138,5 @@ class TradeLegacyAdapter extends TypeAdapter<TradeLegacy> {
138 @override
139 bool operator ==(Object other) =>
140 identical(this, other) ||
143 - other is TradeLegacyAdapter &&
144 - runtimeType == other.runtimeType &&
145 - typeId == other.typeId;
141 + other is TradeLegacyAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
142 }
lib/haven/cw_haven.dart
-1
@@ -12,7 +12,6 @@ import 'package:cw_core/wallet_type.dart';
12 import 'package:hive/hive.dart';
13
14 class HavenWalletService extends WalletService {
15 -
15 HavenWalletService();
16
17 @override
lib/locales/hausa_intl.dart
+4 -5
@@ -795,11 +795,11 @@ class HaMaterialLocalizations extends GlobalMaterialLocalizations {
795 @override
796 // TODO: implement shareButtonLabel
797 String get shareButtonLabel => "shareButtonLabel";
798 -
798 +
799 @override
800 // TODO: implement clearButtonTooltip
801 String get clearButtonTooltip => "clearButtonTooltip";
802 -
802 +
803 @override
804 // TODO: implement selectedDateLabel
805 String get selectedDateLabel => "selectedDateLabel";
@@ -1028,11 +1028,11 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations {
1028 @override
1029 // TODO: implement shareButtonLabel
1030 String get shareButtonLabel => "shareButtonLabel";
1031 -
1031 +
1032 @override
1033 // TODO: implement backButtonLabel
1034 String get backButtonLabel => "backButtonLabel";
1035 -
1035 +
1036 @override
1037 // TODO: implement cancelButtonLabel
1038 String get cancelButtonLabel => "cancelButtonLabel";
@@ -1054,5 +1054,4 @@ class HaCupertinoLocalizations extends GlobalCupertinoLocalizations {
1054
1055 @override
1056 String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint";
1057 -
1057 }
lib/locales/yoruba_intl.dart
+3 -4
@@ -794,11 +794,11 @@ class YoMaterialLocalizations extends GlobalMaterialLocalizations {
794 @override
795 // TODO: implement shareButtonLabel
796 String get shareButtonLabel => "shareButtonLabel";
797 -
797 +
798 @override
799 // TODO: implement clearButtonTooltip
800 String get clearButtonTooltip => "clearButtonTooltip";
801 -
801 +
802 @override
803 // TODO: implement selectedDateLabel
804 String get selectedDateLabel => "selectedDateLabel";
@@ -1028,7 +1028,7 @@ class YoCupertinoLocalizations extends GlobalCupertinoLocalizations {
1028 @override
1029 // TODO: implement shareButtonLabel
1030 String get shareButtonLabel => "shareButtonLabel";
1031 -
1031 +
1032 @override
1033 // TODO: implement backButtonLabel
1034 String get backButtonLabel => "backButtonLabel";
@@ -1054,5 +1054,4 @@ class YoCupertinoLocalizations extends GlobalCupertinoLocalizations {
1054
1055 @override
1056 String get expansionTileExpandedTapHint => "expansionTileExpandedTapHint";
1057 -
1057 }
lib/main.dart
+2 -5
@@ -167,12 +167,10 @@ Future<void> runAppWithZone({Key? topLevelKey}) async {
167 }
168
169 if (!Platform.isWindows) {
170 - var zcashPassword = await secureStorageShared.read(
171 - key: "com.cakewallet.cw_zcash/zec.db");
170 + var zcashPassword = await secureStorageShared.read(key: "com.cakewallet.cw_zcash/zec.db");
171 if (zcashPassword == null || zcashPassword.isEmpty) {
172 zcashPassword = generateKey().substring(0, 32);
174 - secureStorageShared.write(
175 - key: "com.cakewallet.cw_zcash/zec.db", value: zcashPassword);
173 + secureStorageShared.write(key: "com.cakewallet.cw_zcash/zec.db", value: zcashPassword);
174 }
175 zcash?.unlockDatabase(zcashPassword);
176 }
@@ -222,7 +220,6 @@ Future<void> initializeAppConfigs({bool loadWallet = true}) async {
220 CakeHive.registerAdapter(ContactAdapter());
221 }
222
225 -
223 if (!CakeHive.isAdapterRegistered(TransactionDescription.typeId)) {
224 CakeHive.registerAdapter(TransactionDescriptionAdapter());
225 }
lib/monero/cw_monero.dart
+17 -16
@@ -66,12 +66,12 @@ class CWMoneroSubaddressList extends MoneroSubaddressList {
66 final moneroWallet = _wallet as MoneroWallet;
67 final subAddresses = moneroWallet.walletAddresses.subaddressList.subaddresses
68 .map((sub) => Subaddress(
69 - id: sub.id,
70 - address: sub.address,
71 - label: sub.label,
72 - received: sub.balance??"unknown",
73 - txCount: sub.txCount??0,
74 - ))
69 + id: sub.id,
70 + address: sub.address,
71 + label: sub.label,
72 + received: sub.balance ?? "unknown",
73 + txCount: sub.txCount ?? 0,
74 + ))
75 .toList();
76 return ObservableList<Subaddress>.of(subAddresses);
77 }
@@ -91,14 +91,13 @@ class CWMoneroSubaddressList extends MoneroSubaddressList {
91 @override
92 Future<List<Subaddress>> getAll(Object wallet) async {
93 final moneroWallet = wallet as MoneroWallet;
94 - return (await moneroWallet.walletAddresses.subaddressList
95 - .getAll())
94 + return (await moneroWallet.walletAddresses.subaddressList.getAll())
95 .map((sub) => Subaddress(
97 - id: sub.id,
98 - label: sub.label,
99 - address: sub.address,
100 - txCount: sub.txCount??0,
101 - received: sub.balance??'unknown'))
96 + id: sub.id,
97 + label: sub.label,
98 + address: sub.address,
99 + txCount: sub.txCount ?? 0,
100 + received: sub.balance ?? 'unknown'))
101 .toList();
102 }
103
@@ -253,7 +252,11 @@ class CWMonero extends Monero {
252 required int height,
253 required String mnemonic}) =>
254 MoneroRestoreWalletFromSeedCredentials(
256 - name: name, password: password, passphrase: passphrase, height: height, mnemonic: mnemonic);
255 + name: name,
256 + password: password,
257 + passphrase: passphrase,
258 + height: height,
259 + mnemonic: mnemonic);
260
261 @override
262 WalletCredentials createMoneroNewWalletCredentials({
@@ -397,7 +400,6 @@ class CWMonero extends Monero {
400 return moneroWallet.importKeyImagesUR(ur);
401 }
402
400 -
403 @override
404 Future<bool> commitTransactionUR(Object wallet, String ur) {
405 final moneroWallet = wallet as MoneroWallet;
@@ -440,7 +442,6 @@ class CWMonero extends Monero {
442 moneroWallet.trezorService = service as MoneroTrezorService;
443 }
444
443 -
445 @override
446 HardwareWalletService getLedgerHardwareWalletService(ledger.LedgerConnection connection) =>
447 MoneroLedgerService(connection);
lib/new-ui/modal_navigator.dart
+24 -15
@@ -9,7 +9,11 @@ import 'package:flutter/material.dart';
9 /// calling Navigator.of(context).pop() will pop the page INSIDE the modal sheet.
10 /// if you want to pop the whole sheet, use Navigator.of(context, rootNavigator: true).pop().
11 class ModalNavigator extends StatefulWidget {
12 - const ModalNavigator({super.key, required this.rootPage, required this.parentContext, this.heightMode = ModalHeightModes.fullScreen});
12 + const ModalNavigator(
13 + {super.key,
14 + required this.rootPage,
15 + required this.parentContext,
16 + this.heightMode = ModalHeightModes.fullScreen});
17
18 final Widget rootPage;
19 final BuildContext parentContext;
@@ -22,8 +26,10 @@ class ModalNavigator extends StatefulWidget {
26 enum ModalHeightModes {
27 /// just render as big a modal as possible
28 fullScreen,
29 +
30 /// after first frame, read height and lock to that height
31 autoLock,
32 +
33 /// let the content size itself. jumps around when pushing different-sized pages!
34 natural
35 }
@@ -39,7 +45,7 @@ class _ModalNavigatorState extends State<ModalNavigator> {
45 WidgetsBinding.instance.addPostFrameCallback((_) {
46 final context = _sheetKey.currentContext;
47 if (context == null) return;
42 - if(_sheetHeight != null) return;
48 + if (_sheetHeight != null) return;
49
50 final box = context.findRenderObject() as RenderBox;
51 setState(() {
@@ -51,16 +57,19 @@ class _ModalNavigatorState extends State<ModalNavigator> {
57 @override
58 Widget build(BuildContext context) {
59 late final double? height;
54 - switch(widget.heightMode) {
60 + switch (widget.heightMode) {
61 case ModalHeightModes.fullScreen:
56 - height = MediaQuery.of(context).size.height; break;
57 - case ModalHeightModes.autoLock:
58 - height = _sheetHeight; break;
62 + height = MediaQuery.of(context).size.height;
63 + break;
64 + case ModalHeightModes.autoLock:
65 + height = _sheetHeight;
66 + break;
67 case ModalHeightModes.natural:
60 - height = null; break;
68 + height = null;
69 + break;
70 }
71 return Container(
63 - key:_sheetKey,
72 + key: _sheetKey,
73 height: height,
74 child: Theme(
75 data: Theme.of(context).copyWith(
@@ -90,16 +99,16 @@ class _ModalNavigatorState extends State<ModalNavigator> {
99 child: Navigator(
100 key: _navigatorKey,
101 onGenerateRoute: (settings) {
93 -
102 printV(settings.name);
103
104 if (settings.name == "/")
97 - return handleRouteWithPlatformAwareness((context) => PopScope(
98 - canPop: false,
99 - onPopInvokedWithResult: (didPop, result) async {
100 - Navigator.of(widget.parentContext).pop();
101 - },
102 - child: widget.rootPage),
105 + return handleRouteWithPlatformAwareness(
106 + (context) => PopScope(
107 + canPop: false,
108 + onPopInvokedWithResult: (didPop, result) async {
109 + Navigator.of(widget.parentContext).pop();
110 + },
111 + child: widget.rootPage),
112 fullscreenDialog: false);
113 else
114 return createRoute(settings);
lib/new-ui/pages/about_page.dart
+1 -1
@@ -43,7 +43,7 @@ class _AboutPageState extends State<AboutPage> {
43
44 void _easterEgg() {
45 _easterEggCounter++;
46 - if(_easterEggCounter == easterEggTreshold) {
46 + if (_easterEggCounter == easterEggTreshold) {
47 setState(() {
48 _bottomText = aboutPageEasterEggs.elementAt(Random().nextInt(aboutPageEasterEggs.length));
49 });
lib/new-ui/pages/account_customizer.dart
+4 -8
@@ -63,8 +63,8 @@ class _AccountCustomizerState extends State<AccountCustomizer> {
63 WidgetsBinding.instance.addPostFrameCallback((_) {
64 loadCards();
65 final activeId = monero!.getCurrentAccount(widget.dashboardViewModel.wallet).id;
66 - for (int i = 0; i < _items.length-1; i++) {
67 - if(_items[i].accountListItem.id == activeId) {
66 + for (int i = 0; i < _items.length - 1; i++) {
67 + if (_items[i].accountListItem.id == activeId) {
68 final lastIndex = _items.length - 1;
69 final temp = _items[i];
70 _items[i] = _items[lastIndex];
@@ -74,10 +74,7 @@ class _AccountCustomizerState extends State<AccountCustomizer> {
74 break;
75 }
76 }
77 -
77 });
79 -
80 -
78 }
79
80 @override
@@ -93,7 +90,7 @@ class _AccountCustomizerState extends State<AccountCustomizer> {
90 for (int i = 0; i < accounts.length; i++) {
91 final index = widget.dashboardViewModel.cardOrder[i];
92
96 - if(index == null || index >= accounts.length) {
93 + if (index == null || index >= accounts.length) {
94 // db order broken.
95 reset();
96 break;
@@ -361,7 +358,7 @@ class _AccountCustomizerState extends State<AccountCustomizer> {
358 },
359 actionRightButton: Navigator.of(context).pop);
360 });
364 - if(res != null && res is bool && res) {
361 + if (res != null && res is bool && res) {
362 reset();
363 }
364 }
@@ -371,7 +368,6 @@ class _AccountCustomizerState extends State<AccountCustomizer> {
368
369 final accounts = widget.accountListViewModel.accounts;
370 for (int i = 0; i < widget.accountListViewModel.accounts.length; i++) {
374 -
371 _items.add(AccountCustomizerListItem(
372 card: BalanceCard(
373 accountName: accounts[i].label,
lib/new-ui/pages/addresses_page.dart
+2 -1
@@ -431,7 +431,8 @@ class AddressRow extends StatelessWidget {
431 fontSize: 12,
432 color: Theme.of(context).colorScheme.onSurfaceVariant),
433 ),
434 - Text("${hasReceived ? S.of(context).received : S.of(context).balance}: ${item.balance}",
434 + Text(
435 + "${hasReceived ? S.of(context).received : S.of(context).balance}: ${item.balance}",
436 style: TextStyle(
437 fontSize: 12,
438 color: Theme.of(context).colorScheme.onSurfaceVariant)),
lib/new-ui/pages/bridge/bridge_confirm_sheet.dart
+4 -2
@@ -205,9 +205,11 @@ class _BridgeConfirmSheetState extends State<BridgeConfirmSheet> {
205 child: Observer(
206 builder: (_) {
207 if (bridgeViewModel.isExecuting) {
208 - return LoadingBottomWidget(text: "${S.of(context).bridging}...",);
208 + return LoadingBottomWidget(
209 + text: "${S.of(context).bridging}...",
210 + );
211 }
210 - if(bridgeViewModel.isQuoteLoading || bridgeViewModel.quote == null) {
212 + if (bridgeViewModel.isQuoteLoading || bridgeViewModel.quote == null) {
213 return LoadingBottomWidget(text: "${S.of(context).loading}...");
214 }
215 return ConfirmSwiper(
lib/new-ui/pages/bridge/bridge_network_page.dart
+4 -2
@@ -57,12 +57,14 @@ class BridgeNetworkPage extends StatelessWidget {
57 (chain) {
58 final chainName = chain.name;
59 return ListItemRegularRow(
60 - iconPath: 'assets/new-ui/crypto_full_icons/${chainName.toLowerCase()}.svg',
60 + iconPath:
61 + 'assets/new-ui/crypto_full_icons/${chainName.toLowerCase()}.svg',
62 keyValue: chain.chainId.toString(),
63 label: chainName,
64 onTap: () {
65 bridgeViewModel.setDestinationChain(chain.chainId);
65 - Navigator.pushNamed(context, Routes.bridgeReceivingWalletPage, arguments: bridgeViewModel);
66 + Navigator.pushNamed(context, Routes.bridgeReceivingWalletPage,
67 + arguments: bridgeViewModel);
68 },
69 );
70 },
lib/new-ui/pages/bridge/bridge_receive_address_input_page.dart
+4 -4
@@ -115,7 +115,8 @@ class _BridgeReceiveAddressInputPageState extends State<BridgeReceiveAddressInpu
115 focusNode: _focusNode,
116 selectedCurrency: bridgeViewModel.wallet.currency,
117 onEditingComplete: () {},
118 - validator: AddressValidator(type: bridgeViewModel.destinationChainInfo!.currency),
118 + validator:
119 + AddressValidator(type: bridgeViewModel.destinationChainInfo!.currency),
120 ),
121 const Spacer(),
122 Observer(
@@ -124,14 +125,13 @@ class _BridgeReceiveAddressInputPageState extends State<BridgeReceiveAddressInpu
125 onPressed: () {
126 final overlayCtx = Navigator.of(context).overlay?.context;
127 bridgeViewModel.setRecipientAddress(_controller.text.trim());
127 -
128 +
129 WidgetsBinding.instance.addPostFrameCallback((_) {
130 if (overlayCtx != null && overlayCtx.mounted) {
131 showMaterialModalBottomSheet<void>(
132 context: overlayCtx,
133 backgroundColor: Colors.transparent,
133 - builder: (ctx) =>
134 - BridgeConfirmSheet(bridgeViewModel),
134 + builder: (ctx) => BridgeConfirmSheet(bridgeViewModel),
135 );
136 }
137 });
lib/new-ui/pages/card_customizer.dart
+2 -1
@@ -251,7 +251,8 @@ class _CardCustomizerState extends State<CardCustomizer> {
251 ),
252 child: Padding(
253 padding: const EdgeInsets.all(10.0),
254 - child: CakeImageWidget(imageUrl: icon.path),
254 + child: CakeImageWidget(
255 + imageUrl: icon.path),
256 ),
257 ),
258 );
lib/new-ui/pages/coin_control_page.dart
+16 -6
@@ -104,9 +104,12 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
104 child: ModalHeader(
105 iconPath: "assets/new-ui/settings_row_icons/coin-control.svg",
106 title: "Coin Control",
107 - message: widget.canEdit ? S.of(context).coin_control_desc : S.of(context).coin_control_desc_no_edit),
107 + message: widget.canEdit
108 + ? S.of(context).coin_control_desc
109 + : S.of(context).coin_control_desc_no_edit),
110 ),
109 - if (widget.unspentCoinsListViewModel.items.isNotEmpty && widget.canEdit)
111 + if (widget.unspentCoinsListViewModel.items.isNotEmpty &&
112 + widget.canEdit)
113 Padding(
114 padding: const EdgeInsets.all(12.0),
115 child: Row(
@@ -134,7 +137,11 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
137 )
138 ],
139 ),
137 - ) else SizedBox(height: 24,),
140 + )
141 + else
142 + SizedBox(
143 + height: 24,
144 + ),
145 if (widget.unspentCoinsListViewModel.nonFrozenItems.isEmpty &&
146 widget.unspentCoinsListViewModel.frozenItems.isEmpty) ...[
147 SizedBox(height: 12),
@@ -154,7 +161,7 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
161 : Padding(
162 padding: const EdgeInsets.symmetric(horizontal: 18.0),
163 child: CoinControlListSection(
157 - canEdit: widget.canEdit,
164 + canEdit: widget.canEdit,
165 items: widget.unspentCoinsListViewModel.nonFrozenItems,
166 unspentCoinsListViewModel:
167 widget.unspentCoinsListViewModel),
@@ -181,7 +188,7 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
188 .onSurfaceVariant),
189 ),
190 CoinControlListSection(
184 - canEdit: widget.canEdit,
191 + canEdit: widget.canEdit,
192 items: widget
193 .unspentCoinsListViewModel.frozenItems,
194 unspentCoinsListViewModel:
@@ -206,7 +213,10 @@ class _NewCoinControlPageState extends State<NewCoinControlPage> {
213
214 class CoinControlListSection extends StatelessWidget {
215 const CoinControlListSection(
209 - {super.key, required this.items, required this.unspentCoinsListViewModel, required this.canEdit});
216 + {super.key,
217 + required this.items,
218 + required this.unspentCoinsListViewModel,
219 + required this.canEdit});
220
221 final List<UnspentCoinsItem> items;
222 final bool canEdit;
lib/new-ui/pages/home_page.dart
+87 -86
@@ -42,7 +42,7 @@ class _NewHomePageState extends State<NewHomePage> {
42 void initState() {
43 super.initState();
44 _setAccountViewModel();
45 - reaction((_)=>widget.dashboardViewModel.wallet, (_) {
45 + reaction((_) => widget.dashboardViewModel.wallet, (_) {
46 _setAccountViewModel();
47 setState(() {
48 _lightningMode = false;
@@ -59,62 +59,62 @@ class _NewHomePageState extends State<NewHomePage> {
59 @override
60 Widget build(BuildContext context) {
61 return Container(
62 - height: MediaQuery.of(context).size.height,
63 - decoration: BoxDecoration(
64 - gradient: LinearGradient(
65 - colors: [
66 - Theme.of(context).colorScheme.surface,
67 - Theme.of(context).colorScheme.surfaceDim,
68 - ],
69 - begin: Alignment.topCenter,
70 - end: Alignment.bottomCenter,
62 + height: MediaQuery.of(context).size.height,
63 + decoration: BoxDecoration(
64 + gradient: LinearGradient(
65 + colors: [
66 + Theme.of(context).colorScheme.surface,
67 + Theme.of(context).colorScheme.surfaceDim,
68 + ],
69 + begin: Alignment.topCenter,
70 + end: Alignment.bottomCenter,
71 + ),
72 ),
72 - ),
73 - child: Stack(
74 - children: [
75 - CustomScrollView(
76 - physics: BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
77 - slivers:[
78 - SliverPadding(
79 - padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
80 - sliver: CupertinoSliverRefreshControl(
81 - refreshTriggerPullDistance: 160,
82 - refreshIndicatorExtent: 90,
83 - onRefresh: () => widget.dashboardViewModel.refreshDashboard(),
84 - ),
85 - ),
86 - SliverToBoxAdapter(
87 - child: Column(
88 - mainAxisSize: MainAxisSize.max,
89 - mainAxisAlignment: MainAxisAlignment.start,
90 - spacing: 24.0,
91 - children: [
92 - TopBar(
93 - dashboardViewModel: widget.dashboardViewModel,
94 - lightningMode: _lightningMode,
95 - onLightningSwitchPress: () {
96 - setState(() {
97 - _lightningMode = !_lightningMode;
98 - });
99 - },
100 - onSettingsButtonPress: () {
101 - CupertinoScaffold.showCupertinoModalBottomSheet(
102 - context: context,
103 - barrierColor: Colors.black.withAlpha(85),
104 - builder: (context) => FractionallySizedBox(
105 - child: Material(
106 - child: NewSettingsPage(
107 - dashboardViewModel: widget.dashboardViewModel,
108 - authService: getIt.get<AuthService>(),
109 - ))),
110 - );
111 - },
73 + child: Stack(
74 + children: [
75 + CustomScrollView(
76 + physics: BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
77 + slivers: [
78 + SliverPadding(
79 + padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
80 + sliver: CupertinoSliverRefreshControl(
81 + refreshTriggerPullDistance: 160,
82 + refreshIndicatorExtent: 90,
83 + onRefresh: () => widget.dashboardViewModel.refreshDashboard(),
84 + ),
85 ),
113 - Observer(
114 - builder: (_)=>WalletInfoBar(
115 - lightningMode: _lightningMode,
116 - hardwareWalletType: widget.dashboardViewModel.wallet.hardwareWalletType,
117 - name: widget.dashboardViewModel.wallet.name,
86 + SliverToBoxAdapter(
87 + child: Column(
88 + mainAxisSize: MainAxisSize.max,
89 + mainAxisAlignment: MainAxisAlignment.start,
90 + spacing: 24.0,
91 + children: [
92 + TopBar(
93 + dashboardViewModel: widget.dashboardViewModel,
94 + lightningMode: _lightningMode,
95 + onLightningSwitchPress: () {
96 + setState(() {
97 + _lightningMode = !_lightningMode;
98 + });
99 + },
100 + onSettingsButtonPress: () {
101 + CupertinoScaffold.showCupertinoModalBottomSheet(
102 + context: context,
103 + barrierColor: Colors.black.withAlpha(85),
104 + builder: (context) => FractionallySizedBox(
105 + child: Material(
106 + child: NewSettingsPage(
107 + dashboardViewModel: widget.dashboardViewModel,
108 + authService: getIt.get<AuthService>(),
109 + ))),
110 + );
111 + },
112 + ),
113 + Observer(
114 + builder: (_) => WalletInfoBar(
115 + lightningMode: _lightningMode,
116 + hardwareWalletType: widget.dashboardViewModel.wallet.hardwareWalletType,
117 + name: widget.dashboardViewModel.wallet.name,
118 hasCustomize: accountListViewModel != null,
119 onCustomizeButtonTap: openAccountCustomizer),
120 ),
@@ -152,13 +152,15 @@ class _NewHomePageState extends State<NewHomePage> {
152 : SizedBox(width: double.infinity),
153 );
154 }),
155 - UnconfirmedBalanceWidget(dashboardViewModel: widget.dashboardViewModel,),
156 - ],
157 - ),
158 - Observer(
159 - builder: (_) {
160 - return Column(
161 - children: [
155 + UnconfirmedBalanceWidget(
156 + dashboardViewModel: widget.dashboardViewModel,
157 + ),
158 + ],
159 + ),
160 + Observer(
161 + builder: (_) {
162 + return Column(
163 + children: [
164 CoinActionRow(
165 lightningMode: _lightningMode,
166 showSwap: widget.dashboardViewModel.isEnabledSwapAction,
@@ -168,13 +170,12 @@ class _NewHomePageState extends State<NewHomePage> {
170 dashboardViewModel: widget.dashboardViewModel,
171 ),
172 ],
171 - );
172 - },
173 + );
174 + },
175 + ),
176 + ],
177 + ),
178 ),
174 -
175 - ],
176 - ),
177 - ),
179 Observer(
180 builder: (_) => AssetsHistorySection(
181 nftViewModel: widget.nftViewModel,
@@ -186,26 +187,26 @@ class _NewHomePageState extends State<NewHomePage> {
187 )
188 ]),
189 Container(
189 - height: (MediaQuery.of(context).padding.top),
190 - decoration: BoxDecoration(
191 - gradient: LinearGradient(
192 - begin: Alignment.bottomCenter,
193 - end: Alignment.topCenter,
194 - colors: <Color>[
195 - Theme.of(context).colorScheme.surface.withAlpha(5),
196 - Theme.of(context).colorScheme.surface.withAlpha(25),
197 - Theme.of(context).colorScheme.surface.withAlpha(50),
198 - Theme.of(context).colorScheme.surface.withAlpha(100),
199 - Theme.of(context).colorScheme.surface.withAlpha(150),
200 - Theme.of(context).colorScheme.surface.withAlpha(175),
201 - Theme.of(context).colorScheme.surface.withAlpha(200),
202 - ],
190 + height: (MediaQuery.of(context).padding.top),
191 + decoration: BoxDecoration(
192 + gradient: LinearGradient(
193 + begin: Alignment.bottomCenter,
194 + end: Alignment.topCenter,
195 + colors: <Color>[
196 + Theme.of(context).colorScheme.surface.withAlpha(5),
197 + Theme.of(context).colorScheme.surface.withAlpha(25),
198 + Theme.of(context).colorScheme.surface.withAlpha(50),
199 + Theme.of(context).colorScheme.surface.withAlpha(100),
200 + Theme.of(context).colorScheme.surface.withAlpha(150),
201 + Theme.of(context).colorScheme.surface.withAlpha(175),
202 + Theme.of(context).colorScheme.surface.withAlpha(200),
203 + ],
204 + ),
205 ),
206 ),
205 - ),
206 - ],
207 - ),
208 - );
207 + ],
208 + ),
209 + );
210 }
211
212 void openAccountCustomizer() async {
lib/new-ui/pages/lightning_username_page.dart
+10 -6
@@ -13,7 +13,11 @@ import 'package:flutter_bloc/flutter_bloc.dart';
13 import 'package:flutter_svg/flutter_svg.dart';
14
15 class LightningUsernamePage extends StatefulWidget {
16 - LightningUsernamePage({super.key, required this.isSetup, required this.themeStore, required this.lightningUsernameBloc});
16 + LightningUsernamePage(
17 + {super.key,
18 + required this.isSetup,
19 + required this.themeStore,
20 + required this.lightningUsernameBloc});
21
22 final bool isSetup;
23
@@ -167,8 +171,8 @@ class LightningUsernameInfo extends StatelessWidget {
171 children: [
172 CakeImageWidget(
173 imageUrl: isLightMode
170 - ? "assets/new-ui/lightning_username_setup_light.svg"
171 - : "assets/new-ui/lightning_username_setup.svg"),
174 + ? "assets/new-ui/lightning_username_setup_light.svg"
175 + : "assets/new-ui/lightning_username_setup.svg"),
176 Row(
177 mainAxisAlignment: MainAxisAlignment.center,
178 spacing: 2,
@@ -223,8 +227,8 @@ class LightningUsernameEditor extends StatelessWidget {
227 children: [
228 CakeImageWidget(
229 imageUrl: isLightMode
226 - ? "assets/new-ui/lightning_username_setup_light.svg"
227 - : "assets/new-ui/lightning_username_setup.svg"),
230 + ? "assets/new-ui/lightning_username_setup_light.svg"
231 + : "assets/new-ui/lightning_username_setup.svg"),
232 if (isSetup)
233 Padding(
234 padding: const EdgeInsets.symmetric(horizontal: 18.0),
@@ -258,7 +262,7 @@ class LightningUsernameEditor extends StatelessWidget {
262 child: InkWell(
263 onTap: onRandomizeButtonTap,
264 child: CakeImageWidget(
261 - imageUrl: "assets/new-ui/randomize.svg",
265 + imageUrl: "assets/new-ui/randomize.svg",
266 colorFilter: ColorFilter.mode(
267 Theme.of(context).colorScheme.primary, BlendMode.srcIn)),
268 ),
lib/new-ui/pages/receive_page.dart
+33 -24
@@ -171,8 +171,11 @@ class _NewReceivePageState extends State<NewReceivePage> {
171 .whereType<CryptoCurrency>()
172 .toList(), onDismissed: () {
173 widget.addressListViewModel.dismissInfobox();
174 - setState(() {});
175 - }, autoGenerateSubaddressStatus: widget.lightningMode ? AutoGenerateSubaddressStatus.disabled : widget.dashboardViewModel.settingsStore.autoGenerateSubaddressStatus);
174 + setState(() {});
175 + },
176 + autoGenerateSubaddressStatus: widget.lightningMode
177 + ? AutoGenerateSubaddressStatus.disabled
178 + : widget.dashboardViewModel.settingsStore.autoGenerateSubaddressStatus);
179
180 return Container(
181 decoration: BoxDecoration(
@@ -202,29 +205,35 @@ class _NewReceivePageState extends State<NewReceivePage> {
205 trailingWidget: Observer(
206 builder: (_) => AnimatedSwitcher(
207 duration: Duration(milliseconds: 300),
205 - child: _largeQrMode || widget.addressListViewModel.hasAddressRotation
206 - /* TODO rotating is broken on mweb, disabling for now, fix after mvp*/
207 - &&
208 - !(widget.receiveOptionViewModel.selectedReceiveOption.description ?? "")
209 - .toLowerCase()
210 - .contains("mweb") ? ModernButton(
211 - key: ValueKey(_largeQrMode),
212 - size: 36,
213 - icon: _largeQrMode ? Icon(Icons.share) : widget.addressListViewModel.isRotatingAddress
214 - ? CupertinoActivityIndicator()
215 - : Icon(Icons.refresh),
216 - onPressed: () {
217 - if(_largeQrMode) {
208 + child: _largeQrMode ||
209 + widget.addressListViewModel.hasAddressRotation
210 + /* TODO rotating is broken on mweb, disabling for now, fix after mvp*/
211 + &&
212 + !(widget.receiveOptionViewModel.selectedReceiveOption.description ??
213 + "")
214 + .toLowerCase()
215 + .contains("mweb")
216 + ? ModernButton(
217 + key: ValueKey(_largeQrMode),
218 + size: 36,
219 + icon: _largeQrMode
220 + ? Icon(Icons.share)
221 + : widget.addressListViewModel.isRotatingAddress
222 + ? CupertinoActivityIndicator()
223 + : Icon(Icons.refresh),
224 + onPressed: () {
225 + if (_largeQrMode) {
226 ShareUtil.share(
227 text: widget.addressListViewModel.uri.toString(),
228 context: context,
229 );
222 - } else {
223 - if(widget.addressListViewModel.hasAddressRotation) {
224 - widget.addressListViewModel.rotateAddress();
225 - }
226 - }
227 - }):SizedBox.shrink(),
230 + } else {
231 + if (widget.addressListViewModel.hasAddressRotation) {
232 + widget.addressListViewModel.rotateAddress();
233 + }
234 + }
235 + })
236 + : SizedBox.shrink(),
237 ),
238 ),
239 ),
@@ -274,9 +283,9 @@ class _NewReceivePageState extends State<NewReceivePage> {
283 copyData: widget.addressListViewModel.hasPayjoin
284 ? null
285 : ClipboardData(
277 - text: widget.addressListViewModel.displayAmount.isEmpty
278 - ? widget.addressListViewModel.uri.address
279 - : widget.addressListViewModel.uri.toString()),
286 + text: widget.addressListViewModel.displayAmount.isEmpty
287 + ? widget.addressListViewModel.uri.address
288 + : widget.addressListViewModel.uri.toString()),
289 onCopyButtonPressed: () {
290 if (widget.addressListViewModel.hasPayjoin) {
291 showModalBottomSheet(
lib/new-ui/pages/scan_page.dart
+5 -5
@@ -353,11 +353,10 @@ class _ScanPageState extends State<ScanPage> {
353 ),
354 ),
355 Positioned(
356 -bottom: 120, left:0,right:0,
356 + bottom: 120,
357 + left: 0,
358 + right: 0,
359 child: IgnorePointer(
358 -
359 -
360 -
360 child: AnimatedOpacity(
361 duration: Duration(milliseconds: 500),
362 opacity: isScanningURQR ? 1 : 0,
@@ -378,7 +377,8 @@ bottom: 120, left:0,right:0,
377 ),
378 Text(
379 "${decoder.expectedPartCount()}",
381 - style: TextStyle(fontSize: 45, color: Theme.of(context).colorScheme.onSurface),
380 + style:
381 + TextStyle(fontSize: 45, color: Theme.of(context).colorScheme.onSurface),
382 ),
383 ],
384 ),
lib/new-ui/pages/send_page.dart
+32 -31
@@ -187,7 +187,6 @@ class NewSendPage extends StatefulWidget {
187 }
188
189 class _NewSendPageState extends State<NewSendPage> {
190 -
190 int _selectedOutput = 0;
191
192 final _amountControllers = <TextEditingController>[];
@@ -291,7 +290,6 @@ class _NewSendPageState extends State<NewSendPage> {
290 }
291 }
292
294 -
293 @override
294 Widget build(BuildContext context) {
295 return Observer(builder: (_) {
@@ -321,8 +319,8 @@ class _NewSendPageState extends State<NewSendPage> {
319 if (widget.sendViewModel.outputs.length > 1)
320 ModernButton(
321 size: 36,
324 - icon: CakeImageWidget(imageUrl:
325 - "assets/new-ui/remove_recipient.svg",
322 + icon: CakeImageWidget(
323 + imageUrl: "assets/new-ui/remove_recipient.svg",
324 colorFilter: ColorFilter.mode(
325 Theme.of(context).colorScheme.primary,
326 BlendMode.srcIn,
@@ -352,8 +350,8 @@ class _NewSendPageState extends State<NewSendPage> {
350 if (widget.mode.helpContent != null)
351 ModernButton(
352 size: 36,
355 - icon: CakeImageWidget(imageUrl:
356 - "assets/new-ui/help.svg",
353 + icon: CakeImageWidget(
354 + imageUrl: "assets/new-ui/help.svg",
355 colorFilter: ColorFilter.mode(
356 Theme.of(context).colorScheme.primary, BlendMode.srcIn),
357 ),
@@ -420,7 +418,7 @@ class _NewSendPageState extends State<NewSendPage> {
418 output.loadContact(contact);
419 },
420 onPushPasteButton: (context) async {
423 - if(_justHandledPasteButton) return;
421 + if (_justHandledPasteButton) return;
422 _justHandledPasteButton = true;
423 try {
424 output.resetParsedAddress();
@@ -505,7 +503,8 @@ class _NewSendPageState extends State<NewSendPage> {
503 ),
504 ],
505 ),
508 - if (widget.sendViewModel.isMwebAvailable && widget.mode == SendPageModes.normal)
506 + if (widget.sendViewModel.isMwebAvailable &&
507 + widget.mode == SendPageModes.normal)
508 StandardCheckbox(
509 caption: S.of(context).litecoin_mweb_allow_coins,
510 captionColor: Theme.of(context).colorScheme.onSurface,
@@ -516,7 +515,7 @@ class _NewSendPageState extends State<NewSendPage> {
515 onChanged: (value) =>
516 widget.sendViewModel.setAllowMwebCoins(value),
517 ),
519 - if(widget.sendViewModel.hasMemos)
518 + if (widget.sendViewModel.hasMemos)
519 Observer(
520 builder: (_) => NewSendMemoInput(
521 memoController: _memoControllers[_selectedOutput],
@@ -542,14 +541,22 @@ class _NewSendPageState extends State<NewSendPage> {
541 ),
542 if (widget.sendViewModel.hasCoinControl)
543 ListItemRegularRowWidget(
545 - keyValue: "",
546 - label: "Coin Control",
547 - onTap: () {
548 - showCupertinoModalBottomSheet(enableDrag: false, useRootNavigator: true, isDismissible: false, context: context, builder: (context){
549 - return NewCoinControlPage(unspentCoinsListViewModel: widget.sendViewModel.unspentCoinsListViewModel,canEdit: true);
550 - });
551 - }
552 - ),
544 + keyValue: "",
545 + label: "Coin Control",
546 + onTap: () {
547 + showCupertinoModalBottomSheet(
548 + enableDrag: false,
549 + useRootNavigator: true,
550 + isDismissible: false,
551 + context: context,
552 + builder: (context) {
553 + return NewCoinControlPage(
554 + unspentCoinsListViewModel: widget
555 + .sendViewModel
556 + .unspentCoinsListViewModel,
557 + canEdit: true);
558 + });
559 + }),
560 ]),
561 )
562 ],
@@ -718,7 +725,6 @@ class _NewSendPageState extends State<NewSendPage> {
725 if (memo != output.memo && memo.length <= widget.sendViewModel.maxMemoLength) {
726 output.memo = memo;
727 }
721 -
728 });
729 }
730
@@ -731,8 +737,7 @@ class _NewSendPageState extends State<NewSendPage> {
737 widget.sendViewModel.outputs[i].setFiatAmount(_amountControllers[i].text);
738 } else {
739 final amount = widget.sendViewModel.amountParsingProxy.getCanonicalCryptoAmount(
734 - _amountControllers[i].text.sanitized(),
735 - widget.sendViewModel.selectedCryptoCurrency);
740 + _amountControllers[i].text.sanitized(), widget.sendViewModel.selectedCryptoCurrency);
741 widget.sendViewModel.outputs[i].setCryptoAmount(amount);
742 }
743 }
@@ -856,9 +861,7 @@ class _NewSendPageState extends State<NewSendPage> {
861 for (final r in widget.sendViewModel.balanceViewModel.formattedBalances)
862 r.asset: CurrencyPickerBalance(
863 amount: '${r.availableBalance} ${r.asset.title}',
859 - fiat: isFiatDisabled
860 - ? null
861 - : '${r.fiatAvailableBalanceRaw} ${r.fiatCurrency?.symbol}',
864 + fiat: isFiatDisabled ? null : '${r.fiatAvailableBalanceRaw} ${r.fiatCurrency?.symbol}',
865 fiatValue: isFiatDisabled ? null : double.tryParse(r.fiatAvailableBalanceRaw),
866 ),
867 };
@@ -1242,13 +1245,11 @@ class _NewSendPageState extends State<NewSendPage> {
1245 }
1246 _addressControllers[_selectedOutput].text = paymentRequest.address;
1247 if (paymentRequest.amount.isNotEmpty) {
1245 - try{
1248 + try {
1249 _amountControllers[_selectedOutput].text = widget.sendViewModel.amountParsingProxy
1250 .getDisplayCryptoAmount(
1251 paymentRequest.amount, widget.sendViewModel.selectedCryptoCurrency);
1249 - } catch(e) {
1250 -
1251 - }
1252 + } catch (e) {}
1253 }
1254 _memoControllers[_selectedOutput].text = paymentRequest.note;
1255 }
@@ -1417,7 +1418,7 @@ class SendHelpPage extends StatelessWidget {
1418 mainAxisSize: MainAxisSize.max,
1419 mainAxisAlignment: MainAxisAlignment.center,
1420 children: [
1420 - CakeImageWidget(imageUrl:content.imagePath),
1421 + CakeImageWidget(imageUrl: content.imagePath),
1422 Text(
1423 content.description,
1424 textAlign: TextAlign.center,
@@ -1466,8 +1467,8 @@ Future<bool> showParsedAddressConfirmationAlert(
1467 ? parsedAddress.addressSource.iconPath
1468 : parsedAddress.profileImageUrl,
1469 alertContent: S.of(context).extracted_address_content(
1469 - '${parsedAddress.handle} (${parsedAddress.addressSource.label})',
1470 - ),
1470 + '${parsedAddress.handle} (${parsedAddress.addressSource.label})',
1471 + ),
1472 buttonText: S.of(context).ok,
1473 buttonAction: () => Navigator.of(context).pop(true),
1474 );
@@ -1475,4 +1476,4 @@ Future<bool> showParsedAddressConfirmationAlert(
1476 );
1477
1478 return confirmed ?? false;
1478 -}
\ No newline at end of file
1479 +}
lib/new-ui/pages/settings_page.dart
+45 -20
@@ -26,7 +26,8 @@ bool _hasMweb(DashboardViewModel vm) => vm.hasMweb;
26
27 bool _hasWalletConnect(DashboardViewModel vm) => vm.hasWalletConnect;
28
29 -bool _isCupcake(DashboardViewModel vm) => vm.wallet.hardwareWalletType == HardwareWalletType.cupcake;
29 +bool _isCupcake(DashboardViewModel vm) =>
30 + vm.wallet.hardwareWalletType == HardwareWalletType.cupcake;
31
32 class SettingsListItem {
33 final String iconPath;
@@ -37,7 +38,11 @@ class SettingsListItem {
38 final bool Function(DashboardViewModel) use2fa;
39 final bool Function(DashboardViewModel) condition;
40
40 - const SettingsListItem(this.iconPath, this.title, this.route, {this.routeArgs = null, this.requireAuth = false, this.use2fa = _falseFunc, this.condition = _trueFunc});
41 + const SettingsListItem(this.iconPath, this.title, this.route,
42 + {this.routeArgs = null,
43 + this.requireAuth = false,
44 + this.use2fa = _falseFunc,
45 + this.condition = _trueFunc});
46 }
47
48 class SettingsSectionData {
@@ -49,30 +54,49 @@ class SettingsSectionData {
54
55 static SettingsSectionData walletSettings =
56 SettingsSectionData(S.current.wallet_settings, "assets/new-ui/wallet-setting.svg", [
52 - SettingsListItem("assets/new-ui/settings_row_icons/nodes.svg", S.current.nodes, Routes.manageNodes),
53 - SettingsListItem("assets/new-ui/settings_row_icons/privacy.svg", S.current.privacy, Routes.privacyPage),
54 - SettingsListItem("assets/new-ui/settings_row_icons/seed.svg", S.current.seed_and_keys, Routes.showKeys,
55 - routeArgs: true, requireAuth: true, use2fa: (vm)=>vm.settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings),
56 - SettingsListItem("assets/new-ui/settings_row_icons/lightning_username.svg", "Lightning ${S.current.username}", Routes.lightningUsernamePage, condition: _hasLightning),
57 - SettingsListItem("assets/new-ui/settings_row_icons/wc.svg", S.current.walletConnect, Routes.walletConnectConnectionsListing, condition: _hasWalletConnect),
57 + SettingsListItem(
58 + "assets/new-ui/settings_row_icons/nodes.svg", S.current.nodes, Routes.manageNodes),
59 + SettingsListItem(
60 + "assets/new-ui/settings_row_icons/privacy.svg", S.current.privacy, Routes.privacyPage),
61 + SettingsListItem(
62 + "assets/new-ui/settings_row_icons/seed.svg", S.current.seed_and_keys, Routes.showKeys,
63 + routeArgs: true,
64 + requireAuth: true,
65 + use2fa: (vm) => vm.settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings),
66 + SettingsListItem("assets/new-ui/settings_row_icons/lightning_username.svg",
67 + "Lightning ${S.current.username}", Routes.lightningUsernamePage,
68 + condition: _hasLightning),
69 + SettingsListItem("assets/new-ui/settings_row_icons/wc.svg", S.current.walletConnect,
70 + Routes.walletConnectConnectionsListing,
71 + condition: _hasWalletConnect),
72 //SettingsListItem("assets/new-ui/settings_row_icons/silent-payments.svg", S.current.silent_payments_settings, Routes.silentPaymentsSettings, condition: _isBtc),
73 //SettingsListItem("assets/new-ui/settings_row_icons/mweb.svg", S.current.litecoin_mweb_settings, Routes.mwebSettings, condition: _hasMweb),
60 - SettingsListItem("assets/new-ui/settings_row_icons/cupcake.svg", S.current.export_outputs, Routes.urqrAnimatedPage, routeArgs: {'export-outputs': 'export-outputs'}, condition: _isCupcake),
61 - SettingsListItem("assets/new-ui/settings_row_icons/other.svg", S.current.other, Routes.otherSettingsPage),
74 + SettingsListItem("assets/new-ui/settings_row_icons/cupcake.svg", S.current.export_outputs,
75 + Routes.urqrAnimatedPage,
76 + routeArgs: {'export-outputs': 'export-outputs'}, condition: _isCupcake),
77 + SettingsListItem(
78 + "assets/new-ui/settings_row_icons/other.svg", S.current.other, Routes.otherSettingsPage),
79 ]);
80
81 static SettingsSectionData appSettings =
82 SettingsSectionData(S.current.app_settings, "assets/new-ui/cake-setting.svg", [
66 - SettingsListItem("assets/new-ui/settings_row_icons/connections.svg", S.current.connections, Routes.connectionSync),
83 + SettingsListItem("assets/new-ui/settings_row_icons/connections.svg", S.current.connections,
84 + Routes.connectionSync),
85 // SettingsListItem("assets/new-ui/settings_row_icons/defaults.svg", "Defaults", ""),
68 - SettingsListItem("assets/new-ui/settings_row_icons/display.svg", S.current.display, Routes.displaySettingsPage),
69 - SettingsListItem("assets/new-ui/settings_row_icons/security.svg", S.current.security, Routes.securityBackupPage),
70 - SettingsListItem("assets/new-ui/settings_row_icons/backup.svg", S.current.backup, Routes.backup, requireAuth: true, use2fa: (vm)=>vm.settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings),
86 + SettingsListItem("assets/new-ui/settings_row_icons/display.svg", S.current.display,
87 + Routes.displaySettingsPage),
88 + SettingsListItem("assets/new-ui/settings_row_icons/security.svg", S.current.security,
89 + Routes.securityBackupPage),
90 + SettingsListItem("assets/new-ui/settings_row_icons/backup.svg", S.current.backup, Routes.backup,
91 + requireAuth: true,
92 + use2fa: (vm) => vm.settingsStore.shouldRequireTOTP2FAForAllSecurityAndBackupSettings),
93 ]);
94
95 static SettingsSectionData otherSettings = SettingsSectionData("", "", [
74 - SettingsListItem("assets/new-ui/settings_row_icons/support.svg", S.current.settings_support, Routes.support),
75 - SettingsListItem("assets/new-ui/settings_row_icons/info.svg", S.current.about, Routes.aboutPage),
96 + SettingsListItem(
97 + "assets/new-ui/settings_row_icons/support.svg", S.current.settings_support, Routes.support),
98 + SettingsListItem(
99 + "assets/new-ui/settings_row_icons/info.svg", S.current.about, Routes.aboutPage),
100 ]);
101
102 static List<SettingsSectionData> all = [walletSettings, appSettings, otherSettings];
@@ -147,7 +171,8 @@ class SettingsMainPage extends StatelessWidget {
171 child: Row(
172 spacing: 8,
173 children: [
150 - CakeImageWidget(imageUrl: section.titleIconPath,
174 + CakeImageWidget(
175 + imageUrl: section.titleIconPath,
176 colorFilter: ColorFilter.mode(
177 Theme.of(context).colorScheme.onSurfaceVariant,
178 BlendMode.srcIn,
@@ -160,10 +185,10 @@ class SettingsMainPage extends StatelessWidget {
185 ];
186 }).toList(),
187 ),
163 - ),]
164 - ),
188 + ),
189 + ]),
190 ),
191 ]),
192 );
193 }
169 -}
\ No newline at end of file
194 +}
lib/new-ui/pages/swap_page.dart
+26 -21
@@ -51,7 +51,8 @@ import 'package:mobx/mobx.dart';
51 import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
52
53 class NewSwapPage extends StatefulWidget {
54 - NewSwapPage(this.exchangeViewModel, this.authService,this.adrResService, this.initialPaymentRequest,
54 + NewSwapPage(
55 + this.exchangeViewModel, this.authService, this.adrResService, this.initialPaymentRequest,
56 {required this.walletSwitcherViewModel, CryptoCurrency? initialCurrency}) {
57 depositWalletName = exchangeViewModel.depositCurrency == CryptoCurrency.xmr
58 ? exchangeViewModel.wallet.name
@@ -425,11 +426,11 @@ class _NewSwapPageState extends State<NewSwapPage> {
426 Future<String> fetchParsedAddress(
427 BuildContext context, String domain, CryptoCurrency currency) async {
428 printV("$domain");
428 - final parsedAddress = await widget.adrResService.resolve(
429 - query: domain,
430 - wallet: widget.exchangeViewModel.wallet,
431 - currency: currency);
432 - return parsedAddress.isNotEmpty ? parsedAddress.first.parsedAddressByCurrencyMap[currency] ?? '' : '';
429 + final parsedAddress = await widget.adrResService
430 + .resolve(query: domain, wallet: widget.exchangeViewModel.wallet, currency: currency);
431 + return parsedAddress.isNotEmpty
432 + ? parsedAddress.first.parsedAddressByCurrencyMap[currency] ?? ''
433 + : '';
434 }
435
436 void _showFeeAlert(BuildContext context) async {
@@ -472,8 +473,8 @@ class _NewSwapPageState extends State<NewSwapPage> {
473 title: S.of(context).swap,
474 leadingIcon: Icon(Icons.close),
475 onLeadingPressed: Navigator.of(context).maybePop,
475 - trailingIcon: CakeImageWidget(imageUrl:
476 - "assets/new-ui/options.svg",
476 + trailingIcon: CakeImageWidget(
477 + imageUrl: "assets/new-ui/options.svg",
478 colorFilter:
479 ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
480 ),
@@ -543,7 +544,8 @@ class _NewSwapPageState extends State<NewSwapPage> {
544 type: widget.exchangeViewModel.depositCurrency),
545 onPushPasteButton: (context) async {
546 final clipboard = await Clipboard.getData('text/plain');
546 - widget.exchangeViewModel.depositAddress = clipboard?.text ?? '';
547 + widget.exchangeViewModel.depositAddress =
548 + clipboard?.text ?? '';
549
550 final domain = widget.exchangeViewModel.depositAddress;
551 widget.exchangeViewModel.depositAddress =
@@ -600,8 +602,10 @@ class _NewSwapPageState extends State<NewSwapPage> {
602 ? AmountValidator(
603 isAutovalidate: true,
604 currency: widget.exchangeViewModel.receiveCurrency,
603 - minValue: widget.exchangeViewModel.limits.min.toString(),
604 - maxValue: widget.exchangeViewModel.limits.max.toString(),
605 + minValue:
606 + widget.exchangeViewModel.limits.min.toString(),
607 + maxValue:
608 + widget.exchangeViewModel.limits.max.toString(),
609 amountParsingProxy:
610 widget.exchangeViewModel.amountParsingProxy,
611 ).call(value)
@@ -611,7 +615,8 @@ class _NewSwapPageState extends State<NewSwapPage> {
615 type: widget.exchangeViewModel.receiveCurrency),
616 onPushPasteButton: (context) async {
617 final clipboard = await Clipboard.getData('text/plain');
614 - widget.exchangeViewModel.receiveAddress = clipboard?.text ?? '';
618 + widget.exchangeViewModel.receiveAddress =
619 + clipboard?.text ?? '';
620
621 final domain = widget.exchangeViewModel.receiveAddress;
622 widget.exchangeViewModel.receiveAddress =
@@ -783,8 +788,8 @@ class SwapProviderPreview extends StatelessWidget {
788 fontWeight: FontWeight.w400,
789 color: Theme.of(context).colorScheme.onSurfaceVariant),
790 ),
786 - CakeImageWidget(imageUrl:
787 - "assets/new-ui/chooser.svg",
791 + CakeImageWidget(
792 + imageUrl: "assets/new-ui/chooser.svg",
793 colorFilter: ColorFilter.mode(
794 Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
795 )
@@ -980,8 +985,8 @@ class SwapAmountBoxState extends State<SwapAmountBox> {
985 onTap: _presentCurrencyPicker,
986 child: Container(
987 decoration: BoxDecoration(
983 - color: Theme.of(context).colorScheme.surface,
984 - borderRadius: BorderRadius.circular(999999),
988 + color: Theme.of(context).colorScheme.surface,
989 + borderRadius: BorderRadius.circular(999999),
990 ),
991 child: Padding(
992 padding: const EdgeInsets.only(top: 4.0, bottom: 4, left: 4, right: 4),
@@ -1013,11 +1018,11 @@ class SwapAmountBoxState extends State<SwapAmountBox> {
1018 ] else
1019 const SizedBox(width: 10),
1020 Container(
1016 - width:16,height:16,
1021 + width: 16,
1022 + height: 16,
1023 decoration: BoxDecoration(
1018 - borderRadius: BorderRadius.circular(9999999999),
1019 - color: Theme.of(context).colorScheme.surfaceContainerHigh
1020 - ),
1024 + borderRadius: BorderRadius.circular(9999999999),
1025 + color: Theme.of(context).colorScheme.surfaceContainerHigh),
1026 child: Padding(
1027 padding: const EdgeInsets.all(4.0),
1028 child: RotatedBox(
@@ -1069,7 +1074,7 @@ class SwapAmountBoxState extends State<SwapAmountBox> {
1074 amountController.text = widget.exchangeViewModel.depositAmount;
1075 }
1076 },
1072 - onAllButtonPressed: (){
1077 + onAllButtonPressed: () {
1078 setState(() {
1079 _fiatInputMode = false;
1080 });
lib/new-ui/viewmodels/card_customizer/card_customizer_bloc.dart
+6 -12
@@ -19,9 +19,7 @@ class CardCustomizerBloc extends Bloc<CardCustomizerEvent, CardCustomizerState>
19
20 CardCustomizerBloc(this._wallet, {this.lightningMode = false, this.displaySats = false})
21 : super(CardCustomizerNotLoaded(
22 - 0, 0, [CardDesign.genericDefault], [],
23 - "", -1, displaySats, 0)) {
24 -
22 + 0, 0, [CardDesign.genericDefault], [], "", -1, displaySats, 0)) {
23 on<_Init>(_init);
24 on<CardDesignSelected>(_onDesignSelected);
25 on<ColorSelected>(_onColorSelected);
@@ -29,7 +27,6 @@ class CardCustomizerBloc extends Bloc<CardCustomizerEvent, CardCustomizerState>
27 on<DesignSaved>(_onDesignSaved);
28 on<AccountNameChanged>(_onAccountNameChanged);
29
32 -
30 add(_Init());
31 }
32
@@ -96,15 +93,14 @@ class CardCustomizerBloc extends Bloc<CardCustomizerEvent, CardCustomizerState>
93 }
94 final accountName = (account?.label ?? "") as String;
95 late final int accountIndex;
99 - if(account != null) {
96 + if (account != null) {
97 accountIndex = account.id as int;
101 - } else if(lightningMode) {
98 + } else if (lightningMode) {
99 accountIndex = 0;
100 } else {
101 accountIndex = -1;
102 }
106 - final curr =
107 - lightningMode ? CryptoCurrency.btcln : _wallet.currency;
103 + final curr = lightningMode ? CryptoCurrency.btcln : _wallet.currency;
104 final currentDesignSettings = await _loadCurrentDesignSettings(accountIndex);
105 final currentDesign = CardDesign.fromStyleSettings(currentDesignSettings, curr);
106 final availableDesigns = _initAvailableDesigns(lightningMode: lightningMode);
@@ -112,8 +108,7 @@ class CardCustomizerBloc extends Bloc<CardCustomizerEvent, CardCustomizerState>
108 final selectedDesignIndex = _initSelectedDesign(currentDesign);
109 final selectedColor = _initSelectedColor(currentDesign);
110 final availableIconPaths = CardDesign.iconPathsForWalletType(curr);
115 - final selectedIconIndex = _initSelectedIconIndex(
116 - currentDesignSettings, availableIconPaths);
111 + final selectedIconIndex = _initSelectedIconIndex(currentDesignSettings, availableIconPaths);
112
113 emit(CardCustomizerInitial(
114 selectedDesignIndex,
@@ -149,8 +144,7 @@ class CardCustomizerBloc extends Bloc<CardCustomizerEvent, CardCustomizerState>
144 emit(state.copyWith(selectedColorIndex: event.newColorIndex));
145 }
146
152 - void _onIconStyleSelected(
153 - IconStyleSelected event, Emitter<CardCustomizerState> emit) {
147 + void _onIconStyleSelected(IconStyleSelected event, Emitter<CardCustomizerState> emit) {
148 emit(state.copyWith(selectedIconIndex: event.iconIndex));
149 }
150
lib/new-ui/viewmodels/card_customizer/card_customizer_event.dart
-2
@@ -17,14 +17,12 @@ class ColorSelected extends CardCustomizerEvent {
17 ColorSelected(this.newColorIndex);
18 }
19
20 -
20 class AccountNameChanged extends CardCustomizerEvent {
21 final String newAccountName;
22
23 AccountNameChanged(this.newAccountName);
24 }
25
27 -
26 class DesignSaved extends CardCustomizerEvent {}
27
28 class IconStyleSelected extends CardCustomizerEvent {
lib/new-ui/viewmodels/card_customizer/card_customizer_state.dart
+23 -9
@@ -61,7 +61,15 @@ sealed class CardCustomizerState {
61 }
62
63 final class CardCustomizerNotLoaded extends CardCustomizerState {
64 - CardCustomizerNotLoaded(super.selectedDesignIndex, super.selectedColorIndex, super.availableDesigns, super.availableColors, super.accountName, super.accountIndex, super.displaySats, super.cardOrder);
64 + CardCustomizerNotLoaded(
65 + super.selectedDesignIndex,
66 + super.selectedColorIndex,
67 + super.availableDesigns,
68 + super.availableColors,
69 + super.accountName,
70 + super.accountIndex,
71 + super.displaySats,
72 + super.cardOrder);
73
74 @override
75 CardCustomizerState copyWith(
@@ -91,10 +99,9 @@ final class CardCustomizerInitial extends CardCustomizerState {
99 int cardOrder, {
100 List<CardIconPath> availableIconPaths = const [],
101 int selectedIconIndex = 0,
94 - }) : super(selectedDesignIndex, selectedColorIndex, availableDesigns,
95 - availableColors, accountName, accountIndex, displaySats, cardOrder,
96 - availableIconPaths: availableIconPaths,
97 - selectedIconIndex: selectedIconIndex);
102 + }) : super(selectedDesignIndex, selectedColorIndex, availableDesigns, availableColors,
103 + accountName, accountIndex, displaySats, cardOrder,
104 + availableIconPaths: availableIconPaths, selectedIconIndex: selectedIconIndex);
105
106 CardCustomizerInitial copyWith({
107 int? selectedDesignIndex,
@@ -124,10 +131,17 @@ final class CardCustomizerInitial extends CardCustomizerState {
131 }
132
133 final class CardCustomizerSaved extends CardCustomizerState {
127 - CardCustomizerSaved(super.selectedDesignIndex, super.selectedColorIndex,
128 - super.availableDesigns, super.availableColors, super.accountName,
129 - super.accountIndex, super.displaySats, super.cardOrder,
130 - {super.availableIconPaths, super.selectedIconIndex});
134 + CardCustomizerSaved(
135 + super.selectedDesignIndex,
136 + super.selectedColorIndex,
137 + super.availableDesigns,
138 + super.availableColors,
139 + super.accountName,
140 + super.accountIndex,
141 + super.displaySats,
142 + super.cardOrder,
143 + {super.availableIconPaths,
144 + super.selectedIconIndex});
145
146 @override
147 CardCustomizerState copyWith(
lib/new-ui/viewmodels/lightning_username/lightning_username_bloc.dart
+4 -2
@@ -52,7 +52,8 @@ class LightningUsernameBloc extends Bloc<LightningUsernameEvent, LightningUserna
52 }
53 }
54
55 - Future<void> onUsernameSaveRequested(RequestUsernameSave event, Emitter<LightningUsernameState> emit) async {
55 + Future<void> onUsernameSaveRequested(
56 + RequestUsernameSave event, Emitter<LightningUsernameState> emit) async {
57 emit(LightningUsernameSaving(state.username));
58 try {
59 await bitcoin!.setLightningUsername(_wallet, state.username);
@@ -64,7 +65,8 @@ class LightningUsernameBloc extends Bloc<LightningUsernameEvent, LightningUserna
65 return;
66 }
67 }
67 - emit(LightningUsernameError(state.username, UsernameError(bitcoin!.getBreezSdkError(e) ?? e.toString())));
68 + emit(LightningUsernameError(
69 + state.username, UsernameError(bitcoin!.getBreezSdkError(e) ?? e.toString())));
70 }
71 }
72
lib/new-ui/viewmodels/lightning_username/lightning_username_event.dart
+1 -1
@@ -11,4 +11,4 @@ final class ChangeUsername extends LightningUsernameEvent {
11 ChangeUsername(this.newUsername);
12 }
13
14 -final class RequestUsernameSave extends LightningUsernameEvent {}
\ No newline at end of file
14 +final class RequestUsernameSave extends LightningUsernameEvent {}
lib/new-ui/widgets/addresses_page/address_info.dart
+1 -2
@@ -34,8 +34,7 @@ class AddressInfoPopup extends StatelessWidget {
34 children: [
35 Text('Index: ${walletAddressEditOrCreateViewModel.index}'),
36 SizedBox(height: 16),
37 - Text(
38 - 'Derivation Path: ${walletAddressEditOrCreateViewModel.derivationPath}'),
37 + Text('Derivation Path: ${walletAddressEditOrCreateViewModel.derivationPath}'),
38 ],
39 ),
40 ),
lib/new-ui/widgets/addresses_page/address_label_input.dart
+1 -2
@@ -33,8 +33,7 @@ class _AddressLabelInputPopupState extends State<AddressLabelInputPopup> {
33 (AddressEditOrCreateState state) {
34 if (state is AddressSavedSuccessfully) {
35 WidgetsBinding.instance.addPostFrameCallback((_) {
36 - if (mounted)
37 - Navigator.of(context).pop(widget.walletAddressEditOrCreateViewModel.label);
36 + if (mounted) Navigator.of(context).pop(widget.walletAddressEditOrCreateViewModel.label);
37 });
38 }
39 });
lib/new-ui/widgets/animated_dropdown.dart
+21 -12
@@ -2,7 +2,7 @@ import 'package:cake_wallet/new-ui/widgets/dropdown_row.dart';
2 import 'package:flutter/material.dart';
3
4 class AnimatedDropdown extends StatefulWidget {
5 - const AnimatedDropdown({super.key,required this.content, required this.dropdownText});
5 + const AnimatedDropdown({super.key, required this.content, required this.dropdownText});
6
7 final Widget content;
8 final String dropdownText;
@@ -23,21 +23,30 @@ class _AnimatedDropdownState extends State<AnimatedDropdown> {
23 shape: RoundedSuperellipseBorder(
24 borderRadius: BorderRadius.circular(20),
25 ),
26 - color: Theme.of(context).colorScheme.surfaceContainer,),
26 + color: Theme.of(context).colorScheme.surfaceContainer,
27 + ),
28 child: Column(
29 children: [
29 - DropdownRow(expanded: _expanded, text: widget.dropdownText,onTap: (){
30 - setState(() {
31 - _expanded = !_expanded;
32 - });
33 - },),
34 - AnimatedOpacity(duration:Duration(milliseconds: 150),opacity:_expanded?1:0,child: Divider(height: 1,thickness: 1,)),
30 + DropdownRow(
31 + expanded: _expanded,
32 + text: widget.dropdownText,
33 + onTap: () {
34 + setState(() {
35 + _expanded = !_expanded;
36 + });
37 + },
38 + ),
39 + AnimatedOpacity(
40 + duration: Duration(milliseconds: 150),
41 + opacity: _expanded ? 1 : 0,
42 + child: Divider(
43 + height: 1,
44 + thickness: 1,
45 + )),
46 AnimatedCrossFade(
36 - firstChild: Container(height:0),
47 + firstChild: Container(height: 0),
48 secondChild: widget.content,
38 - crossFadeState: _expanded
39 - ? CrossFadeState.showSecond
40 - : CrossFadeState.showFirst,
49 + crossFadeState: _expanded ? CrossFadeState.showSecond : CrossFadeState.showFirst,
50 duration: const Duration(milliseconds: 300),
51 sizeCurve: Curves.easeOutCubic,
52 )
lib/new-ui/widgets/apps_widget.dart
+7 -7
@@ -94,7 +94,11 @@ class AppsWidget extends StatelessWidget {
94 ),
95 softWrap: true,
96 ),
97 - isCake == true ? CakeImageWidget(imageUrl: "assets/new-ui/cakelabs-icon.svg", color: Theme.of(context).colorScheme.onSurfaceVariant) : SizedBox(),
97 + isCake == true
98 + ? CakeImageWidget(
99 + imageUrl: "assets/new-ui/cakelabs-icon.svg",
100 + color: Theme.of(context).colorScheme.onSurfaceVariant)
101 + : SizedBox(),
102 ],
103 ),
104 SizedBox(height: 5),
@@ -114,7 +118,6 @@ class AppsWidget extends StatelessWidget {
118 color: Theme.of(context).colorScheme.onSurfaceVariant,
119 size: 20,
120 )
117 -
121 ],
122 ),
123 if (hint != null) ...[
@@ -137,11 +140,8 @@ class AppsWidget extends StatelessWidget {
140 ),
141 ],
142 );
140 - }
141 - else {
142 - return Stack(
143 -
144 - );
143 + } else {
144 + return Stack();
145 }
146 }
147 }
lib/new-ui/widgets/bridge/confirm_details_card.dart
+3 -2
@@ -17,7 +17,7 @@ class ConfirmDetailsCard extends StatelessWidget {
17 builder: (_) {
18 final feeParts = <String>[
19 bridgeViewModel.quoteNativeFeeFormattedForDisplay,
20 - bridgeViewModel.quoteNativeFiatFeeFormattedForDisplay,
20 + bridgeViewModel.quoteNativeFiatFeeFormattedForDisplay,
21 ];
22 final feeLine = feeParts.join(' ');
23
@@ -40,7 +40,8 @@ class ConfirmDetailsCard extends StatelessWidget {
40 ),
41 ExpandableBridgeDetailRow(
42 label: S.of(context).to,
43 - title: bridgeViewModel.destinationWalletName ?? bridgeViewModel.recipientAddress.trim(),
43 + title: bridgeViewModel.destinationWalletName ??
44 + bridgeViewModel.recipientAddress.trim(),
45 address: bridgeViewModel.recipientAddress.trim(),
46 showChevron: bridgeViewModel.destinationWalletName != null,
47 ),
lib/new-ui/widgets/bridge/transfer_history_row.dart
+4 -2
@@ -88,7 +88,8 @@ class TransferHistoryRow extends StatelessWidget {
88 child: Stack(
89 children: [
90 CakeImageWidget(
91 - imageUrl: 'assets/new-ui/crypto_full_icons/${sourceChainName?.toLowerCase()}.svg',
91 + imageUrl:
92 + 'assets/new-ui/crypto_full_icons/${sourceChainName?.toLowerCase()}.svg',
93 width: 28,
94 height: 28,
95 ),
@@ -96,7 +97,8 @@ class TransferHistoryRow extends StatelessWidget {
97 top: 14,
98 left: 12,
99 child: CakeImageWidget(
99 - imageUrl: 'assets/new-ui/crypto_full_icons/${destChainName?.toLowerCase()}.svg',
100 + imageUrl:
101 + 'assets/new-ui/crypto_full_icons/${destChainName?.toLowerCase()}.svg',
102 width: 28,
103 height: 28,
104 ),
lib/new-ui/widgets/changelog_modal.dart
+1 -1
@@ -107,7 +107,7 @@ class _ChangelogModalState extends State<ChangelogModal> {
107 NewPrimaryButton(
108 onPressed: () {
109 try {
110 - launchUrl(Uri.https("blog.cakewallet.com"));
110 + launchUrl(Uri.https("blog.cakewallet.com"));
111 } catch (_) {}
112 },
113 text: S.of(context).view_more_info,
lib/new-ui/widgets/coin_control_page/coin_control_list_item.dart
+75 -61
@@ -14,10 +14,11 @@ class CoinControlListItem extends StatelessWidget {
14 required this.isFrozen,
15 required this.isChange,
16 required this.isSilentPayment,
17 - required this.isFirst,
17 + required this.isFirst,
18 required this.isLast,
19 required this.isLoading,
20 - this.onCheckBoxTap, required this.hasCheckbox,
20 + this.onCheckBoxTap,
21 + required this.hasCheckbox,
22 });
23
24 final String note;
@@ -37,61 +38,70 @@ class CoinControlListItem extends StatelessWidget {
38 @override
39 Widget build(BuildContext context) {
40 return Container(
40 - height:70,
41 - decoration: BoxDecoration(
42 - color: Theme.of(context).colorScheme.surfaceContainer,
43 - borderRadius: BorderRadius.vertical(
44 - top: isFirst ? Radius.circular(12) : Radius.circular(0),
45 - bottom: isLast ? Radius.circular(12) : Radius.circular(0),
41 + height: 70,
42 + decoration: BoxDecoration(
43 + color: Theme.of(context).colorScheme.surfaceContainer,
44 + borderRadius: BorderRadius.vertical(
45 + top: isFirst ? Radius.circular(12) : Radius.circular(0),
46 + bottom: isLast ? Radius.circular(12) : Radius.circular(0),
47 + ),
48 ),
47 - ),
48 - child: Padding(
49 - padding: const EdgeInsets.symmetric(horizontal: 12.0),
50 - child: Row(
51 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
52 - children: [
53 - Row(
54 - spacing: 12,
55 - children: [
56 - _getLeading(context),
57 - // NewSimpleCheckbox(value: isSending, onChanged: (value){onCheckBoxTap?.call();}),
58 - Column(
59 - crossAxisAlignment: CrossAxisAlignment.start,
60 - mainAxisAlignment: MainAxisAlignment.center,
61 - spacing: 4,
62 - children: [
63 - Row(
64 - spacing:4,
65 - children: [
66 - Text(amount, style: TextStyle(fontSize:14,fontWeight: FontWeight.w400,color: Theme.of(context).colorScheme.onSurface),),
67 - if(address.toLowerCase().contains("mweb")) // hack carried over from old ui, we really should just have a boolean in the object
68 - CakeImageWidget(imageUrl:
69 - "assets/new-ui/address-type-picker-icons/mweb.svg",
49 + child: Padding(
50 + padding: const EdgeInsets.symmetric(horizontal: 12.0),
51 + child: Row(
52 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
53 + children: [
54 + Row(
55 + spacing: 12,
56 + children: [
57 + _getLeading(context),
58 + // NewSimpleCheckbox(value: isSending, onChanged: (value){onCheckBoxTap?.call();}),
59 + Column(
60 + crossAxisAlignment: CrossAxisAlignment.start,
61 + mainAxisAlignment: MainAxisAlignment.center,
62 + spacing: 4,
63 + children: [
64 + Row(
65 + spacing: 4,
66 + children: [
67 + Text(
68 + amount,
69 + style: TextStyle(
70 + fontSize: 14,
71 + fontWeight: FontWeight.w400,
72 + color: Theme.of(context).colorScheme.onSurface),
73 + ),
74 + if (address.toLowerCase().contains(
75 + "mweb")) // hack carried over from old ui, we really should just have a boolean in the object
76 + CakeImageWidget(
77 + imageUrl: "assets/new-ui/address-type-picker-icons/mweb.svg",
78 + width: 18,
79 + height: 18,
80 + colorFilter: ColorFilter.mode(
81 + Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
82 + ),
83 + if (isSilentPayment)
84 + CakeImageWidget(
85 + imageUrl: "assets/new-ui/address-type-picker-icons/silent.svg",
86 width: 18,
87 height: 18,
88 colorFilter: ColorFilter.mode(
89 Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
90 ),
75 - if(isSilentPayment)
76 - CakeImageWidget(imageUrl:
77 - "assets/new-ui/address-type-picker-icons/silent.svg",
78 - width: 18,
79 - height: 18,
80 - colorFilter: ColorFilter.mode(
81 - Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
82 - ),
91 ],
84 - ),
85 - AutoSizeText(
86 - '${address.substring(0, 5)}...${address.substring(address.length - 5)}',
87 - style: TextStyle(fontSize:12,fontWeight: FontWeight.w400,color: Theme.of(context).colorScheme.onSurfaceVariant),
88 - maxLines: 1,
89 - ),
90 - ],
91 -
92 - )
93 - ],
94 - ),
92 + ),
93 + AutoSizeText(
94 + '${address.substring(0, 5)}...${address.substring(address.length - 5)}',
95 + style: TextStyle(
96 + fontSize: 12,
97 + fontWeight: FontWeight.w400,
98 + color: Theme.of(context).colorScheme.onSurfaceVariant),
99 + maxLines: 1,
100 + ),
101 + ],
102 + )
103 + ],
104 + ),
105 Row(
106 spacing: 8,
107 children: [
@@ -102,8 +112,8 @@ class CoinControlListItem extends StatelessWidget {
112 fontWeight: FontWeight.w400,
113 color: Theme.of(context).colorScheme.onSurfaceVariant),
114 ),
105 - CakeImageWidget(imageUrl:
106 - "assets/new-ui/arrow_right.svg",
115 + CakeImageWidget(
116 + imageUrl: "assets/new-ui/arrow_right.svg",
117 colorFilter: ColorFilter.mode(
118 Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
119 ),
@@ -111,24 +121,28 @@ class CoinControlListItem extends StatelessWidget {
121 )
122 ],
123 ),
114 - )
115 - );
124 + ));
125 }
126
127 Widget _getLeading(BuildContext context) {
119 - if(isLoading) {
120 - return CircularProgressIndicator(color: Theme.of(context).colorScheme.primary,);
128 + if (isLoading) {
129 + return CircularProgressIndicator(
130 + color: Theme.of(context).colorScheme.primary,
131 + );
132 }
133
123 - if(isFrozen) {
124 - return CakeImageWidget(imageUrl:"assets/new-ui/frozen.svg");
134 + if (isFrozen) {
135 + return CakeImageWidget(imageUrl: "assets/new-ui/frozen.svg");
136 }
137
127 - if(!hasCheckbox) {
138 + if (!hasCheckbox) {
139 return SizedBox.shrink();
140 }
141
131 - return NewSimpleCheckbox(value: isSending, onChanged: (value){onCheckBoxTap?.call();});
132 -
142 + return NewSimpleCheckbox(
143 + value: isSending,
144 + onChanged: (value) {
145 + onCheckBoxTap?.call();
146 + });
147 }
148 }
lib/new-ui/widgets/coins_page/action_row/coin_action_row.dart
+67 -68
@@ -27,7 +27,8 @@ import '../../../pages/receive_page.dart';
27 import 'coin_action_button.dart';
28
29 class CoinActionRow extends StatelessWidget {
30 - const CoinActionRow({super.key, this.lightningMode = false, this.showSwap = true, required this.walletType});
30 + const CoinActionRow(
31 + {super.key, this.lightningMode = false, this.showSwap = true, required this.walletType});
32
33 final bool lightningMode;
34 final bool showSwap;
@@ -43,8 +44,8 @@ class CoinActionRow extends StatelessWidget {
44 spacing: MediaQuery.of(context).size.width * 0.05,
45 children: [
46 CoinActionButton(
46 - icon: CakeImageWidget(imageUrl:
47 - "assets/new-ui/send.svg",
47 + icon: CakeImageWidget(
48 + imageUrl: "assets/new-ui/send.svg",
49 colorFilter: ColorFilter.mode(
50 Theme.of(context).colorScheme.primary,
51 BlendMode.srcIn,
@@ -75,14 +76,14 @@ class CoinActionRow extends StatelessWidget {
76 );
77 } else {
78 Map<String, dynamic>? args;
78 - if (lightningMode) args = {'coinTypeToSpendFrom' : UnspentCoinType.lightning};
79 + if (lightningMode) args = {'coinTypeToSpendFrom': UnspentCoinType.lightning};
80 Navigator.of(context).pushNamed(Routes.send, arguments: args);
81 }
82 },
83 ),
84 CoinActionButton(
84 - icon: CakeImageWidget(imageUrl:
85 - "assets/new-ui/receive.svg",
85 + icon: CakeImageWidget(
86 + imageUrl: "assets/new-ui/receive.svg",
87 colorFilter: ColorFilter.mode(
88 Theme.of(context).colorScheme.primary,
89 BlendMode.srcIn,
@@ -96,7 +97,7 @@ class CoinActionRow extends StatelessWidget {
97 context: context,
98 barrierColor: Colors.black.withAlpha(60),
99 builder: (context) {
99 - return Material(child: ModalNavigator(parentContext:context,rootPage: page));
100 + return Material(child: ModalNavigator(parentContext: context, rootPage: page));
101 },
102 );
103 } else {
@@ -114,8 +115,8 @@ class CoinActionRow extends StatelessWidget {
115 ),
116 if (showSwap)
117 CoinActionButton(
117 - icon: CakeImageWidget(imageUrl:
118 - "assets/new-ui/exchange.svg",
118 + icon: CakeImageWidget(
119 + imageUrl: "assets/new-ui/exchange.svg",
120 colorFilter: ColorFilter.mode(
121 Theme.of(context).colorScheme.primary,
122 BlendMode.srcIn,
@@ -123,7 +124,8 @@ class CoinActionRow extends StatelessWidget {
124 ),
125 label: S.of(context).swap,
126 action: () {
126 - final page = getIt.get<NewSwapPage>(param2: lightningMode ? CryptoCurrency.btcln : null);
127 + final page =
128 + getIt.get<NewSwapPage>(param2: lightningMode ? CryptoCurrency.btcln : null);
129 if (FeatureFlag.hasNewUiExtraPages) {
130 CupertinoScaffold.showCupertinoModalBottomSheet(
131 context: context,
@@ -140,8 +142,8 @@ class CoinActionRow extends StatelessWidget {
142 },
143 ),
144 CoinActionButton(
143 - icon: CakeImageWidget(imageUrl:
144 - "assets/new-ui/scan.svg",
145 + icon: CakeImageWidget(
146 + imageUrl: "assets/new-ui/scan.svg",
147 colorFilter: ColorFilter.mode(
148 Theme.of(context).colorScheme.primary,
149 BlendMode.srcIn,
@@ -156,67 +158,64 @@ class CoinActionRow extends StatelessWidget {
158 }
159
160 Future<void> _onPressedScan(BuildContext context) async {
159 - final code = await presentQRScanner(context, showHelp: true);
161 + final code = await presentQRScanner(context, showHelp: true);
162
161 - if (code == null || code.isEmpty) return;
163 + if (code == null || code.isEmpty) return;
164
163 - late final PaymentRequest req;
164 - var unspentCoinType = UnspentCoinType.any;
165 - if (SendViewModelBase.isNonZeroAmountLightningInvoice(code)) {
166 - unspentCoinType = UnspentCoinType.lightning;
167 - final amount = getBolt11Amount(code)?.toString() ?? "0";
168 - req = PaymentRequest(code, amount, "", "", "");
169 - } else if (SendViewModelBase.isLnurlInvoice(code)) {
170 - unspentCoinType = UnspentCoinType.lightning;
171 - final amount = (await LNURL.getPayRequestAmount(code))?.toString() ?? "0";
172 - req = PaymentRequest(code, amount, "", "", "");
173 - } else if (OpenCryptoPayService.isOpenCryptoPayQR(code)) {
174 - req = PaymentRequest(code, "", "", "", "");
175 - } else
176 - if (Uri.tryParse(code)?.scheme == "wc") {
177 - if (!isWalletConnectCompatibleChain(walletType)) {
178 - showPopUp<void>(
179 - context: context,
180 - builder: (context) => AlertWithOneAction(
181 - alertTitle: "WalletConnect",
182 - alertContent: S
183 - .of(context)
184 - .switchToWCCompatibleWallet(walletConnectCompatibleChainsLabel()),
185 - buttonText: "OK",
186 - buttonAction: Navigator.of(context).pop));
187 - return;
188 - }
189 -
190 - Navigator.of(context)
191 - .pushNamed(Routes.walletConnectConnectionsListing, arguments: Uri.parse(code));
192 - return;
193 - } else if(["http", "https", "tcp"].contains(Uri.tryParse(code)?.scheme)) {
194 - Navigator.of(context).pushNamed(Routes.newNode,
195 - arguments: {"editingNode": Node.fromUri(Uri.parse(code), walletType)});
165 + late final PaymentRequest req;
166 + var unspentCoinType = UnspentCoinType.any;
167 + if (SendViewModelBase.isNonZeroAmountLightningInvoice(code)) {
168 + unspentCoinType = UnspentCoinType.lightning;
169 + final amount = getBolt11Amount(code)?.toString() ?? "0";
170 + req = PaymentRequest(code, amount, "", "", "");
171 + } else if (SendViewModelBase.isLnurlInvoice(code)) {
172 + unspentCoinType = UnspentCoinType.lightning;
173 + final amount = (await LNURL.getPayRequestAmount(code))?.toString() ?? "0";
174 + req = PaymentRequest(code, amount, "", "", "");
175 + } else if (OpenCryptoPayService.isOpenCryptoPayQR(code)) {
176 + req = PaymentRequest(code, "", "", "", "");
177 + } else if (Uri.tryParse(code)?.scheme == "wc") {
178 + if (!isWalletConnectCompatibleChain(walletType)) {
179 + showPopUp<void>(
180 + context: context,
181 + builder: (context) => AlertWithOneAction(
182 + alertTitle: "WalletConnect",
183 + alertContent:
184 + S.of(context).switchToWCCompatibleWallet(walletConnectCompatibleChainsLabel()),
185 + buttonText: "OK",
186 + buttonAction: Navigator.of(context).pop));
187 return;
197 -
198 - }else {
199 - final uri = Uri.tryParse(code);
200 - if (uri == null) return;
201 - req = PaymentRequest.fromUri(uri);
188 }
189
204 - final sendPage = getIt.get<NewSendPage>(
205 - param1: SendPageParams(
206 - initialPaymentRequest: req,
207 - unspentCoinType: unspentCoinType,
208 - ),
209 - );
190 + Navigator.of(context)
191 + .pushNamed(Routes.walletConnectConnectionsListing, arguments: Uri.parse(code));
192 + return;
193 + } else if (["http", "https", "tcp"].contains(Uri.tryParse(code)?.scheme)) {
194 + Navigator.of(context).pushNamed(Routes.newNode,
195 + arguments: {"editingNode": Node.fromUri(Uri.parse(code), walletType)});
196 + return;
197 + } else {
198 + final uri = Uri.tryParse(code);
199 + if (uri == null) return;
200 + req = PaymentRequest.fromUri(uri);
201 + }
202
211 - CupertinoScaffold.showCupertinoModalBottomSheet(
212 - context: context,
213 - barrierColor: Colors.black.withAlpha(60),
214 - builder: (context) => Material(
215 - child: ModalNavigator(
216 - rootPage: sendPage,
217 - parentContext: context,
218 - ),
203 + final sendPage = getIt.get<NewSendPage>(
204 + param1: SendPageParams(
205 + initialPaymentRequest: req,
206 + unspentCoinType: unspentCoinType,
207 + ),
208 + );
209 +
210 + CupertinoScaffold.showCupertinoModalBottomSheet(
211 + context: context,
212 + barrierColor: Colors.black.withAlpha(60),
213 + builder: (context) => Material(
214 + child: ModalNavigator(
215 + rootPage: sendPage,
216 + parentContext: context,
217 ),
220 - );
221 - }
218 + ),
219 + );
220 + }
221 }
lib/new-ui/widgets/coins_page/assets_history/asset_tile.dart
+13 -9
@@ -18,7 +18,10 @@ class AssetTile extends StatelessWidget {
18 this.title,
19 this.trailingText,
20 this.modalMode = AssetDetailsModalModes.normal,
21 - required this.wallet, required this.showSwap, required this.isFirst, required this.isLast});
21 + required this.wallet,
22 + required this.showSwap,
23 + required this.isFirst,
24 + required this.isLast});
25
26 final BalanceRecord balance;
27 final bool showSecondary;
@@ -37,7 +40,7 @@ class AssetTile extends StatelessWidget {
40 final iconPath = balance.asset.iconPath ?? "";
41
42 return GestureDetector(
40 - onTap: (){
43 + onTap: () {
44 showModalBottomSheet(
45 context: context,
46 isScrollControlled: true,
@@ -120,11 +123,12 @@ class AssetTile extends StatelessWidget {
123 title ?? balance.asset.fullName ?? balance.asset.name,
124 style: TextStyle(fontWeight: FontWeight.w500),
125 ),
123 - if(trailingText != null)
124 - Text(
125 - trailingText!,
126 - style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
127 - ),
126 + if (trailingText != null)
127 + Text(
128 + trailingText!,
129 + style: TextStyle(
130 + color: Theme.of(context).colorScheme.onSurfaceVariant),
131 + ),
132 ],
133 ),
134 Padding(
@@ -133,8 +137,8 @@ class AssetTile extends StatelessWidget {
137 fit: BoxFit.scaleDown,
138 alignment: Alignment.centerLeft,
139 child: Text(
136 - "${showSecondary ?balance.secondAvailableBalance: balance.availableBalance} ${balance.formattedAssetTitle.safeSubString(0, 6)}",
137 - maxLines:1,
140 + "${showSecondary ? balance.secondAvailableBalance : balance.availableBalance} ${balance.formattedAssetTitle.safeSubString(0, 6)}",
141 + maxLines: 1,
142 style: TextStyle(
143 color: Theme.of(context).colorScheme.onSurfaceVariant,
144 ),
lib/new-ui/widgets/coins_page/assets_history/assets_history_section.dart
+26 -18
@@ -47,7 +47,8 @@ class _AssetsHistorySectionState extends State<AssetsHistorySection> {
47
48 void reloadTabs() {
49 final oldTabLength = tabs.length;
50 - final hasAssetsTab = widget.dashboardViewModel.balanceViewModel.isHomeScreenSettingsEnabled || (widget.dashboardViewModel.hasMweb && widget.dashboardViewModel.mwebEnabled);
50 + final hasAssetsTab = widget.dashboardViewModel.balanceViewModel.isHomeScreenSettingsEnabled ||
51 + (widget.dashboardViewModel.hasMweb && widget.dashboardViewModel.mwebEnabled);
52 final hasNftTab = isNFTACtivatedChain(widget.dashboardViewModel.wallet.type,
53 chainId: widget.dashboardViewModel.wallet.chainId);
54 tabs = [
@@ -56,12 +57,14 @@ class _AssetsHistorySectionState extends State<AssetsHistorySection> {
57 S.current.assets,
58 AssetsSection(
59 dashboardViewModel: widget.dashboardViewModel,
59 - ), AssetsHistorySectionActionButton(S.current.tokens, "assets/new-ui/options_slider.svg", (){
60 - Navigator.of(context).pushNamed(
61 - Routes.homeSettings,
62 - arguments: widget.dashboardViewModel.balanceViewModel,
63 - );
64 - })),
60 + ),
61 + AssetsHistorySectionActionButton(S.current.tokens, "assets/new-ui/options_slider.svg",
62 + () {
63 + Navigator.of(context).pushNamed(
64 + Routes.homeSettings,
65 + arguments: widget.dashboardViewModel.balanceViewModel,
66 + );
67 + })),
68 AssetsHistorySectionTab(
69 S.current.history,
70 HistorySection(
@@ -69,9 +72,14 @@ class _AssetsHistorySectionState extends State<AssetsHistorySection> {
72 roundedTopSection: hasAssetsTab || hasNftTab,
73 dashboardViewModel: widget.dashboardViewModel,
74 short: true,
72 - ), AssetsHistorySectionActionButton(S.current.all_pascal_case, "assets/new-ui/arrow_right.svg", (){openHistoryModal(context);})),
75 + ),
76 + AssetsHistorySectionActionButton(
77 + S.current.all_pascal_case, "assets/new-ui/arrow_right.svg", () {
78 + openHistoryModal(context);
79 + })),
80 if (hasNftTab)
74 - AssetsHistorySectionTab(S.current.nfts, NFTListingPage(nftViewModel: widget.nftViewModel), null)
81 + AssetsHistorySectionTab(
82 + S.current.nfts, NFTListingPage(nftViewModel: widget.nftViewModel), null)
83 ];
84 if (oldTabLength != tabs.length) {
85 setState(() {
@@ -85,23 +93,23 @@ class _AssetsHistorySectionState extends State<AssetsHistorySection> {
93 super.initState();
94 reloadTabs();
95
88 - reaction((_)=>widget.dashboardViewModel.balanceViewModel.formattedBalances, (value) {
96 + reaction((_) => widget.dashboardViewModel.balanceViewModel.formattedBalances, (value) {
97 reloadTabs();
98 });
91 - reaction((_)=>widget.dashboardViewModel.mwebEnabled, (_)=>reloadTabs());
99 + reaction((_) => widget.dashboardViewModel.mwebEnabled, (_) => reloadTabs());
100 }
101
102 @override
103 Widget build(BuildContext context) {
104 return SliverMainAxisGroup(
105 slivers: [
98 - if(tabs.length>1)
99 - AssetsTopBar(
106 + if (tabs.length > 1)
107 + AssetsTopBar(
108 onTransactionHistoryOpened: () => openHistoryModal(context),
101 - dashboardViewModel: widget.dashboardViewModel,
102 - tabs: tabs,
103 - onTabChange: (index) {
104 - setState(() {
109 + dashboardViewModel: widget.dashboardViewModel,
110 + tabs: tabs,
111 + onTabChange: (index) {
112 + setState(() {
113 _selectedTab = index;
114 });
115 },
@@ -109,7 +117,7 @@ class _AssetsHistorySectionState extends State<AssetsHistorySection> {
117 ),
118 if (tabs.length == 1)
119 Observer(
112 - builder:(_)=> HistoryTopBar(
120 + builder: (_) => HistoryTopBar(
121 onTap: () => openHistoryModal(context),
122 roundedBottom: widget.dashboardViewModel.itemsShort.isEmpty,
123 ),
lib/new-ui/widgets/coins_page/assets_history/assets_section.dart
+52 -50
@@ -4,7 +4,6 @@ import 'package:cw_core/crypto_currency.dart';
4 import 'package:flutter/material.dart';
5 import 'package:flutter_mobx/flutter_mobx.dart';
6
7 -
7 import 'asset_tile.dart';
8
9 class AssetsSection extends StatelessWidget {
@@ -14,64 +13,65 @@ class AssetsSection extends StatelessWidget {
13
14 @override
15 Widget build(BuildContext context) {
17 -
16 return SliverToBoxAdapter(
17 child: Padding(
18 padding: const EdgeInsets.only(bottom: 64.0),
21 - child: Observer(
22 - builder: (context) {
23 - final hasMweb = dashboardViewModel.hasMweb && dashboardViewModel.mwebEnabled;
24 - return ListView.separated(
25 - shrinkWrap: true,
26 - padding: EdgeInsets.symmetric(vertical: 18),
27 - physics: NeverScrollableScrollPhysics(),
28 - itemCount: dashboardViewModel.balanceViewModel.formattedBalances.length + (hasMweb ? 1 : 0),
29 - separatorBuilder: (context, index) => Padding(
30 - padding: const EdgeInsets.symmetric(horizontal: 18.0),
31 - child: Container(
32 - color: Theme.of(context).colorScheme.surfaceContainer,
33 - height:1,
34 - child: Padding(
35 - padding: const EdgeInsets.symmetric(horizontal: 8.0),
36 - child: Container(color: Theme.of(context).colorScheme.surfaceContainerHigh,),
19 + child: Observer(builder: (context) {
20 + final hasMweb = dashboardViewModel.hasMweb && dashboardViewModel.mwebEnabled;
21 + return ListView.separated(
22 + shrinkWrap: true,
23 + padding: EdgeInsets.symmetric(vertical: 18),
24 + physics: NeverScrollableScrollPhysics(),
25 + itemCount:
26 + dashboardViewModel.balanceViewModel.formattedBalances.length + (hasMweb ? 1 : 0),
27 + separatorBuilder: (context, index) => Padding(
28 + padding: const EdgeInsets.symmetric(horizontal: 18.0),
29 + child: Container(
30 + color: Theme.of(context).colorScheme.surfaceContainer,
31 + height: 1,
32 + child: Padding(
33 + padding: const EdgeInsets.symmetric(horizontal: 8.0),
34 + child: Container(
35 + color: Theme.of(context).colorScheme.surfaceContainerHigh,
36 ),
37 ),
38 ),
40 - itemBuilder: (context, index) {
41 - return Observer(builder: (context) {
42 - if (hasMweb) {
43 - return AssetTile(
44 - showSwap: dashboardViewModel.isEnabledSwapAction,
45 - balance: dashboardViewModel.balanceViewModel.formattedBalances.first,
46 - showSecondary: index > 0 ? true : false,
47 - wallet: dashboardViewModel.wallet,
48 - chainIconPath: index > 0 ? dashboardViewModel.wallet.currency.chainIconPath! : "",
49 - trailingText: index > 0 ? "MWEB" : null,
50 - modalMode: index > 0
51 - ? AssetDetailsModalModes.ltcPrivate
52 - : AssetDetailsModalModes.ltcTransparent,
53 - isFirst: index == 0,
54 - isLast: index != 0,
55 - title: index > 0 ? "Litecoin Private" : null,
56 - );
57 - }
58 -
59 - final balance = dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index);
39 + ),
40 + itemBuilder: (context, index) {
41 + return Observer(builder: (context) {
42 + if (hasMweb) {
43 return AssetTile(
44 showSwap: dashboardViewModel.isEnabledSwapAction,
62 - showBridgeButton: dashboardViewModel.showBridge(balance.asset),
63 - balance: balance,
45 + balance: dashboardViewModel.balanceViewModel.formattedBalances.first,
46 + showSecondary: index > 0 ? true : false,
47 wallet: dashboardViewModel.wallet,
48 + chainIconPath:
49 + index > 0 ? dashboardViewModel.wallet.currency.chainIconPath! : "",
50 + trailingText: index > 0 ? "MWEB" : null,
51 + modalMode: index > 0
52 + ? AssetDetailsModalModes.ltcPrivate
53 + : AssetDetailsModalModes.ltcTransparent,
54 isFirst: index == 0,
66 - isLast: index == dashboardViewModel.balanceViewModel.formattedBalances.length-1,
67 - chainIconPath: _getChainIconPath(),
55 + isLast: index != 0,
56 + title: index > 0 ? "Litecoin Private" : null,
57 );
69 - });
70 -
71 - },
72 - );
73 - }
74 - ),
58 + }
59 +
60 + final balance =
61 + dashboardViewModel.balanceViewModel.formattedBalances.elementAt(index);
62 + return AssetTile(
63 + showSwap: dashboardViewModel.isEnabledSwapAction,
64 + showBridgeButton: dashboardViewModel.showBridge(balance.asset),
65 + balance: balance,
66 + wallet: dashboardViewModel.wallet,
67 + isFirst: index == 0,
68 + isLast: index == dashboardViewModel.balanceViewModel.formattedBalances.length - 1,
69 + chainIconPath: _getChainIconPath(),
70 + );
71 + });
72 + },
73 + );
74 + }),
75 ),
76 );
77 }
@@ -79,8 +79,10 @@ class AssetsSection extends StatelessWidget {
79 // TODO refactor chainIconPath to get rid of this ugly thing. it's needed because arbitrum's wallet currency isn't arb
80 String _getChainIconPath() {
81 try {
82 - return CryptoCurrency.fromString(dashboardViewModel.wallet.currency.tag ??dashboardViewModel.wallet.currency.title).chainIconPath!;
83 - } catch(e) {
82 + return CryptoCurrency.fromString(
83 + dashboardViewModel.wallet.currency.tag ?? dashboardViewModel.wallet.currency.title)
84 + .chainIconPath!;
85 + } catch (e) {
86 return dashboardViewModel.wallet.currency.chainIconPath ?? "";
87 }
88 }
lib/new-ui/widgets/coins_page/assets_history/assets_top_bar.dart
+52 -55
@@ -10,7 +10,8 @@ class AssetsTopBar extends StatelessWidget {
10 required this.onTabChange,
11 required this.onTransactionHistoryOpened,
12 required this.selectedTab,
13 - required this.tabs, required this.dashboardViewModel,
13 + required this.tabs,
14 + required this.dashboardViewModel,
15 });
16
17 final void Function(int) onTabChange;
@@ -21,77 +22,73 @@ class AssetsTopBar extends StatelessWidget {
22
23 @override
24 Widget build(BuildContext context) {
24 -
25 return SliverToBoxAdapter(
26 child: Padding(
27 padding: const EdgeInsets.only(top: 32.0, bottom: 0.0, left: 12.0, right: 18.0),
28 child: Row(
29 - crossAxisAlignment: CrossAxisAlignment.center,
30 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
31 - children: [
32 - LineTabSwitcher(
33 - tabs: tabs.map((item)=>item.title).toList(),
34 - onTabChange: onTabChange,
35 - selectedTab: selectedTab,
36 - ),
37 - AnimatedSwitcher(
38 - duration: Duration(milliseconds: 300),
39 - layoutBuilder: (currentChild, previousChildren) {
40 - return Stack(
41 - alignment: Alignment.centerRight,
42 - children: <Widget>[
43 - ...previousChildren,
44 - if (currentChild != null) currentChild,
45 - ],
46 - );
47 - },
48 - child: Row(
49 - key: ValueKey(selectedTab),
50 - spacing: 8,
29 + crossAxisAlignment: CrossAxisAlignment.center,
30 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
31 children: [
52 -
53 - Opacity(
54 - opacity: tabs[selectedTab].actionButton != null ? 1 : 0,
55 - child: GestureDetector(
56 - onTap: () {
57 - if(tabs[selectedTab].actionButton != null) {
58 - tabs[selectedTab].actionButton?.onPressed();
59 - }
60 - },
61 - child: Container(
62 - height: 40,
63 - decoration: BoxDecoration(
64 - borderRadius: BorderRadius.circular(999999),
65 - color: Theme.of(context).colorScheme.surfaceContainer,
66 - ),
67 - child: Padding(
68 - padding: const EdgeInsets.symmetric(horizontal: 12.0),
69 - child: Row(
70 - spacing: 6,
71 - children: [
72 -
73 - if ((tabs[selectedTab].actionButton?.title ?? "").isNotEmpty)
32 + LineTabSwitcher(
33 + tabs: tabs.map((item) => item.title).toList(),
34 + onTabChange: onTabChange,
35 + selectedTab: selectedTab,
36 + ),
37 + AnimatedSwitcher(
38 + duration: Duration(milliseconds: 300),
39 + layoutBuilder: (currentChild, previousChildren) {
40 + return Stack(
41 + alignment: Alignment.centerRight,
42 + children: <Widget>[
43 + ...previousChildren,
44 + if (currentChild != null) currentChild,
45 + ],
46 + );
47 + },
48 + child: Row(
49 + key: ValueKey(selectedTab),
50 + spacing: 8,
51 + children: [
52 + Opacity(
53 + opacity: tabs[selectedTab].actionButton != null ? 1 : 0,
54 + child: GestureDetector(
55 + onTap: () {
56 + if (tabs[selectedTab].actionButton != null) {
57 + tabs[selectedTab].actionButton?.onPressed();
58 + }
59 + },
60 + child: Container(
61 + height: 40,
62 + decoration: BoxDecoration(
63 + borderRadius: BorderRadius.circular(999999),
64 + color: Theme.of(context).colorScheme.surfaceContainer,
65 + ),
66 + child: Padding(
67 + padding: const EdgeInsets.symmetric(horizontal: 12.0),
68 + child: Row(
69 + spacing: 6,
70 + children: [
71 + if ((tabs[selectedTab].actionButton?.title ?? "").isNotEmpty)
72 Text(
73 tabs[selectedTab].actionButton?.title ?? "",
74 style: TextStyle(color: Theme.of(context).colorScheme.primary),
75 ),
78 - CakeImageWidget(
79 - imageUrl: tabs[selectedTab].actionButton?.iconPath,
80 - colorFilter: ColorFilter.mode(
81 - Theme.of(context).colorScheme.primary, BlendMode.srcIn)),
76 + CakeImageWidget(
77 + imageUrl: tabs[selectedTab].actionButton?.iconPath,
78 + colorFilter: ColorFilter.mode(
79 + Theme.of(context).colorScheme.primary, BlendMode.srcIn)),
80 ],
81 ),
82 + ),
83 + ),
84 + ),
85 ),
85 - ),
86 + ],
87 ),
88 ),
89 ],
90 ),
90 - ),
91 - ],
92 - ),
91 ),
92 );
93 }
96 -
94 }
lib/new-ui/widgets/coins_page/assets_history/history_filters_page.dart
+6 -3
@@ -55,7 +55,8 @@ class HistoryFiltersPage extends StatelessWidget {
55 if (dashboardViewModel.tradeFilterStore.displayAllTrades) {
56 subtitle = S.of(context).manage_providers;
57 subtitleColor = Theme.of(context).colorScheme.onSurfaceVariant;
58 - } else if (dashboardViewModel.tradeFilterStore.enabledProvidersCount == 0) {
58 + } else if (dashboardViewModel.tradeFilterStore.enabledProvidersCount ==
59 + 0) {
60 subtitle = S.of(context).no_providers_selected;
61 subtitleColor = Color(0xFFFFB84E);
62 } else {
@@ -74,10 +75,12 @@ class HistoryFiltersPage extends StatelessWidget {
75 value: item.value(),
76 onChanged: (val) {
77 if ((val &&
77 - dashboardViewModel.tradeFilterStore.enabledProvidersCount ==
78 + dashboardViewModel
79 + .tradeFilterStore.enabledProvidersCount ==
80 0) ||
81 (!val &&
80 - dashboardViewModel.tradeFilterStore.enabledProvidersCount >
82 + dashboardViewModel
83 + .tradeFilterStore.enabledProvidersCount >
84 0)) {
85 dashboardViewModel.tradeFilterStore
86 .toggleDisplayExchange(ExchangeProviderDescription.all);
lib/new-ui/widgets/coins_page/assets_history/history_modal.dart
+3 -3
@@ -88,9 +88,9 @@ class HistoryModal extends StatelessWidget {
88 color: Colors.transparent,
89 child: Container(
90 decoration: BoxDecoration(
91 - borderRadius: BorderRadius.circular(18),
92 - border: Border.all(color: Theme.of(context).colorScheme.primary, width: 1)
93 - ),
91 + borderRadius: BorderRadius.circular(18),
92 + border: Border.all(
93 + color: Theme.of(context).colorScheme.primary, width: 1)),
94 height: 56,
95 width: double.infinity,
96 child: Row(
lib/new-ui/widgets/coins_page/assets_history/history_order_tile.dart
+10 -16
@@ -4,15 +4,15 @@ import 'package:cw_core/crypto_currency.dart';
4 import 'package:flutter/material.dart';
5
6 class HistoryOrderTile extends StatelessWidget {
7 - const HistoryOrderTile(
8 - {super.key,
9 - required this.date,
10 - required this.amount,
11 - required this.amountFiat,
12 - required this.roundedTop,
13 - required this.roundedBottom,
14 - required this.bottomSeparator,
15 - });
7 + const HistoryOrderTile({
8 + super.key,
9 + required this.date,
10 + required this.amount,
11 + required this.amountFiat,
12 + required this.roundedTop,
13 + required this.roundedBottom,
14 + required this.bottomSeparator,
15 + });
16
17 final String date;
18 final String amount;
@@ -21,23 +21,17 @@ class HistoryOrderTile extends StatelessWidget {
21 final bool roundedBottom;
22 final bool bottomSeparator;
23
24 -
25 -
26 -
24 @override
25 Widget build(BuildContext context) {
29 -
26 return HistoryTileBase(
27 title: "Order",
28 date: date,
29 amount: amount,
30 amountFiat: amountFiat,
35 - leadingIcon:Image.asset("assets/images/cakepay.png"),
31 + leadingIcon: Image.asset("assets/images/cakepay.png"),
32 roundedTop: roundedTop,
33 roundedBottom: roundedBottom,
34 bottomSeparator: bottomSeparator,
35 );
40 -
36 }
42 -
37 }
lib/new-ui/widgets/coins_page/assets_history/history_section.dart
+172 -158
@@ -24,7 +24,12 @@ import 'package:flutter_mobx/flutter_mobx.dart';
24 import 'package:intl/intl.dart';
25
26 class HistorySection extends StatelessWidget {
27 - const HistorySection({super.key, required this.dashboardViewModel, required this.short, required this.roundedTopSection, required this.detailsAsPage});
27 + const HistorySection(
28 + {super.key,
29 + required this.dashboardViewModel,
30 + required this.short,
31 + required this.roundedTopSection,
32 + required this.detailsAsPage});
33
34 final DashboardViewModel dashboardViewModel;
35 final bool short;
@@ -33,7 +38,6 @@ class HistorySection extends StatelessWidget {
38
39 @override
40 Widget build(BuildContext context) {
36 -
41 return SliverPadding(
42 padding: EdgeInsets.only(left: 16.0, right: 16, top: short && roundedTopSection ? 18 : 0),
43 sliver: Observer(
@@ -42,170 +46,180 @@ class HistorySection extends StatelessWidget {
46 final items = short ? dashboardViewModel.itemsShort : dashboardViewModel.items;
47
48 return (items.isEmpty)
45 - ? SliverPadding(
46 - padding: EdgeInsets.only(top: 24),
47 - sliver: SliverToBoxAdapter(
48 - child: (dashboardViewModel.status is SyncingSyncStatus)
49 - ? SizedBox.shrink()
50 - : Center(
51 - child: Text(S.of(context).transactions_will_appear_here,
52 - style: TextStyle(
53 - fontSize: 14,
54 - fontWeight: FontWeight.w400,
55 - color: Theme.of(context).colorScheme.onSurfaceVariant)),
56 - ),
57 - ),
58 - )
59 - : SliverPadding(
60 - padding: EdgeInsets.only(bottom: short ? 0 : 144),
61 - sliver: SliverList(
62 - delegate: SliverChildBuilderDelegate(
63 - childCount: items.length,
64 - (context, index) => Observer(builder: (_) {
65 - final prevItem = index == 0 ? null : items[index - 1];
66 - final topPadding = index == 0 ? 0.0 : 18.0;
67 - final item = items[index];
68 - final nextItem = index == items.length - 1
69 - ? null
70 - : items[index + 1];
71 -
72 - final roundedBottom = (nextItem == null || nextItem is DateSectionItem);
73 - final roundedTop = roundedTopSection && (prevItem == null || prevItem is DateSectionItem);
74 -
75 - if (item is TransactionListItem) {
76 - final transaction = item.transaction;
77 - final transactionType = dashboardViewModel.getTransactionType(transaction);
78 -
79 - if (item.hasTokens && item.assetOfTransaction == null) {
80 - return Container();
81 - }
82 -
83 - CryptoCurrency? asset;
84 - if (transaction.additionalInfo["isLightning"] == true)
85 - asset = CryptoCurrency.btcln;
86 - else
87 - asset = item.assetOfTransaction;
88 -
89 - return GestureDetector(
90 - onTap: () {
91 - final page = getIt.get<TransactionDetailsModal>(param1: transaction);
92 - if (detailsAsPage) {
93 - Navigator.of(context).push(
94 - CupertinoPageRoute(builder: (context) => Material(child: page)));
95 - } else {
96 - showModalBottomSheet(
97 - isScrollControlled: true,
98 - context: context,
99 - builder: (context) =>
100 - FractionallySizedBox(heightFactor: 0.9, child: page));
101 - }
102 - },
103 - child: HistoryTile(
104 - title: item.formattedTitle + transactionType,
105 - date: _formatTransactionDate(item.date, localeName),
106 - amount: item.formattedCryptoAmount,
107 - amountFiat: item.formattedFiatAmount,
108 - hasTokens: item.hasTokens,
109 - chainIconPath: _getChainIconPath(),
110 - roundedBottom: roundedBottom,
111 - roundedTop: roundedTop,
112 - bottomSeparator: !roundedBottom,
113 - direction: item.transaction.direction,
114 - pending: item.transaction.isPending,
115 - asset: asset,
116 - ),
117 - );
118 - } else if (item is TradeListItem) {
119 - final trade = item.trade;
120 - final tradeFrom = trade.from;
121 - final tradeTo = trade.to;
122 -
123 - return GestureDetector(
124 - onTap: () => Navigator.of(context)
125 - .pushNamed(Routes.tradeDetails, arguments: trade),
126 - child: HistoryTradeTile(
127 - from: tradeFrom,
128 - to: tradeTo,
129 - provider: trade.provider,
130 - date: _formatTransactionDate(item.trade.createdAt ?? DateTime.now(), localeName),
131 - amount: dashboardViewModel.balanceDisplayMode == BalanceDisplayMode.hiddenBalance ? "---" : trade.amountFormatted(),
132 - receiveAmount: dashboardViewModel.balanceDisplayMode == BalanceDisplayMode.hiddenBalance ? "---" : trade.receiveAmountFormatted(),
133 - roundedBottom: roundedBottom,
134 - roundedTop: roundedTop,
135 - bottomSeparator: !roundedBottom,
136 - swapState: trade.state,
137 - ),
138 - );
139 - } else if (item is SpecificDateSectionItem) {
140 - return Padding(
141 - padding: EdgeInsets.only(left: 8.0, bottom: 8.0, top: topPadding),
142 - child: Text(item.text,
49 + ? SliverPadding(
50 + padding: EdgeInsets.only(top: 24),
51 + sliver: SliverToBoxAdapter(
52 + child: (dashboardViewModel.status is SyncingSyncStatus)
53 + ? SizedBox.shrink()
54 + : Center(
55 + child: Text(S.of(context).transactions_will_appear_here,
56 style: TextStyle(
144 - color: Theme.of(context).colorScheme.onSurfaceVariant)));
145 - } else if (item is DateSectionItem) {
146 - return Padding(
147 - padding: EdgeInsets.only(left: 8.0, bottom: 8.0, top: topPadding),
148 - child: Text(DateFormat("MMMM yyyy", localeName).format(item.date),
149 - style: TextStyle(
150 - color: Theme.of(context).colorScheme.onSurfaceVariant)));
151 - } else if (item is OrderListItem) {
152 - return GestureDetector(
153 - onTap: () => Navigator.of(context)
154 - .pushNamed(Routes.orderDetails, arguments: item.order),
155 - child: HistoryOrderTile(
156 - date: _formatTransactionDate(item.order.createdAt, localeName),
157 - amount: item.orderFormattedAmount,
158 - amountFiat: "",
159 - roundedBottom: roundedBottom,
160 - roundedTop: roundedTop,
161 - bottomSeparator: !roundedBottom,
162 - ),
163 - );
164 - } else if (item is PayjoinTransactionListItem) {
165 - final session = item.session;
166 -
167 - return GestureDetector(
168 - onTap: () => Navigator.of(context).pushNamed(
169 - Routes.payjoinDetails,
170 - arguments: [item.sessionId, item.transaction],
57 + fontSize: 14,
58 + fontWeight: FontWeight.w400,
59 + color: Theme.of(context).colorScheme.onSurfaceVariant)),
60 ),
172 - child: PayjoinHistoryTile(
173 - createdAt: _formatTransactionDate(session.inProgressSince!, localeName),
174 - amount: dashboardViewModel.appStore.amountParsingProxy
175 - .asDisplayString(Money(
176 - session.amount, CryptoCurrency.btc)),
177 - currency: item.transaction?.from ?? "BTC",
178 - state: item.status,
179 - isSending: session.isSenderSession,
180 - roundedTop: roundedTop,
61 + ),
62 + )
63 + : SliverPadding(
64 + padding: EdgeInsets.only(bottom: short ? 0 : 144),
65 + sliver: SliverList(
66 + delegate: SliverChildBuilderDelegate(
67 + childCount: items.length,
68 + (context, index) => Observer(builder: (_) {
69 + final prevItem = index == 0 ? null : items[index - 1];
70 + final topPadding = index == 0 ? 0.0 : 18.0;
71 + final item = items[index];
72 + final nextItem = index == items.length - 1 ? null : items[index + 1];
73 +
74 + final roundedBottom = (nextItem == null || nextItem is DateSectionItem);
75 + final roundedTop = roundedTopSection &&
76 + (prevItem == null || prevItem is DateSectionItem);
77 +
78 + if (item is TransactionListItem) {
79 + final transaction = item.transaction;
80 + final transactionType =
81 + dashboardViewModel.getTransactionType(transaction);
82 +
83 + if (item.hasTokens && item.assetOfTransaction == null) {
84 + return Container();
85 + }
86 +
87 + CryptoCurrency? asset;
88 + if (transaction.additionalInfo["isLightning"] == true)
89 + asset = CryptoCurrency.btcln;
90 + else
91 + asset = item.assetOfTransaction;
92 +
93 + return GestureDetector(
94 + onTap: () {
95 + final page =
96 + getIt.get<TransactionDetailsModal>(param1: transaction);
97 + if (detailsAsPage) {
98 + Navigator.of(context).push(CupertinoPageRoute(
99 + builder: (context) => Material(child: page)));
100 + } else {
101 + showModalBottomSheet(
102 + isScrollControlled: true,
103 + context: context,
104 + builder: (context) =>
105 + FractionallySizedBox(heightFactor: 0.9, child: page));
106 + }
107 + },
108 + child: HistoryTile(
109 + title: item.formattedTitle + transactionType,
110 + date: _formatTransactionDate(item.date, localeName),
111 + amount: item.formattedCryptoAmount,
112 + amountFiat: item.formattedFiatAmount,
113 + hasTokens: item.hasTokens,
114 + chainIconPath: _getChainIconPath(),
115 roundedBottom: roundedBottom,
182 - bottomSeparator: !roundedBottom),
183 - );
184 - } else if (item is AnonpayTransactionListItem) {
185 - final transactionInfo = item.transaction;
116 + roundedTop: roundedTop,
117 + bottomSeparator: !roundedBottom,
118 + direction: item.transaction.direction,
119 + pending: item.transaction.isPending,
120 + asset: asset,
121 + ),
122 + );
123 + } else if (item is TradeListItem) {
124 + final trade = item.trade;
125 + final tradeFrom = trade.from;
126 + final tradeTo = trade.to;
127
187 - return GestureDetector(
128 + return GestureDetector(
129 + onTap: () => Navigator.of(context)
130 + .pushNamed(Routes.tradeDetails, arguments: trade),
131 + child: HistoryTradeTile(
132 + from: tradeFrom,
133 + to: tradeTo,
134 + provider: trade.provider,
135 + date: _formatTransactionDate(
136 + item.trade.createdAt ?? DateTime.now(), localeName),
137 + amount: dashboardViewModel.balanceDisplayMode ==
138 + BalanceDisplayMode.hiddenBalance
139 + ? "---"
140 + : trade.amountFormatted(),
141 + receiveAmount: dashboardViewModel.balanceDisplayMode ==
142 + BalanceDisplayMode.hiddenBalance
143 + ? "---"
144 + : trade.receiveAmountFormatted(),
145 + roundedBottom: roundedBottom,
146 + roundedTop: roundedTop,
147 + bottomSeparator: !roundedBottom,
148 + swapState: trade.state,
149 + ),
150 + );
151 + } else if (item is SpecificDateSectionItem) {
152 + return Padding(
153 + padding: EdgeInsets.only(left: 8.0, bottom: 8.0, top: topPadding),
154 + child: Text(item.text,
155 + style: TextStyle(
156 + color: Theme.of(context).colorScheme.onSurfaceVariant)));
157 + } else if (item is DateSectionItem) {
158 + return Padding(
159 + padding: EdgeInsets.only(left: 8.0, bottom: 8.0, top: topPadding),
160 + child: Text(DateFormat("MMMM yyyy", localeName).format(item.date),
161 + style: TextStyle(
162 + color: Theme.of(context).colorScheme.onSurfaceVariant)));
163 + } else if (item is OrderListItem) {
164 + return GestureDetector(
165 onTap: () => Navigator.of(context)
189 - .pushNamed(Routes.anonPayDetailsPage, arguments: transactionInfo),
190 - child: AnonpayHistoryTile(
191 - provider: transactionInfo.provider,
192 - createdAt: _formatTransactionDate(transactionInfo.createdAt, localeName),
193 - amount: transactionInfo.fiatAmount?.toString() ??
194 - (transactionInfo.amountTo?.toString() ?? ''),
195 - currency: transactionInfo.fiatAmount != null
196 - ? transactionInfo.fiatEquiv ?? ''
197 - : CryptoCurrency.fromFullName(transactionInfo.coinTo)
198 - .name
199 - .toUpperCase(),
166 + .pushNamed(Routes.orderDetails, arguments: item.order),
167 + child: HistoryOrderTile(
168 + date: _formatTransactionDate(item.order.createdAt, localeName),
169 + amount: item.orderFormattedAmount,
170 + amountFiat: "",
171 + roundedBottom: roundedBottom,
172 + roundedTop: roundedTop,
173 + bottomSeparator: !roundedBottom,
174 + ),
175 + );
176 + } else if (item is PayjoinTransactionListItem) {
177 + final session = item.session;
178 +
179 + return GestureDetector(
180 + onTap: () => Navigator.of(context).pushNamed(
181 + Routes.payjoinDetails,
182 + arguments: [item.sessionId, item.transaction],
183 + ),
184 + child: PayjoinHistoryTile(
185 + createdAt:
186 + _formatTransactionDate(session.inProgressSince!, localeName),
187 + amount: dashboardViewModel.appStore.amountParsingProxy
188 + .asDisplayString(Money(session.amount, CryptoCurrency.btc)),
189 + currency: item.transaction?.from ?? "BTC",
190 + state: item.status,
191 + isSending: session.isSenderSession,
192 roundedTop: roundedTop,
193 roundedBottom: roundedBottom,
202 - bottomSeparator: !roundedBottom));
203 - } else
204 - return Text(item.runtimeType.toString());
205 - }),
194 + bottomSeparator: !roundedBottom),
195 + );
196 + } else if (item is AnonpayTransactionListItem) {
197 + final transactionInfo = item.transaction;
198 +
199 + return GestureDetector(
200 + onTap: () => Navigator.of(context).pushNamed(
201 + Routes.anonPayDetailsPage,
202 + arguments: transactionInfo),
203 + child: AnonpayHistoryTile(
204 + provider: transactionInfo.provider,
205 + createdAt: _formatTransactionDate(
206 + transactionInfo.createdAt, localeName),
207 + amount: transactionInfo.fiatAmount?.toString() ??
208 + (transactionInfo.amountTo?.toString() ?? ''),
209 + currency: transactionInfo.fiatAmount != null
210 + ? transactionInfo.fiatEquiv ?? ''
211 + : CryptoCurrency.fromFullName(transactionInfo.coinTo)
212 + .name
213 + .toUpperCase(),
214 + roundedTop: roundedTop,
215 + roundedBottom: roundedBottom,
216 + bottomSeparator: !roundedBottom));
217 + } else
218 + return Text(item.runtimeType.toString());
219 + }),
220 + ),
221 ),
207 - ),
208 - );
222 + );
223 },
224 ));
225 }
lib/new-ui/widgets/coins_page/assets_history/history_swap_providers_page.dart
+4 -2
@@ -42,9 +42,11 @@ class HistorySwapProvidersPage extends StatelessWidget {
42 title: S.of(context).swap_providers,
43 onSelected: (val) {
44 if ((val &&
45 - dashboardViewModel.tradeFilterStore.enabledProvidersCount == 0) ||
45 + dashboardViewModel.tradeFilterStore.enabledProvidersCount ==
46 + 0) ||
47 (!val &&
47 - dashboardViewModel.tradeFilterStore.enabledProvidersCount > 0)) {
48 + dashboardViewModel.tradeFilterStore.enabledProvidersCount >
49 + 0)) {
50 dashboardViewModel.tradeFilterStore
51 .toggleDisplayExchange(ExchangeProviderDescription.all);
52 }
lib/new-ui/widgets/coins_page/assets_history/history_tile.dart
+31 -29
@@ -60,15 +60,14 @@ class HistoryTile extends StatelessWidget {
60 }
61 }
62
63 - Color? _getPrimaryTextColor() {
64 - }
63 + Color? _getPrimaryTextColor() {}
64
65 Widget _getLeadingIcon(BuildContext context) {
66 if (asset == CryptoCurrency.btcln) {
67 return Stack(
68 children: [
70 - CakeImageWidget(imageUrl:
71 - "assets/new-ui/lightning-icon.svg",
69 + CakeImageWidget(
70 + imageUrl: "assets/new-ui/lightning-icon.svg",
71 width: 34,
72 height: 34,
73 ),
@@ -96,36 +95,39 @@ class HistoryTile extends StatelessWidget {
95 );
96 }
97
99 - if(hasTokens) {
100 - return Stack(children: [
101 - Opacity(
102 - opacity: pending ? 0.5 : 1,
103 - child: CakeImageWidget(
98 + if (hasTokens) {
99 + return Stack(
100 + children: [
101 + Opacity(
102 + opacity: pending ? 0.5 : 1,
103 + child: CakeImageWidget(
104 imageUrl: asset?.iconPath ?? "",
105 width: 34,
106 ),
107 - ),
108 - Align(
109 - alignment: Alignment.bottomRight,
110 - child: Container(
111 - decoration: ShapeDecoration(
112 - shape: RoundedSuperellipseBorder(
113 - borderRadius: BorderRadius.circular(5),side: BorderSide(color: Colors.black)),
114 - color: Colors.white),
115 - child: Padding(
116 - padding: const EdgeInsets.all(2.0),
117 - child: CakeImageWidget(
118 - imageUrl: chainIconPath,
119 - width: 12,
120 - height: 12,
121 - colorFilter:
122 - ColorFilter.mode(Colors.black, BlendMode.srcIn),
123 - ),
124 - )))
125 - ],);
107 + ),
108 + Align(
109 + alignment: Alignment.bottomRight,
110 + child: Container(
111 + decoration: ShapeDecoration(
112 + shape: RoundedSuperellipseBorder(
113 + borderRadius: BorderRadius.circular(5),
114 + side: BorderSide(color: Colors.black)),
115 + color: Colors.white),
116 + child: Padding(
117 + padding: const EdgeInsets.all(2.0),
118 + child: CakeImageWidget(
119 + imageUrl: chainIconPath,
120 + width: 12,
121 + height: 12,
122 + colorFilter: ColorFilter.mode(Colors.black, BlendMode.srcIn),
123 + ),
124 + )))
125 + ],
126 + );
127 }
128
128 - return CakeImageWidget(imageUrl:_getDirectionIcon(),
129 + return CakeImageWidget(
130 + imageUrl: _getDirectionIcon(),
131 colorFilter: ColorFilter.mode(
132 direction == TransactionDirection.outgoing
133 ? Theme.of(context).colorScheme.inverseSurface.withAlpha(175)
lib/new-ui/widgets/coins_page/assets_history/history_tile_base.dart
+26 -23
@@ -109,24 +109,25 @@ class HistoryTileBase extends StatelessWidget {
109 Expanded(
110 child: Padding(
111 padding: EdgeInsets.only(right: 4),
112 - child: Row(
113 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
114 - children: [
115 - Column(
116 - crossAxisAlignment: CrossAxisAlignment.start,
112 + child: Row(
113 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
114 + children: [
115 + Column(
116 + crossAxisAlignment: CrossAxisAlignment.start,
117 children: [
118 - if(title != null)
119 - Text(title!,
120 - style: TextStyle(color: Theme.of(context).colorScheme.onSurface))
121 - else if(titleWidget != null) titleWidget!,
118 + if (title != null)
119 + Text(title!,
120 + style: TextStyle(color: Theme.of(context).colorScheme.onSurface))
121 + else if (titleWidget != null)
122 + titleWidget!,
123 Text(date,
124 style: TextStyle(
125 color: Theme.of(context).colorScheme.onSurfaceVariant)),
126 ],
126 - ),
127 - Column(
128 - crossAxisAlignment: CrossAxisAlignment.end,
129 - children: [
127 + ),
128 + Column(
129 + crossAxisAlignment: CrossAxisAlignment.end,
130 + children: [
131 if (amount != null)
132 Text(amount!,
133 style: TextStyle(
@@ -141,22 +142,24 @@ class HistoryTileBase extends StatelessWidget {
142 else if (amountFiatWidget != null)
143 amountFiatWidget!
144 ],
144 - ),
145 - ],
146 - ),
145 + ),
146 + ],
147 + ),
148 ),
149 ),
150 ],
151 ),
152 ),
153 ),
153 - if(bottomSeparator) Container(
154 - color: Theme.of(context).colorScheme.surfaceContainer,
155 - child: Padding(
156 - padding: EdgeInsets.only(left: 56, right: 16),
157 - child: Container(height: 1, color: Theme.of(context).colorScheme.outlineVariant.withAlpha(175)),
158 - ),
159 - )
154 + if (bottomSeparator)
155 + Container(
156 + color: Theme.of(context).colorScheme.surfaceContainer,
157 + child: Padding(
158 + padding: EdgeInsets.only(left: 56, right: 16),
159 + child: Container(
160 + height: 1, color: Theme.of(context).colorScheme.outlineVariant.withAlpha(175)),
161 + ),
162 + )
163 ],
164 );
165 }
lib/new-ui/widgets/coins_page/assets_history/history_top_bar.dart
+10 -10
@@ -19,9 +19,8 @@ class HistoryTopBar extends StatelessWidget {
19 child: Container(
20 decoration: BoxDecoration(
21 borderRadius: BorderRadius.vertical(
22 - top: Radius.circular(18),
23 - bottom: roundedBottom ? Radius.circular(18) : Radius.zero
24 - ),
22 + top: Radius.circular(18),
23 + bottom: roundedBottom ? Radius.circular(18) : Radius.zero),
24 color: Theme.of(context).colorScheme.surfaceContainer),
25 child: Padding(
26 padding: EdgeInsets.symmetric(
@@ -43,13 +42,14 @@ class HistoryTopBar extends StatelessWidget {
42 )
43 ],
44 ),
46 - if(!roundedBottom)
47 - Container(
48 - height: 1,
49 - width: double.infinity,
50 - color: Theme.of(context).colorScheme.outlineVariant.withAlpha(175),
51 - )
52 - else Container(height: 2)
45 + if (!roundedBottom)
46 + Container(
47 + height: 1,
48 + width: double.infinity,
49 + color: Theme.of(context).colorScheme.outlineVariant.withAlpha(175),
50 + )
51 + else
52 + Container(height: 2)
53 ],
54 ),
55 ),
lib/new-ui/widgets/coins_page/assets_history/history_trade_tile.dart
+12 -9
@@ -36,7 +36,6 @@ class HistoryTradeTile extends StatelessWidget {
36 return SizedBox(width: 50, height: 50);
37 }
38
39 -
39 double currencyIconSize = 22.0;
40
41 return SizedBox(
@@ -90,7 +89,9 @@ class HistoryTradeTile extends StatelessWidget {
89 style: TextStyle(
90 color: Theme.of(context).colorScheme.onSurfaceVariant,
91 fontWeight: FontWeight.w500)),
93 - if(from?.title != null) Text(from!.title, style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant)),
92 + if (from?.title != null)
93 + Text(from!.title,
94 + style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant)),
95 if (fromChainIcon?.isNotEmpty ?? false)
96 CakeImageWidget(
97 imageUrl: fromChainIcon,
@@ -111,11 +112,12 @@ class HistoryTradeTile extends StatelessWidget {
112 receiveAmount.withMaxDecimals(8),
113 style: TextStyle(fontWeight: FontWeight.w500),
114 ),
114 - if(to!=null)
115 - Text(
116 - to!.title,
117 - ),
118 - if (toChainIcon?.isNotEmpty ?? false) CakeImageWidget(imageUrl: toChainIcon, width: 12, height: 12)
115 + if (to != null)
116 + Text(
117 + to!.title,
118 + ),
119 + if (toChainIcon?.isNotEmpty ?? false)
120 + CakeImageWidget(imageUrl: toChainIcon, width: 12, height: 12)
121 ],
122 ),
123 leadingIcon: _getLeadingStack(context),
@@ -144,10 +146,11 @@ class HistoryTradeTile extends StatelessWidget {
146 }
147
148 String? _getChainIcon(CryptoCurrency? currency) {
147 - if(currency == null) return null;
149 + if (currency == null) return null;
150 try {
151 if (currency.title.isNotEmpty) {
150 - final parsedCurrency = CryptoCurrency.safeParseCurrencyFromString(currency.title, tag: currency.tag);
152 + final parsedCurrency =
153 + CryptoCurrency.safeParseCurrencyFromString(currency.title, tag: currency.tag);
154 if (parsedCurrency?.chainIconPath != null) return parsedCurrency!.chainIconPath!;
155 }
156
lib/new-ui/widgets/coins_page/assets_history/transaction_details_modal.dart
+35 -35
@@ -17,7 +17,8 @@ import 'package:flutter_mobx/flutter_mobx.dart';
17 import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
18
19 class TransactionDetailsModal extends StatefulWidget {
20 - const TransactionDetailsModal({super.key, required this.transactionDetailsViewModel, this.highlightNoteField = false});
20 + const TransactionDetailsModal(
21 + {super.key, required this.transactionDetailsViewModel, this.highlightNoteField = false});
22
23 final TransactionDetailsViewModel transactionDetailsViewModel;
24 final bool highlightNoteField;
@@ -41,7 +42,7 @@ class _TransactionDetailsModalState extends State<TransactionDetailsModal> {
42 }
43 });
44
44 - if(widget.highlightNoteField) {
45 + if (widget.highlightNoteField) {
46 noteFocusNode.requestFocus();
47 }
48 }
@@ -73,9 +74,8 @@ class _TransactionDetailsModalState extends State<TransactionDetailsModal> {
74 child: Column(
75 children: [
76 TokenImageWidget(
76 - imageUrl: widget
77 - .transactionDetailsViewModel.transactionAsset.iconPath ??
78 - "",
77 + imageUrl:
78 + widget.transactionDetailsViewModel.transactionAsset.iconPath ?? "",
79 size: 64,
80 ),
81 SizedBox(height: 10),
@@ -87,12 +87,18 @@ class _TransactionDetailsModalState extends State<TransactionDetailsModal> {
87 CopyWrapper(
88 requireLongPress: true,
89 data: ClipboardData(text: transactionInfoAmount.toString()),
90 - builder: (context, copied)=> AnimatedSwitcher(
90 + builder: (context, copied) => AnimatedSwitcher(
91 duration: Duration(milliseconds: 300),
92 child: Text(
93 key: ValueKey(copied),
94 - copied ? S.of(context).copied : transactionInfoAmount.toStringWithSymbol(),
95 - style: TextStyle(fontSize: 28, color: copied ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onSurface),
94 + copied
95 + ? S.of(context).copied
96 + : transactionInfoAmount.toStringWithSymbol(),
97 + style: TextStyle(
98 + fontSize: 28,
99 + color: copied
100 + ? Theme.of(context).colorScheme.primary
101 + : Theme.of(context).colorScheme.onSurface),
102 ),
103 ),
104 ),
@@ -104,25 +110,23 @@ class _TransactionDetailsModalState extends State<TransactionDetailsModal> {
110 NewListSections(sections: {
111 "": widget.transactionDetailsViewModel.items
112 .map((item) {
107 - if (item.value.isEmpty) return null;
113 + if (item.value.isEmpty) return null;
114
109 - final shouldBuildBottomWidget =
110 - item.value.length > 25;
115 + final shouldBuildBottomWidget = item.value.length > 25;
116
112 - return ListItemRegularRow(
113 - copyableText: item.value,
114 - showArrow: false,
115 - keyValue:
116 - ((item.key as ValueKey?)?.value as String?) ??
117 - item.title,
118 - label: item.title,
119 - trailingWidget: shouldBuildBottomWidget
120 - ? null
121 - : _buildTrailingWIdget(item),
122 - bottomWidget: shouldBuildBottomWidget
123 - ? _buildBottomWidget(item)
124 - : null);
125 - })
117 + return ListItemRegularRow(
118 + copyableText: item.value,
119 + showArrow: false,
120 + keyValue: ((item.key as ValueKey?)?.value as String?) ??
121 + item.title,
122 + label: item.title,
123 + trailingWidget: shouldBuildBottomWidget
124 + ? null
125 + : _buildTrailingWIdget(item),
126 + bottomWidget: shouldBuildBottomWidget
127 + ? _buildBottomWidget(item)
128 + : null);
129 + })
130 .whereType<ListItem>()
131 .toList(),
132 }),
@@ -157,12 +161,10 @@ class _TransactionDetailsModalState extends State<TransactionDetailsModal> {
161 "view tx": [
162 ListItemRegularRow(
163 keyValue: "view tx on",
160 - label: widget.transactionDetailsViewModel
161 - .explorerDescription,
162 - onTap: widget
163 - .transactionDetailsViewModel.launchExplorer,
164 - foregroundColor:
165 - Theme.of(context).colorScheme.primary,
164 + label:
165 + widget.transactionDetailsViewModel.explorerDescription,
166 + onTap: widget.transactionDetailsViewModel.launchExplorer,
167 + foregroundColor: Theme.of(context).colorScheme.primary,
168 trailingIconPath: "assets/new-ui/link_arrow.svg",
169 trailingIconSize: 8)
170 ],
@@ -174,10 +176,8 @@ class _TransactionDetailsModalState extends State<TransactionDetailsModal> {
176 onTap: () {
177 Navigator.of(context)
178 .pushNamed(Routes.bumpFeePage, arguments: [
177 - widget.transactionDetailsViewModel
178 - .transactionInfo,
179 - widget.transactionDetailsViewModel
180 - .rawTransaction
179 + widget.transactionDetailsViewModel.transactionInfo,
180 + widget.transactionDetailsViewModel.rawTransaction
181 ]);
182 })
183 ]
lib/new-ui/widgets/coins_page/cards/balance_card.dart
+44 -38
@@ -9,30 +9,30 @@ class BalanceCardAction {
9 final VoidCallback onTap;
10 final double? iconSize;
11
12 - const BalanceCardAction({required this.label, required this.icon, required this.onTap, this.iconSize = 16});
12 + const BalanceCardAction(
13 + {required this.label, required this.icon, required this.onTap, this.iconSize = 16});
14 }
15
16 class BalanceCard extends StatelessWidget {
16 - const BalanceCard({
17 - super.key,
18 - required this.width,
19 - required this.design,
20 - this.gradient,
21 - this.borderRadius = 20,
22 - this.selected = false,
23 - this.accountName = "",
24 - this.accountBalance = "",
25 - this.balance = "",
26 - this.fiatBalance = "",
27 - this.assetName = "",
28 - this.fiatCurrencyTitle = "",
29 - this.designSwitchDuration = const Duration(),
30 - this.actions = const [],
31 - this.capitalizeAssetName = true,
32 - this.onCustomizeTapped,
33 - this.accountIndex,
34 - this.fiatFirst = false
35 - });
17 + const BalanceCard(
18 + {super.key,
19 + required this.width,
20 + required this.design,
21 + this.gradient,
22 + this.borderRadius = 20,
23 + this.selected = false,
24 + this.accountName = "",
25 + this.accountBalance = "",
26 + this.balance = "",
27 + this.fiatBalance = "",
28 + this.assetName = "",
29 + this.fiatCurrencyTitle = "",
30 + this.designSwitchDuration = const Duration(),
31 + this.actions = const [],
32 + this.capitalizeAssetName = true,
33 + this.onCustomizeTapped,
34 + this.accountIndex,
35 + this.fiatFirst = false});
36
37 final double width;
38 final double borderRadius;
@@ -89,15 +89,15 @@ class BalanceCard extends StatelessWidget {
89 switchOutCurve: Curves.easeInOut,
90 child: design.backgroundType == CardDesignBackgroundTypes.svgFull
91 ? ClipRSuperellipse(
92 - borderRadius: BorderRadius.circular(borderRadius),
93 - key: ValueKey(design.imagePath),
92 + borderRadius: BorderRadius.circular(borderRadius),
93 + key: ValueKey(design.imagePath),
94 child: CakeImageWidget(
95 imageUrl: design.imagePath,
96 width: width,
97 height: height,
98 fit: BoxFit.fill,
99 ),
100 - )
100 + )
101 : const SizedBox.shrink(
102 key: ValueKey('svgFullOff'),
103 ),
@@ -114,10 +114,10 @@ class BalanceCard extends StatelessWidget {
114 crossAxisAlignment: CrossAxisAlignment.start,
115 mainAxisSize: MainAxisSize.max,
116 children: [
117 - if(leadText.isNotEmpty || accountBalance.isNotEmpty)
118 - Row(
119 - mainAxisSize: MainAxisSize.max,
120 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
117 + if (leadText.isNotEmpty || accountBalance.isNotEmpty)
118 + Row(
119 + mainAxisSize: MainAxisSize.max,
120 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
121 children: [
122 Row(
123 spacing: 4,
@@ -136,7 +136,9 @@ class BalanceCard extends StatelessWidget {
136 AnimatedDefaultTextStyle(
137 duration: designSwitchDuration,
138 style: Theme.of(context).textTheme.titleMedium!.copyWith(
139 - fontWeight: FontWeight.w500, color: design.colors.textColor.withAlpha(leadText == accountName ? 255 : 128)),
139 + fontWeight: FontWeight.w500,
140 + color: design.colors.textColor
141 + .withAlpha(leadText == accountName ? 255 : 128)),
142 child: Text(leadText),
143 ),
144 ],
@@ -147,10 +149,10 @@ class BalanceCard extends StatelessWidget {
149 child: Text(
150 accountBalance,
151 style: TextStyle(color: design.colors.textColor, fontSize: 14),
152 + ),
153 ),
151 - ),
152 - ],
153 - ),
154 + ],
155 + ),
156 AnimatedOpacity(
157 opacity: selected ? 1 : 0,
158 duration: textFadeDuration,
@@ -171,16 +173,20 @@ class BalanceCard extends StatelessWidget {
173 children: [
174 AnimatedDefaultTextStyle(
175 duration: designSwitchDuration,
174 - style: DefaultTextStyle.of(context)
175 - .style
176 - .copyWith(color: design.colors.textColor, fontSize: 28, fontWeight: FontWeight.w500, letterSpacing: -0.4),
176 + style: DefaultTextStyle.of(context).style.copyWith(
177 + color: design.colors.textColor,
178 + fontSize: 28,
179 + fontWeight: FontWeight.w500,
180 + letterSpacing: -0.4),
181 child: Text(fiatFirst ? fiatBalance : balance),
182 ),
183 AnimatedDefaultTextStyle(
184 duration: designSwitchDuration,
181 - style: DefaultTextStyle.of(context)
182 - .style
183 - .copyWith(color: design.colors.textColorSecondary, fontSize: 28, fontWeight: FontWeight.w400, letterSpacing: -0.4),
185 + style: DefaultTextStyle.of(context).style.copyWith(
186 + color: design.colors.textColorSecondary,
187 + fontSize: 28,
188 + fontWeight: FontWeight.w400,
189 + letterSpacing: -0.4),
190 child: Text(resolvedAssetName),
191 ),
192 ],
lib/new-ui/widgets/coins_page/cards/cards_view.dart
+45 -39
@@ -32,7 +32,8 @@ class CardsView extends StatefulWidget {
32 required this.dashboardViewModel,
33 required this.accountListViewModel,
34 required this.lightningMode,
35 - required this.onCompactModeBackgroundCardsTapped, required this.onCustomizeTapped});
35 + required this.onCompactModeBackgroundCardsTapped,
36 + required this.onCustomizeTapped});
37
38 final DashboardViewModel dashboardViewModel;
39 final MoneroAccountListViewModel? accountListViewModel;
@@ -73,7 +74,6 @@ class _CardsViewState extends State<CardsView> {
74
75 final top = baseTop - (howFarBehind * overlapAmount);
76
76 -
77 final left = (parentWidth - effectiveCardWidth) / 2.0;
78
79 return AnimatedPositioned(
@@ -91,7 +91,7 @@ class _CardsViewState extends State<CardsView> {
91 // printV(visualIndex);
92 if (compactMode && visualIndex != 0) {
93 widget.onCompactModeBackgroundCardsTapped();
94 - } else if(!compactMode) {
94 + } else if (!compactMode) {
95 setState(() {
96 if (widget.accountListViewModel != null)
97 widget.accountListViewModel!
@@ -103,18 +103,20 @@ class _CardsViewState extends State<CardsView> {
103 onLongPress: () {
104 if (_selectedIndex == visualIndex) {
105 widget.dashboardViewModel.balanceViewModel.switchBalanceValue();
106 - };
106 + }
107 + ;
108 HapticFeedback.heavyImpact();
109 },
110 child: Observer(builder: (_) {
110 - if(realIndex >= (widget.accountListViewModel?.accounts.length ?? 1)) {
111 + if (realIndex >= (widget.accountListViewModel?.accounts.length ?? 1)) {
112 return Container();
113 }
114 final account = widget.accountListViewModel?.accounts[realIndex];
115
116 // The second balance should always be the lightning balance
117 // printV(widget.dashboardViewModel.balanceViewModel.formattedBalances.first.availableBalance);
117 - final walletBalanceRecord = widget.dashboardViewModel.balanceViewModel.getMainBalanceRecord(widget.lightningMode);
118 + final walletBalanceRecord = widget.dashboardViewModel.balanceViewModel
119 + .getMainBalanceRecord(widget.lightningMode);
120
121 late final String walletBalance;
122 late final String walletFiatBalance;
@@ -141,7 +143,7 @@ class _CardsViewState extends State<CardsView> {
143 if (widget.dashboardViewModel.cardDesigns.isEmpty ||
144 realIndex >= widget.dashboardViewModel.cardDesigns.length)
145 cardDesign = CardDesign.genericDefault;
144 - else if(widget.lightningMode)
146 + else if (widget.lightningMode)
147 cardDesign = widget.dashboardViewModel.cardDesigns[realIndex + 1];
148 else
149 cardDesign = widget.dashboardViewModel.cardDesigns[realIndex];
@@ -156,7 +158,9 @@ class _CardsViewState extends State<CardsView> {
158 accountBalance = account.balance ?? "0.00";
159 }
160
159 - final assetName = widget.dashboardViewModel.balanceViewModel.showCombinedBalance ? "" : walletBalanceRecord?.formattedAssetTitle ?? assetTitleFallback;
161 + final assetName = widget.dashboardViewModel.balanceViewModel.showCombinedBalance
162 + ? ""
163 + : walletBalanceRecord?.formattedAssetTitle ?? assetTitleFallback;
164
165 final List<BalanceCardAction> actions = widget.lightningMode
166 ? [
@@ -205,13 +209,12 @@ class _CardsViewState extends State<CardsView> {
209 );
210 }
211
208 - String get assetTitleFallback => widget.dashboardViewModel.appStore.amountParsingProxy.getCryptoSymbol(
209 - widget.lightningMode
210 - ? CryptoCurrency.btcln
211 - : widget.dashboardViewModel.wallet.currency);
212 + String get assetTitleFallback =>
213 + widget.dashboardViewModel.appStore.amountParsingProxy.getCryptoSymbol(
214 + widget.lightningMode ? CryptoCurrency.btcln : widget.dashboardViewModel.wallet.currency);
215
216 bool _shouldCapitalizeAssetName() {
214 - if(widget.dashboardViewModel.wallet.type != WalletType.bitcoin) {
217 + if (widget.dashboardViewModel.wallet.type != WalletType.bitcoin) {
218 return true;
219 }
220
@@ -227,7 +230,8 @@ class _CardsViewState extends State<CardsView> {
230 }
231 }
232
230 - double get effectiveCardWidth => min(MediaQuery.of(context).size.width * 0.878, responsiveLayoutUtil.shouldRenderMobileUI ? 768 : 512);
233 + double get effectiveCardWidth => min(MediaQuery.of(context).size.width * 0.878,
234 + responsiveLayoutUtil.shouldRenderMobileUI ? 768 : 512);
235
236 double _getBoxHeight(int numCards, double overlapAmount) {
237 return
@@ -243,10 +247,10 @@ class _CardsViewState extends State<CardsView> {
247 final parentWidth = MediaQuery.of(context).size.width;
248 final children = <Widget>[];
249
246 - int numCards = widget.dashboardViewModel.wallet.type == WalletType.bitcoin
247 - ? 1
248 - : widget.dashboardViewModel.cardDesigns.length;
249 - if(numCards == 0) numCards = 1;
250 + int numCards = widget.dashboardViewModel.wallet.type == WalletType.bitcoin
251 + ? 1
252 + : widget.dashboardViewModel.cardDesigns.length;
253 + if (numCards == 0) numCards = 1;
254
255 if (_selectedIndex >= (numCards)) {
256 _selectedIndex = 0;
@@ -267,7 +271,6 @@ class _CardsViewState extends State<CardsView> {
271 }
272 }
273
270 -
274 final bool compactMode = numCards >= compactModeTreshold;
275 final double overlapAmount = compactMode ? 5.0 : 46.0;
276 for (int i = min(numCards - 1, maxCards); i >= 0; i--) {
@@ -280,8 +283,7 @@ class _CardsViewState extends State<CardsView> {
283 realIndex < widget.accountListViewModel!.accounts.length &&
284 widget.accountListViewModel?.selected.label !=
285 widget.accountListViewModel?.accounts[realIndex].label) {
283 - widget.accountListViewModel!
284 - .select(widget.accountListViewModel!.accounts[realIndex]);
286 + widget.accountListViewModel!.select(widget.accountListViewModel!.accounts[realIndex]);
287 }
288
289 children.add(_buildCard(
@@ -326,15 +328,17 @@ class _CardsViewState extends State<CardsView> {
328 unspentCoinType: UnspentCoinType.nonMweb,
329 mode: SendPageModes.lightningDeposit,
330 ));
329 - showCupertinoModalBottomSheet(context: context, barrierColor: Colors.black.withAlpha(128), builder: (context){
330 - return Padding(
331 - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
332 - child: SizedBox(
333 - height:MediaQuery.of(context).size.height*0.6,
334 - child:ModalNavigator(parentContext:context,rootPage: Material(child: page))
335 - ),
336 - );
337 - });
331 + showCupertinoModalBottomSheet(
332 + context: context,
333 + barrierColor: Colors.black.withAlpha(128),
334 + builder: (context) {
335 + return Padding(
336 + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
337 + child: SizedBox(
338 + height: MediaQuery.of(context).size.height * 0.6,
339 + child: ModalNavigator(parentContext: context, rootPage: Material(child: page))),
340 + );
341 + });
342 } else {
343 Navigator.pushNamed(
344 context,
@@ -371,15 +375,17 @@ class _CardsViewState extends State<CardsView> {
375 unspentCoinType: unspentCoinType,
376 mode: SendPageModes.lightningWithdrawal,
377 ));
374 - showCupertinoModalBottomSheet(context: context, barrierColor: Colors.black.withAlpha(128), builder: (context){
375 - return Padding(
376 - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
377 - child: SizedBox(
378 -height:MediaQuery.of(context).size.height*0.6,
379 - child:ModalNavigator(parentContext:context,rootPage: Material(child: page))
380 - ),
381 - );
382 - });
378 + showCupertinoModalBottomSheet(
379 + context: context,
380 + barrierColor: Colors.black.withAlpha(128),
381 + builder: (context) {
382 + return Padding(
383 + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
384 + child: SizedBox(
385 + height: MediaQuery.of(context).size.height * 0.6,
386 + child: ModalNavigator(parentContext: context, rootPage: Material(child: page))),
387 + );
388 + });
389 } else {
390 Navigator.pushNamed(
391 context,
lib/new-ui/widgets/coins_page/mweb_ad.dart
+2 -2
@@ -33,8 +33,8 @@ class MwebAd extends StatelessWidget {
33 child: Row(
34 mainAxisAlignment: MainAxisAlignment.spaceBetween,
35 children: [
36 - CakeImageWidget(imageUrl:
37 - "assets/new-ui/settings_row_icons/mweb.svg",
36 + CakeImageWidget(
37 + imageUrl: "assets/new-ui/settings_row_icons/mweb.svg",
38 width: 24,
39 height: 24,
40 ),
lib/new-ui/widgets/coins_page/top_bar_widget/chain_icon.dart
+3 -3
@@ -7,9 +7,9 @@ import 'package:flutter_svg/svg.dart';
7 class ChainIcon extends StatelessWidget {
8 const ChainIcon(
9 {super.key,
10 - required this.iconPath,
11 - required this.dashboardViewModel,
12 - required this.isSyncHeavy});
10 + required this.iconPath,
11 + required this.dashboardViewModel,
12 + required this.isSyncHeavy});
13
14 final String iconPath;
15 final bool isSyncHeavy;
lib/new-ui/widgets/coins_page/top_bar_widget/lightning_switcher.dart
+5 -3
@@ -48,7 +48,8 @@ class LightningSwitcher extends StatelessWidget {
48 duration: Duration(milliseconds: 150),
49 transitionBuilder: (child, animation) =>
50 FadeTransition(opacity: animation, child: child),
51 - child: CakeImageWidget(imageUrl:'assets/new-ui/switcher-bitcoin.svg',
51 + child: CakeImageWidget(
52 + imageUrl: 'assets/new-ui/switcher-bitcoin.svg',
53 key: ValueKey(lightningMode),
54 width: 32,
55 height: 32,
@@ -64,7 +65,8 @@ class LightningSwitcher extends StatelessWidget {
65 duration: Duration(milliseconds: 150),
66 transitionBuilder: (child, animation) =>
67 FadeTransition(opacity: animation, child: child),
67 - child: CakeImageWidget(imageUrl: 'assets/new-ui/switcher-lightning.svg',
68 + child: CakeImageWidget(
69 + imageUrl: 'assets/new-ui/switcher-lightning.svg',
70 key: ValueKey(lightningMode),
71 width: 32,
72 height: 32,
@@ -85,4 +87,4 @@ class LightningSwitcher extends StatelessWidget {
87 ),
88 );
89 }
88 -}
\ No newline at end of file
90 +}
lib/new-ui/widgets/coins_page/top_bar_widget/pulsing_dot.dart
+6 -6
@@ -1,8 +1,9 @@
1 import 'package:flutter/material.dart';
2
3 class PulsingDot extends StatefulWidget {
4 - const PulsingDot({super.key,});
5 -
4 + const PulsingDot({
5 + super.key,
6 + });
7
8 final double size = 5;
9 final Color color = const Color(0xFFFFC414);
@@ -14,8 +15,7 @@ class PulsingDot extends StatefulWidget {
15 State<PulsingDot> createState() => _PulsingDotState();
16 }
17
17 -class _PulsingDotState extends State<PulsingDot>
18 - with SingleTickerProviderStateMixin {
18 +class _PulsingDotState extends State<PulsingDot> with SingleTickerProviderStateMixin {
19 late final AnimationController controller;
20
21 @override
@@ -38,7 +38,7 @@ class _PulsingDotState extends State<PulsingDot>
38 duration: widget.fadeOutDuration,
39 );
40 await Future.delayed(widget.restDuration);
41 - if(!mounted) return;
41 + if (!mounted) return;
42 controller.value = 1.0;
43 }
44 }
@@ -63,4 +63,4 @@ class _PulsingDotState extends State<PulsingDot>
63 ),
64 );
65 }
66 -}
\ No newline at end of file
66 +}
lib/new-ui/widgets/coins_page/top_bar_widget/sync_bar.dart
+13 -12
@@ -68,7 +68,7 @@ class SyncBar extends StatelessWidget {
68 context: context,
69 barrierColor: Colors.black.withAlpha(85),
70 builder: (context) => FractionallySizedBox(
71 - child: Material(
71 + child: Material(
72 child: getIt.get<ManageNodesPage>(param1: false),
73 )));
74 },
@@ -147,15 +147,15 @@ class SyncBar extends StatelessWidget {
147
148 Widget? _getIcon(BuildContext context, Type status) {
149 if (status == LostConnectionSyncStatus || status == FailedSyncStatus) {
150 - return CakeImageWidget(imageUrl:
151 - "assets/new-ui/offline.svg",
150 + return CakeImageWidget(
151 + imageUrl: "assets/new-ui/offline.svg",
152 colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.error, BlendMode.srcIn),
153 );
154 }
155
156 if (failStatuses.contains(status)) {
157 - return CakeImageWidget(imageUrl:
158 - "assets/new-ui/warning.svg",
157 + return CakeImageWidget(
158 + imageUrl: "assets/new-ui/warning.svg",
159 colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.error, BlendMode.srcIn),
160 );
161 }
@@ -163,19 +163,20 @@ class SyncBar extends StatelessWidget {
163 final List<Widget> children = [];
164
165 if (dashboardViewModel.isTorEnabled) {
166 - children.add(CakeImageWidget(imageUrl:"assets/new-ui/tor_sync.svg",
166 + children.add(CakeImageWidget(
167 + imageUrl: "assets/new-ui/tor_sync.svg",
168 colorFilter: ColorFilter.mode(Color(0xFF8A38F5), BlendMode.srcIn)));
169 }
170 if (dashboardViewModel.hasMweb) {
170 - children.add(CakeImageWidget(imageUrl:
171 - "assets/new-ui/mweb_sync.svg",
171 + children.add(CakeImageWidget(
172 + imageUrl: "assets/new-ui/mweb_sync.svg",
173 colorFilter:
173 - ColorFilter.mode(Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
174 + ColorFilter.mode(Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
175 ));
176 }
177 if (dashboardViewModel.hasSilentPayments) {
177 - children.add(CakeImageWidget(imageUrl:
178 - "assets/new-ui/silent_sync.svg",
178 + children.add(CakeImageWidget(
179 + imageUrl: "assets/new-ui/silent_sync.svg",
180 colorFilter: ColorFilter.mode(Color(0xFFEFBA5E), BlendMode.srcIn),
181 ));
182 }
@@ -194,4 +195,4 @@ class SyncBar extends StatelessWidget {
195 bool _showDot() {
196 return !isSyncHeavy && progressStatuses.contains(dashboardViewModel.status.runtimeType);
197 }
197 -}
\ No newline at end of file
198 +}
lib/new-ui/widgets/coins_page/top_bar_widget/top_bar.dart
+3 -3
@@ -26,7 +26,8 @@ class TopBar extends StatelessWidget {
26 @override
27 Widget build(BuildContext context) {
28 return Padding(
29 - padding: EdgeInsets.only(bottom: 10, left: 18, right:18, top: 10+_additionalTopPadding(context)),
29 + padding: EdgeInsets.only(
30 + bottom: 10, left: 18, right: 18, top: 10 + _additionalTopPadding(context)),
31 child: Observer(
32 builder: (_) => Row(
33 spacing: 12,
@@ -59,10 +60,9 @@ class TopBar extends StatelessWidget {
60 );
61 }
62
62 -
63 //FIXME remove after this gets fixed flutter-side
64 double _additionalTopPadding(BuildContext context) {
65 - if(Platform.isIOS && MediaQuery.of(context).viewPadding.top < 12) return 24;
65 + if (Platform.isIOS && MediaQuery.of(context).viewPadding.top < 12) return 24;
66
67 return 0;
68 }
lib/new-ui/widgets/coins_page/unconfirmed_balance_widget.dart
+63 -64
@@ -23,83 +23,82 @@ class UnconfirmedBalanceWidget extends StatelessWidget {
23 .hasAdditionalBalance(dashboardViewModel.wallet.currency);
24
25 return AnimatedSize(
26 - duration: const Duration(milliseconds: 300),
27 - curve: Curves.easeOutCubic,
28 - alignment: Alignment.topCenter,
29 - child: show
30 - ? Column(
31 - children: [
32 - const SizedBox(height: 12, width: double.infinity),
33 - Observer(
34 - builder: (context) {
35 - final balance = dashboardViewModel.balanceViewModel.additionalBalance(currency);
26 + duration: const Duration(milliseconds: 300),
27 + curve: Curves.easeOutCubic,
28 + alignment: Alignment.topCenter,
29 + child: show
30 + ? Column(
31 + children: [
32 + const SizedBox(height: 12, width: double.infinity),
33 + Observer(builder: (context) {
34 + final balance = dashboardViewModel.balanceViewModel.additionalBalance(currency);
35
37 - return Container(
38 - width: MediaQuery.of(context).size.width * 0.87,
39 - height: 48,
40 - decoration: BoxDecoration(
41 - color: Theme.of(context).colorScheme.surfaceContainer,
42 - borderRadius: BorderRadius.circular(16.0),
43 - ),
44 - child: Material(
45 - color: Colors.transparent,
46 - child: InkWell(
47 - onTap: () {
48 - showMaterialModalBottomSheet(
49 - backgroundColor: Colors.transparent,
50 - context: context,
51 - builder: (context) => UnconfirmedBalanceModal(
52 - balance: balance.toStringWithSymbol(),
53 - currencyIconPath: currency.iconPath ?? "",
54 - ));
55 - },
56 - child: Padding(
57 - padding: const EdgeInsets.symmetric(horizontal: 12.0),
58 - child: Row(
59 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
36 + return Container(
37 + width: MediaQuery.of(context).size.width * 0.87,
38 + height: 48,
39 + decoration: BoxDecoration(
40 + color: Theme.of(context).colorScheme.surfaceContainer,
41 + borderRadius: BorderRadius.circular(16.0),
42 + ),
43 + child: Material(
44 + color: Colors.transparent,
45 + child: InkWell(
46 + onTap: () {
47 + showMaterialModalBottomSheet(
48 + backgroundColor: Colors.transparent,
49 + context: context,
50 + builder: (context) => UnconfirmedBalanceModal(
51 + balance: balance.toStringWithSymbol(),
52 + currencyIconPath: currency.iconPath ?? "",
53 + ));
54 + },
55 + child: Padding(
56 + padding: const EdgeInsets.symmetric(horizontal: 12.0),
57 + child: Row(
58 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
59 + children: [
60 + Row(
61 + spacing: 12,
62 children: [
63 + SizedBox(
64 + height: 20,
65 + width: 20,
66 + child: CircularProgressIndicator(
67 + strokeWidth: 2,
68 + backgroundColor:
69 + Theme.of(context).colorScheme.primary.withAlpha(50),
70 + color: Theme.of(context).colorScheme.primary,
71 + value: dashboardViewModel.confirmationProgress,
72 + ),
73 + ),
74 Row(
62 - spacing: 12,
75 + spacing: 4,
76 children: [
64 - SizedBox(
65 - height: 20,
66 - width: 20,
67 - child: CircularProgressIndicator(
68 - strokeWidth: 2,
69 - backgroundColor: Theme.of(context).colorScheme.primary.withAlpha(50),
77 + Text(
78 + "$balance ${currency.title}",
79 + style: TextStyle(
80 color: Theme.of(context).colorScheme.primary,
71 - value: dashboardViewModel.confirmationProgress,
81 ),
82 ),
74 - Row(
75 - spacing: 4,
76 - children: [
77 - Text(
78 - "$balance ${currency.title}",
79 - style: TextStyle(
80 - color: Theme.of(context).colorScheme.primary,
81 - ),
82 - ),
83 - Text(S.of(context).confirming),
84 - ],
85 - )
83 + Text(S.of(context).confirming),
84 ],
87 - ),
88 - Icon(
89 - Icons.chevron_right,
90 - color: Theme.of(context).colorScheme.onSurfaceVariant,
85 )
86 ],
87 ),
94 - ),
88 + Icon(
89 + Icons.chevron_right,
90 + color: Theme.of(context).colorScheme.onSurfaceVariant,
91 + )
92 + ],
93 ),
94 ),
97 - );
98 - }
99 - ),
100 - ],
101 - )
102 - : const SizedBox(width: double.infinity),
95 + ),
96 + ),
97 + );
98 + }),
99 + ],
100 + )
101 + : const SizedBox(width: double.infinity),
102 );
103 });
104 }
lib/new-ui/widgets/coins_page/wallet_info.dart
+8 -6
@@ -11,7 +11,8 @@ class WalletInfoBar extends StatelessWidget {
11 required this.lightningMode,
12 required this.name,
13 required this.hardwareWalletType,
14 - required this.onCustomizeButtonTap, required this.hasCustomize});
14 + required this.onCustomizeButtonTap,
15 + required this.hasCustomize});
16
17 final bool lightningMode;
18 final String name;
@@ -31,7 +32,6 @@ class WalletInfoBar extends StatelessWidget {
32 child: Row(
33 mainAxisSize: MainAxisSize.min,
34 mainAxisAlignment: MainAxisAlignment.center,
34 -
35 children: [
36 AnimatedSwitcher(
37 duration: Duration(milliseconds: 150),
@@ -46,8 +46,8 @@ class WalletInfoBar extends StatelessWidget {
46 ? const SizedBox.shrink(key: ValueKey("empty"))
47 : Padding(
48 padding: const EdgeInsets.only(right: 8),
49 - child: CakeImageWidget(imageUrl:
50 - hardwareWalletIcon!,
49 + child: CakeImageWidget(
50 + imageUrl: hardwareWalletIcon!,
51 key: ValueKey("hardware_wallet_icon"),
52 width: 24,
53 height: 24,
@@ -60,8 +60,10 @@ class WalletInfoBar extends StatelessWidget {
60 ),
61 Text(
62 name,
63 - style: Theme.of(context).textTheme.titleLarge?.copyWith(
64 - color: Theme.of(context).colorScheme.onSurface),
63 + style: Theme.of(context)
64 + .textTheme
65 + .titleLarge
66 + ?.copyWith(color: Theme.of(context).colorScheme.onSurface),
67 ),
68 if (hasCustomize) ...[
69 SizedBox(width: 8),
lib/new-ui/widgets/confirm_swiper.dart
+8 -8
@@ -44,8 +44,7 @@ class _ConfirmSwiperState extends State<ConfirmSwiper> {
44 return GestureDetector(
45 onHorizontalDragUpdate: (d) {
46 setState(() {
47 - drag = max(pillHorizontalPadding,
48 - min(maxDrag, drag + d.delta.dx));
47 + drag = max(pillHorizontalPadding, min(maxDrag, drag + d.delta.dx));
48 });
49 },
50 onHorizontalDragEnd: (_) {
@@ -69,9 +68,7 @@ class _ConfirmSwiperState extends State<ConfirmSwiper> {
68 height: pillSize + pillHorizontalPadding * 2,
69 width: areaWidth,
70 decoration: BoxDecoration(
72 - color: Theme.of(context)
73 - .colorScheme
74 - .surfaceContainerLowest,
71 + color: Theme.of(context).colorScheme.surfaceContainerLowest,
72 borderRadius: BorderRadius.circular(99999),
73 ),
74 child: Center(
@@ -116,8 +113,7 @@ class TrackClipper extends CustomClipper<Path> {
113 Path getClip(Size size) {
114 final left = cut.clamp(0.0, size.width);
115 final rect = Rect.fromLTRB(left, 0, size.width, size.height);
119 - return Path()
120 - ..addRRect(RRect.fromRectAndRadius(rect, Radius.circular(radius)));
116 + return Path()..addRRect(RRect.fromRectAndRadius(rect, Radius.circular(radius)));
117 }
118
119 @override
@@ -168,7 +164,11 @@ class _FlowingTextState extends State<FlowingText> with SingleTickerProviderStat
164 return LinearGradient(
165 begin: Alignment(-1 + (controller.value) * 2, 0),
166 end: Alignment(controller.value * 2, 0),
171 - colors: [Colors.transparent, Theme.of(context).colorScheme.surfaceContainerHighest, Colors.transparent],
167 + colors: [
168 + Colors.transparent,
169 + Theme.of(context).colorScheme.surfaceContainerHighest,
170 + Colors.transparent
171 + ],
172 ).createShader(r);
173 },
174 blendMode: BlendMode.srcATop,
lib/new-ui/widgets/copy_wrapper.dart
+1 -1
@@ -9,7 +9,7 @@ class CopyWrapper extends StatefulWidget {
9 const CopyWrapper(
10 {super.key,
11 this.data,
12 - this.requireLongPress = false,
12 + this.requireLongPress = false,
13 this.isSensitive = false,
14 required this.builder,
15 this.duration = const Duration(milliseconds: 1200)});
lib/new-ui/widgets/currency_picker/currency_picker_args.dart
+4 -4
@@ -16,8 +16,9 @@ final Set<String> _stablecoinSymbols = {
16 };
17
18 bool isTrustedStablecoin(CryptoCurrency c) =>
19 - (c.groups.contains(CurrencyGroups.stablecoin) ||
20 - _stablecoinSymbols.contains(c.title.toUpperCase())) && !c.isPotentialScam;
19 + (c.groups.contains(CurrencyGroups.stablecoin) ||
20 + _stablecoinSymbols.contains(c.title.toUpperCase())) &&
21 + !c.isPotentialScam;
22
23 const _kEvmDefaultTokenNatives = <CryptoCurrency>[
24 CryptoCurrency.baseEth,
@@ -44,8 +45,7 @@ void appendEvmDefaultTokens(List<CryptoCurrency> into) {
45 }
46
47 class CurrencyPickerBalance {
47 - const CurrencyPickerBalance(
48 - {required this.amount, this.fiat, this.fiatValue});
48 + const CurrencyPickerBalance({required this.amount, this.fiat, this.fiatValue});
49
50 final String amount;
51 final String? fiat;
lib/new-ui/widgets/currency_picker/picker_recents_loader.dart
+1 -3
@@ -39,9 +39,7 @@ class PickerRecentsLoader {
39 int limit,
40 ) async {
41 final trades = await Trade.getAll();
42 - final ordered = trades
43 - .where((t) => _executedTradeStates.contains(t.state))
44 - .toList()
42 + final ordered = trades.where((t) => _executedTradeStates.contains(t.state)).toList()
43 ..sort((a, b) => (b.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0))
44 .compareTo(a.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0)));
45
lib/new-ui/widgets/currency_picker/single_network_currency_picker.dart
+2 -4
@@ -47,10 +47,8 @@ class _SingleNetworkCurrencyPickerState extends State<SingleNetworkCurrencyPicke
47 Widget build(BuildContext context) {
48 final native = walletTypeToCryptoCurrency(_network);
49 final query = _searchController.text.trim();
50 - final tokens = _args.items
51 - .where((c) => c != native)
52 - .where((c) => currencyMatchesQuery(c, query))
53 - .toList();
50 + final tokens =
51 + _args.items.where((c) => c != native).where((c) => currencyMatchesQuery(c, query)).toList();
52
53 final insertOrder = {for (var i = 0; i < tokens.length; i++) tokens[i]: i};
54 tokens.sort((a, b) {
lib/new-ui/widgets/dropdown_row.dart
+1 -2
@@ -38,8 +38,7 @@ class DropdownRow extends StatelessWidget {
38 turns: expanded ? 0.0 : 0.5,
39 curve: Curves.easeOut,
40 child: CakeImageWidget(
41 - imageUrl:
42 - "assets/new-ui/dropdown_arrow.svg",
41 + imageUrl: "assets/new-ui/dropdown_arrow.svg",
42 colorFilter:
43 ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
44 ))
lib/new-ui/widgets/keyboard_hide_overlay.dart
+1 -2
@@ -75,8 +75,7 @@ class _KeyboardHideButtonState extends State<KeyboardHideButton> {
75 child: Padding(
76 padding: const EdgeInsets.all(8.0),
77 child: CakeImageWidget(
78 - imageUrl:
79 - "assets/new-ui/hide_keyboard.svg",
78 + imageUrl: "assets/new-ui/hide_keyboard.svg",
79 colorFilter: ColorFilter.mode(
80 Theme.of(context).colorScheme.onPrimary, BlendMode.srcIn),
81 ),
lib/new-ui/widgets/line_tab_switcher.dart
+37 -43
@@ -64,15 +64,13 @@ class _LineTabSwitcherState extends State<LineTabSwitcher> {
64 }
65
66 void measure() {
67 - if(textWidgetsMeasured) return;
67 + if (textWidgetsMeasured) return;
68 setState(() {
69 - textWidgetSizes = textWidgetKeys
70 - .map((k) => k.currentContext!.size)
71 - .whereType<Size>()
72 - .toList();
69 + textWidgetSizes =
70 + textWidgetKeys.map((k) => k.currentContext!.size).whereType<Size>().toList();
71
74 - for(final size in textWidgetSizes) {
75 - totalWidth += size.width+itemPadding;
72 + for (final size in textWidgetSizes) {
73 + totalWidth += size.width + itemPadding;
74 }
75 totalWidth += barPadding;
76 textWidgetsMeasured = true;
@@ -90,10 +88,9 @@ class _LineTabSwitcherState extends State<LineTabSwitcher> {
88 mainAxisAlignment: MainAxisAlignment.start,
89 children: [
90 Container(
93 - height: 28,
94 - child: Row(
95 - children: widget.tabs.map((item){
96 -
91 + height: 28,
92 + child: Row(
93 + children: widget.tabs.map((item) {
94 final index = widget.tabs.indexOf(item);
95
96 return GestureDetector(
@@ -107,15 +104,15 @@ class _LineTabSwitcherState extends State<LineTabSwitcher> {
104 AnimatedDefaultTextStyle(
105 duration: Duration(milliseconds: 150),
106 style: DefaultTextStyle.of(context).style.copyWith(
110 - inherit: true,
111 - fontSize: 16,
112 - fontWeight: FontWeight.w500,
113 - color: widget.selectedTab == index
114 - ? Theme.of(context).colorScheme.onSurface
115 - : Theme.of(context).colorScheme.onSurfaceVariant,
116 - ),
107 + inherit: true,
108 + fontSize: 16,
109 + fontWeight: FontWeight.w500,
110 + color: widget.selectedTab == index
111 + ? Theme.of(context).colorScheme.onSurface
112 + : Theme.of(context).colorScheme.onSurfaceVariant,
113 + ),
114 child: Padding(
118 - padding: EdgeInsets.symmetric(horizontal: itemPadding/2),
115 + padding: EdgeInsets.symmetric(horizontal: itemPadding / 2),
116 child: Text(
117 item,
118 key: textWidgetKeys[index],
@@ -125,34 +122,31 @@ class _LineTabSwitcherState extends State<LineTabSwitcher> {
122 ],
123 ),
124 );
128 - }).toList()
129 - )
130 - ),
131 - if(widget.tabs.length > 1)
132 - Container(
133 - width: totalWidth,
134 - height: 2,
135 - child: Stack(
136 - children: [
137 - AnimatedPositioned(
138 - curve: Curves.easeOut,
139 - left: _calcBarLeft(),
140 - bottom: 0,
141 - duration: Duration(milliseconds: 150),
142 - child: AnimatedSize(
125 + }).toList())),
126 + if (widget.tabs.length > 1)
127 + Container(
128 + width: totalWidth,
129 + height: 2,
130 + child: Stack(
131 + children: [
132 + AnimatedPositioned(
133 + curve: Curves.easeOut,
134 + left: _calcBarLeft(),
135 + bottom: 0,
136 duration: Duration(milliseconds: 150),
144 - child: Container(
145 - height: 2,
146 - width: textWidgetSizes.isEmpty
147 - ? 0
148 - : textWidgetSizes[widget.selectedTab].width,
149 - color: Theme.of(context).colorScheme.onSurface,
137 + child: AnimatedSize(
138 + duration: Duration(milliseconds: 150),
139 + child: Container(
140 + height: 2,
141 + width:
142 + textWidgetSizes.isEmpty ? 0 : textWidgetSizes[widget.selectedTab].width,
143 + color: Theme.of(context).colorScheme.onSurface,
144 + ),
145 ),
146 ),
152 - ),
153 - ],
147 + ],
148 + ),
149 ),
155 - ),
150 ],
151 );
152 }
lib/new-ui/widgets/long_press_menu.dart
+1 -2
@@ -76,8 +76,7 @@ class _LongPressMenuState extends State<LongPressMenu> {
76 spacing: 8,
77 children: [
78 CakeImageWidget(
79 - imageUrl:
80 - item.iconPath,
79 + imageUrl: item.iconPath,
80 height: 20,
81 width: 20,
82 colorFilter: ColorFilter.mode(color, BlendMode.srcIn),
lib/new-ui/widgets/modal_header.dart
+7 -5
@@ -3,7 +3,11 @@ import 'package:flutter/material.dart';
3
4 class ModalHeader extends StatelessWidget {
5 const ModalHeader(
6 - {super.key, required this.iconPath, required this.message, required this.title, this.bottomWidget});
6 + {super.key,
7 + required this.iconPath,
8 + required this.message,
9 + required this.title,
10 + this.bottomWidget});
11
12 final String iconPath;
13 final String title;
@@ -25,8 +29,7 @@ class ModalHeader extends StatelessWidget {
29 mainAxisAlignment: MainAxisAlignment.center,
30 crossAxisAlignment: CrossAxisAlignment.center,
31 children: [
28 - CakeImageWidget(
29 - imageUrl: iconPath, width: 36, height: 36),
32 + CakeImageWidget(imageUrl: iconPath, width: 36, height: 36),
33 Text(
34 title,
35 style: TextStyle(
@@ -44,7 +47,6 @@ class ModalHeader extends StatelessWidget {
47 color: Theme.of(context).colorScheme.onSurfaceVariant),
48 textAlign: TextAlign.center,
49 )),
47 -
50 ],
51 ),
52 ),
@@ -62,4 +64,4 @@ class ModalHeader extends StatelessWidget {
64 ),
65 );
66 }
65 -}
\ No newline at end of file
67 +}
lib/new-ui/widgets/modal_page_wrapper.dart
+7 -9
@@ -3,18 +3,17 @@ import 'package:cake_wallet/new-ui/widgets/receive_page/receive_top_bar.dart';
3 import 'package:flutter/material.dart';
4 import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
5
6 -void nothing(){}
6 +void nothing() {}
7
8 class ModalPageWrapper extends StatelessWidget {
9 ModalPageWrapper(
10 {super.key,
11 required this.content,
12 required this.topBar,
13 - this.header,
14 - this.bottomContent,
13 + this.header,
14 + this.bottomContent,
15 this.horizontalPadding = 18.0,
16 - this.verticalPadding = 72.0}) {
17 - }
16 + this.verticalPadding = 72.0}) {}
17
18 final Widget content;
19 final Widget? bottomContent;
@@ -35,8 +34,8 @@ class ModalPageWrapper extends StatelessWidget {
34 alignment: Alignment.topCenter,
35 children: [
36 Positioned.fill(
38 - child: Padding(
39 - padding: EdgeInsets.symmetric(horizontal: horizontalPadding),
37 + child: Padding(
38 + padding: EdgeInsets.symmetric(horizontal: horizontalPadding),
39 child: CustomScrollView(
40 controller: ModalScrollController.of(context),
41 physics: ClampingScrollPhysics(),
@@ -49,8 +48,7 @@ class ModalPageWrapper extends StatelessWidget {
48 SliverSafeArea(sliver: SliverToBoxAdapter(child: content)),
49 SliverToBoxAdapter(child: SizedBox(height: verticalPadding)),
50 ],
52 - )
53 - )),
51 + ))),
52 if (bottomContent != null)
53 Positioned(
54 bottom: 12,
lib/new-ui/widgets/modern_button.dart
+1 -1
@@ -83,4 +83,4 @@ class ModernButton extends StatelessWidget {
83 ],
84 );
85 }
86 -}
\ No newline at end of file
86 +}
lib/new-ui/widgets/new_primary_button.dart
+17 -16
@@ -26,7 +26,6 @@ class NewPrimaryButton extends StatelessWidget {
26
27 @override
28 Widget build(BuildContext context) {
29 -
29 return SizedBox(
30 height: 52.0,
31 child: TextButton(
@@ -42,23 +41,25 @@ class NewPrimaryButton extends StatelessWidget {
41 ),
42 ),
43 child: Center(
45 - child: isLoading ? CupertinoActivityIndicator() : Row(
46 - spacing: 10,
47 - mainAxisSize: MainAxisSize.min,
48 - children: <Widget>[
49 - if(image != null) image!,
50 - Text(
51 - text,
52 - style: Theme.of(context).textTheme.bodyMedium?.copyWith(
53 - fontSize: 14,
54 - fontWeight: FontWeight.w600,
55 - color: textColor,
44 + child: isLoading
45 + ? CupertinoActivityIndicator()
46 + : Row(
47 + spacing: 10,
48 + mainAxisSize: MainAxisSize.min,
49 + children: <Widget>[
50 + if (image != null) image!,
51 + Text(
52 + text,
53 + style: Theme.of(context).textTheme.bodyMedium?.copyWith(
54 + fontSize: 14,
55 + fontWeight: FontWeight.w600,
56 + color: textColor,
57 + ),
58 + )
59 + ],
60 ),
57 - )
58 - ],
59 - ),
61 ),
62 ),
63 );
64 }
64 -}
\ No newline at end of file
65 +}
lib/new-ui/widgets/picker.dart
+95 -52
@@ -67,7 +67,7 @@ class _NewPickerState<Item> extends State<NewPicker<Item>> {
67 @override
68 Widget build(BuildContext context) {
69 return Observer(
70 - builder: (_)=>Container(
70 + builder: (_) => Container(
71 decoration: BoxDecoration(
72 color: Theme.of(context).colorScheme.surface,
73 borderRadius: BorderRadius.vertical(top: Radius.circular(24))),
@@ -86,11 +86,18 @@ class _NewPickerState<Item> extends State<NewPicker<Item>> {
86 mainAxisSize: MainAxisSize.min,
87 children: [
88 if (widget.description != null && widget.description!.isNotEmpty)
89 - Text(widget.description!,textAlign: TextAlign.center,style: TextStyle(fontSize:14,fontWeight: FontWeight.w400,color: Theme.of(context).colorScheme.onSurfaceVariant),),
90 - SizedBox(height:16),
89 + Text(
90 + widget.description!,
91 + textAlign: TextAlign.center,
92 + style: TextStyle(
93 + fontSize: 14,
94 + fontWeight: FontWeight.w400,
95 + color: Theme.of(context).colorScheme.onSurfaceVariant),
96 + ),
97 + SizedBox(height: 16),
98 ...widget.items.map((item) {
99 final isSelected = widget.items.indexOf(item) == widget.selectedIndex;
93 - return Column( children: [
100 + return Column(children: [
101 if (item.isSliderItem)
102 PickerSliderButton(
103 key: ValueKey(isSelected),
@@ -99,22 +106,23 @@ class _NewPickerState<Item> extends State<NewPicker<Item>> {
106 onSelected: (item) {
107 Navigator.of(context).push(MaterialPageRoute(
108 builder: (context) => Material(
102 - child: PickerSliderPage(
103 - title: widget.sliderPageTitle,
104 - sliderInitialValue: sliderCurrentValue!,
105 - valueDescription: widget.sliderValueDescription ?? "",
106 - sliderMaxValue: widget.sliderMaxValue!,
107 - onSubmitted: (value) {
108 - setState(() {
109 - sliderCurrentValue = value;
110 - });
111 - widget.onSliderChanged?.call(value);
112 - widget.onItemSelected(item);
113 - }),
114 - )));
109 + child: PickerSliderPage(
110 + title: widget.sliderPageTitle,
111 + sliderInitialValue: sliderCurrentValue!,
112 + valueDescription: widget.sliderValueDescription ?? "",
113 + sliderMaxValue: widget.sliderMaxValue!,
114 + onSubmitted: (value) {
115 + setState(() {
116 + sliderCurrentValue = value;
117 + });
118 + widget.onSliderChanged?.call(value);
119 + widget.onItemSelected(item);
120 + }),
121 + )));
122 },
123 isFirst: widget.items.indexOf(item) == 0,
117 - customSubtitle: "${sliderCurrentValue?.toInt()} ${widget.sliderValueDescription}",
124 + customSubtitle:
125 + "${sliderCurrentValue?.toInt()} ${widget.sliderValueDescription}",
126 isLast: widget.items.indexOf(item) == widget.items.length - 1,
127 )
128 else
@@ -169,7 +177,8 @@ class PickerSliderButton<Item> extends StatelessWidget {
177 required this.isSelected,
178 required this.onSelected,
179 required this.isFirst,
172 - required this.isLast, this.customSubtitle});
180 + required this.isLast,
181 + this.customSubtitle});
182
183 final PickerItem<Item> item;
184 final bool isSelected;
@@ -186,7 +195,7 @@ class PickerSliderButton<Item> extends StatelessWidget {
195 },
196 child: Container(
197 height: 64,
189 - width: MediaQuery.of(context).size.height*0.9,
198 + width: MediaQuery.of(context).size.height * 0.9,
199 decoration: BoxDecoration(
200 color: Theme.of(context).colorScheme.surfaceContainer,
201 borderRadius: BorderRadius.vertical(
@@ -217,24 +226,29 @@ class PickerSliderButton<Item> extends StatelessWidget {
226 fontSize: 14,
227 color: Theme.of(context).colorScheme.onSurfaceVariant,
228 fontWeight: FontWeight.w400)),
220 - if(isSelected) CakeImageWidget(imageUrl:
221 - "assets/new-ui/arrow_right.svg",
222 - colorFilter:
223 - ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),)
229 + if (isSelected)
230 + CakeImageWidget(
231 + imageUrl: "assets/new-ui/arrow_right.svg",
232 + colorFilter: ColorFilter.mode(
233 + Theme.of(context).colorScheme.primary, BlendMode.srcIn),
234 + )
235 ],
236 ),
226 - if (customSubtitle != null || item.subtitle != null) Text(customSubtitle ?? item.subtitle!,style: TextStyle(
227 - fontSize: 12,
228 - color: Theme.of(context).colorScheme.onSurfaceVariant,
229 - fontWeight: FontWeight.w400))
237 + if (customSubtitle != null || item.subtitle != null)
238 + Text(customSubtitle ?? item.subtitle!,
239 + style: TextStyle(
240 + fontSize: 12,
241 + color: Theme.of(context).colorScheme.onSurfaceVariant,
242 + fontWeight: FontWeight.w400))
243 ],
244 ),
232 - isSelected? NewSimpleCheckbox(value: true, onChanged: (val){}):
233 - CakeImageWidget(imageUrl:
234 - "assets/new-ui/arrow_right.svg",
235 - colorFilter:
236 - ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
237 - )
245 + isSelected
246 + ? NewSimpleCheckbox(value: true, onChanged: (val) {})
247 + : CakeImageWidget(
248 + imageUrl: "assets/new-ui/arrow_right.svg",
249 + colorFilter:
250 + ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
251 + )
252 ],
253 ),
254 ),
@@ -266,7 +280,7 @@ class PickerRow<Item> extends StatelessWidget {
280 },
281 child: Container(
282 height: 64,
269 - width: MediaQuery.of(context).size.height*0.9,
283 + width: MediaQuery.of(context).size.height * 0.9,
284 decoration: BoxDecoration(
285 color: Theme.of(context).colorScheme.surfaceContainer,
286 borderRadius: BorderRadius.vertical(
@@ -299,19 +313,30 @@ class PickerRow<Item> extends StatelessWidget {
313 fontWeight: FontWeight.w400))
314 ],
315 ),
302 - item.subtitle != null ? Text(item.subtitle!,style: TextStyle(
303 - fontSize: 12,
304 - color: Theme.of(context).colorScheme.onSurfaceVariant,
305 - fontWeight: FontWeight.w400)) : SizedBox.shrink()
316 + item.subtitle != null
317 + ? Text(item.subtitle!,
318 + style: TextStyle(
319 + fontSize: 12,
320 + color: Theme.of(context).colorScheme.onSurfaceVariant,
321 + fontWeight: FontWeight.w400))
322 + : SizedBox.shrink()
323 ],
324 ),
325 AnimatedSwitcher(
309 - duration: Duration(milliseconds: 100),
310 -
326 + duration: Duration(milliseconds: 100),
327 child: isSelected
312 - ? NewSimpleCheckbox(key: ValueKey(1), value: true, onChanged: (val){onSelected(item.value);})
313 - : NewSimpleCheckbox(key: ValueKey(0), value: false, onChanged: (val){onSelected(item.value);})
314 - )
328 + ? NewSimpleCheckbox(
329 + key: ValueKey(1),
330 + value: true,
331 + onChanged: (val) {
332 + onSelected(item.value);
333 + })
334 + : NewSimpleCheckbox(
335 + key: ValueKey(0),
336 + value: false,
337 + onChanged: (val) {
338 + onSelected(item.value);
339 + }))
340 ],
341 ),
342 ),
@@ -369,10 +394,24 @@ class _PickerSliderPageState<Item> extends State<PickerSliderPage<Item>> {
394 mainAxisAlignment: MainAxisAlignment.center,
395 mainAxisSize: MainAxisSize.max,
396 children: [
372 - Row(mainAxisAlignment:MainAxisAlignment.center,spacing:4,children: [
373 - Text(sliderValue.toStringAsFixed(0), style: TextStyle(fontSize:18,fontWeight: FontWeight.w600,color: Theme.of(context).colorScheme.primary),),
374 - Text(widget.valueDescription, style: TextStyle(fontSize:18,fontWeight: FontWeight.w600,color: Theme.of(context).colorScheme.onSurface)),
375 - ],),
397 + Row(
398 + mainAxisAlignment: MainAxisAlignment.center,
399 + spacing: 4,
400 + children: [
401 + Text(
402 + sliderValue.toStringAsFixed(0),
403 + style: TextStyle(
404 + fontSize: 18,
405 + fontWeight: FontWeight.w600,
406 + color: Theme.of(context).colorScheme.primary),
407 + ),
408 + Text(widget.valueDescription,
409 + style: TextStyle(
410 + fontSize: 18,
411 + fontWeight: FontWeight.w600,
412 + color: Theme.of(context).colorScheme.onSurface)),
413 + ],
414 + ),
415 Padding(
416 padding: const EdgeInsets.symmetric(horizontal: 16.0),
417 child: Slider(
@@ -394,10 +433,14 @@ class _PickerSliderPageState<Item> extends State<PickerSliderPage<Item>> {
433 ),
434 Padding(
435 padding: const EdgeInsets.all(16.0),
397 - child: NewPrimaryButton(onPressed: (){
398 - widget.onSubmitted(sliderValue);
399 - Navigator.of(context).pop();
400 - }, text: "Continue", color: Theme.of(context).colorScheme.primary, textColor: Theme.of(context).colorScheme.onPrimary),
436 + child: NewPrimaryButton(
437 + onPressed: () {
438 + widget.onSubmitted(sliderValue);
439 + Navigator.of(context).pop();
440 + },
441 + text: "Continue",
442 + color: Theme.of(context).colorScheme.primary,
443 + textColor: Theme.of(context).colorScheme.onPrimary),
444 )
445 ],
446 ),
lib/new-ui/widgets/receive_page/payjoin_copy_modal.dart
+1 -1
@@ -56,7 +56,7 @@ class PayjoinCopyModal extends StatelessWidget {
56 ]
57 }),
58 ),
59 - SizedBox(height:128)
59 + SizedBox(height: 128)
60 ],
61 ),
62 ),
lib/new-ui/widgets/receive_page/receive_address_type.dart
+2 -1
@@ -52,7 +52,8 @@ class ReceiveAddressTypeDisplay extends StatelessWidget {
52 spacing: 12.0,
53 children: [
54 if (iconPath != null)
55 - CakeImageWidget(imageUrl:iconPath,
55 + CakeImageWidget(
56 + imageUrl: iconPath,
57 width: 24,
58 height: 24,
59 colorFilter: ColorFilter.mode(
lib/new-ui/widgets/receive_page/receive_address_type_selector.dart
+9 -2
@@ -160,7 +160,8 @@ class _ReceiveAddressTypeSelectorState extends State<ReceiveAddressTypeSelector>
160 ReceiveAddressTypeSelector.otherOptionsExpandDuration,
161 turns: _otherOptionsExpanded ? 0.0 : 0.5,
162 curve: Curves.easeOut,
163 - child: CakeImageWidget(imageUrl:"assets/new-ui/dropdown_arrow.svg"))
163 + child: CakeImageWidget(
164 + imageUrl: "assets/new-ui/dropdown_arrow.svg"))
165 ],
166 ),
167 ),
@@ -280,7 +281,13 @@ class ReceiveAddressTypeRow extends StatelessWidget {
281 Row(
282 children: [
283 if (iconPath != null)
283 - CakeImageWidget(imageUrl:iconPath!, width: iconSize, height: iconSize,colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.onSurfaceVariant,BlendMode.srcIn),)
284 + CakeImageWidget(
285 + imageUrl: iconPath!,
286 + width: iconSize,
287 + height: iconSize,
288 + colorFilter: ColorFilter.mode(
289 + Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
290 + )
291 else
292 Container(width: iconSize, height: iconSize),
293 Padding(
lib/new-ui/widgets/receive_page/receive_amount_display.dart
+52 -56
@@ -3,7 +3,6 @@ import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_v
3 import 'package:flutter/material.dart';
4 import 'package:flutter_mobx/flutter_mobx.dart';
5
6 -
6 class ReceiveAmountDisplay extends StatelessWidget {
7 const ReceiveAmountDisplay(
8 {super.key, required this.walletAddressListViewModel, required this.largeQrMode});
@@ -11,69 +10,66 @@ class ReceiveAmountDisplay extends StatelessWidget {
10 final WalletAddressListViewModel walletAddressListViewModel;
11 final bool largeQrMode;
12
14 -
13 @override
14 Widget build(BuildContext context) {
15 return Observer(
18 - builder: (_) =>
19 - AnimatedOpacity(
20 - duration: Duration(milliseconds: 300),
21 - curve: Curves.easeOutCubic,
22 - opacity: largeQrMode || walletAddressListViewModel.displayAmount.isEmpty ? 0 : 1,
23 - child: AnimatedAlign(
24 - duration: Duration(milliseconds: 300),
25 - curve: Curves.easeOutCubic,
26 - heightFactor: largeQrMode || walletAddressListViewModel.displayAmount.isEmpty ? 0 : 1,
27 - alignment: Alignment.topCenter,
28 - child: Container(
29 - width: double.infinity,
30 - child: Row(
31 - spacing: 4,
32 - mainAxisSize: MainAxisSize.min,
33 - mainAxisAlignment: MainAxisAlignment.center,
34 - children: [
35 - Container(
36 - decoration: BoxDecoration(
37 - borderRadius: BorderRadius.circular(12),
38 - color: Theme
39 - .of(context)
40 - .colorScheme
41 - .surfaceContainer
42 - ),
43 - child:
44 - Padding(
45 - padding: const EdgeInsets.all(8.0),
46 - child: Row(
47 - spacing: 8.0,
48 - children: [
49 - Text(walletAddressListViewModel.displayAmount, style: TextStyle(color: Theme
50 - .of(context)
51 - .colorScheme
52 - .primary, fontSize: 16, fontWeight: FontWeight.w500),),
53 - Text(walletAddressListViewModel.cryptoCurrencySymbol,
54 - style: TextStyle(color: Theme
55 - .of(context)
56 - .colorScheme
57 - .primary, fontSize: 16, fontWeight: FontWeight.w500))
58 - ],
16 + builder: (_) => AnimatedOpacity(
17 + duration: Duration(milliseconds: 300),
18 + curve: Curves.easeOutCubic,
19 + opacity: largeQrMode || walletAddressListViewModel.displayAmount.isEmpty ? 0 : 1,
20 + child: AnimatedAlign(
21 + duration: Duration(milliseconds: 300),
22 + curve: Curves.easeOutCubic,
23 + heightFactor: largeQrMode || walletAddressListViewModel.displayAmount.isEmpty ? 0 : 1,
24 + alignment: Alignment.topCenter,
25 + child: Container(
26 + width: double.infinity,
27 + child: Row(
28 + spacing: 4,
29 + mainAxisSize: MainAxisSize.min,
30 + mainAxisAlignment: MainAxisAlignment.center,
31 + children: [
32 + Container(
33 + decoration: BoxDecoration(
34 + borderRadius: BorderRadius.circular(12),
35 + color: Theme.of(context).colorScheme.surfaceContainer),
36 + child: Padding(
37 + padding: const EdgeInsets.all(8.0),
38 + child: Row(
39 + spacing: 8.0,
40 + children: [
41 + Text(
42 + walletAddressListViewModel.displayAmount,
43 + style: TextStyle(
44 + color: Theme.of(context).colorScheme.primary,
45 + fontSize: 16,
46 + fontWeight: FontWeight.w500),
47 ),
60 - ),
61 -
48 + Text(walletAddressListViewModel.cryptoCurrencySymbol,
49 + style: TextStyle(
50 + color: Theme.of(context).colorScheme.primary,
51 + fontSize: 16,
52 + fontWeight: FontWeight.w500))
53 + ],
54 ),
63 - if(!walletAddressListViewModel.isFiatDisabled)
64 - Padding(
65 - padding: const EdgeInsets.all(8.0),
66 - child: Text(_getFiatAmount(),
67 - style: TextStyle(color: Theme
68 - .of(context)
69 - .colorScheme
70 - .onSurfaceVariant, fontSize: 16, fontWeight: FontWeight.w500),),
71 - )
72 - ],
55 + ),
56 ),
74 - ),
57 + if (!walletAddressListViewModel.isFiatDisabled)
58 + Padding(
59 + padding: const EdgeInsets.all(8.0),
60 + child: Text(
61 + _getFiatAmount(),
62 + style: TextStyle(
63 + color: Theme.of(context).colorScheme.onSurfaceVariant,
64 + fontSize: 16,
65 + fontWeight: FontWeight.w500),
66 + ),
67 + )
68 + ],
69 ),
70 ),
71 + ),
72 + ),
73 );
74 }
75
lib/new-ui/widgets/receive_page/receive_amount_modal.dart
+8 -8
@@ -30,7 +30,7 @@ class _ReceiveAmountModalState extends State<ReceiveAmountModal> {
30 @override
31 void initState() {
32 super.initState();
33 - if(widget.walletAddressListViewModel.selectedCurrency is FiatCurrency) {
33 + if (widget.walletAddressListViewModel.selectedCurrency is FiatCurrency) {
34 _amountController.text = widget.walletAddressListViewModel.fiatAmount;
35 } else {
36 _amountController.text = widget.walletAddressListViewModel.displayAmount;
@@ -103,7 +103,8 @@ class _ReceiveAmountModalState extends State<ReceiveAmountModal> {
103 ),
104 RotatedBox(
105 quarterTurns: 2,
106 - child: CakeImageWidget(imageUrl:"assets/new-ui/dropdown_arrow.svg"))
106 + child: CakeImageWidget(
107 + imageUrl: "assets/new-ui/dropdown_arrow.svg"))
108 ],
109 ),
110 ),
@@ -137,7 +138,8 @@ class _ReceiveAmountModalState extends State<ReceiveAmountModal> {
138 controller: _amountController,
139 keyboardType: TextInputType.numberWithOptions(
140 signed: false,
140 - decimal: widget.walletAddressListViewModel.selectedCurrencyDecimals > 0,
141 + decimal:
142 + widget.walletAddressListViewModel.selectedCurrencyDecimals > 0,
143 ),
144 inputFormatters: [
145 DecimalInputFormatter(
@@ -159,7 +161,6 @@ class _ReceiveAmountModalState extends State<ReceiveAmountModal> {
161 border: InputBorder.none,
162 filled: true,
163 fillColor: Colors.transparent,
162 -
164 ),
165 style: TextStyle(color: Theme.of(context).colorScheme.onSurface),
166 ),
@@ -209,7 +210,7 @@ class _ReceiveAmountModalState extends State<ReceiveAmountModal> {
210 NewPrimaryButton(
211 text: S.of(context).continue_text,
212 onPressed: () {
212 - if(double.tryParse(_amountController.text) != null) {
213 + if (double.tryParse(_amountController.text) != null) {
214 widget.walletAddressListViewModel.changeAmount(_amountController.text);
215 }
216 Navigator.of(context).pop();
@@ -228,9 +229,8 @@ class _ReceiveAmountModalState extends State<ReceiveAmountModal> {
229 }
230
231 void _presentTokenCurrencyPicker(BuildContext context) {
231 - final items = widget.walletAddressListViewModel.tokenCurrencies
232 - .whereType<CryptoCurrency>()
233 - .toList();
232 + final items =
233 + widget.walletAddressListViewModel.tokenCurrencies.whereType<CryptoCurrency>().toList();
234 CurrencyPickerSheet.show(
235 context: context,
236 args: CurrencyPickerArgs(
lib/new-ui/widgets/receive_page/receive_bottom_buttons.dart
+27 -22
@@ -34,7 +34,6 @@ class ReceiveBottomButtons extends StatefulWidget {
34 }
35
36 class _ReceiveBottomButtonsState extends State<ReceiveBottomButtons> {
37 -
37 @override
38 Widget build(BuildContext context) {
39 final double targetOpacity = widget.largeQrMode ? 0 : 1;
@@ -57,27 +56,33 @@ class _ReceiveBottomButtonsState extends State<ReceiveBottomButtons> {
56 spacing: 16,
57 children: [
58 GestureDetector(
60 - onTap: widget.copyData == null ? widget.onCopyButtonPressed : null,
61 - child: IgnorePointer(
62 - ignoring: widget.copyData == null,
63 - child: CopyWrapper(
64 - data: widget.copyData,
65 - builder: (context, copied) => AnimatedSwitcher(
66 - duration: Duration(milliseconds: 200),
67 - child: IgnorePointer(
68 - child: ModernButton.svg(
69 - key: ValueKey(copied),
70 - size: 60,
71 - iconSize: 32,
72 - svgPath: "assets/new-ui/copy.svg",
73 - onPressed: () {},
74 - label: copied ? S.of(context).copied : S.of(context).copy,
75 - iconColor: copied ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.surfaceContainer,
76 - backgroundColor: copied ? Theme.of(context).colorScheme.surfaceContainerHighest : Theme.of(context).colorScheme.primary,
77 - ),
78 - ),
59 + onTap: widget.copyData == null ? widget.onCopyButtonPressed : null,
60 + child: IgnorePointer(
61 + ignoring: widget.copyData == null,
62 + child: CopyWrapper(
63 + data: widget.copyData,
64 + builder: (context, copied) => AnimatedSwitcher(
65 + duration: Duration(milliseconds: 200),
66 + child: IgnorePointer(
67 + child: ModernButton.svg(
68 + key: ValueKey(copied),
69 + size: 60,
70 + iconSize: 32,
71 + svgPath: "assets/new-ui/copy.svg",
72 + onPressed: () {},
73 + label: copied ? S.of(context).copied : S.of(context).copy,
74 + iconColor: copied
75 + ? Theme.of(context).colorScheme.primary
76 + : Theme.of(context).colorScheme.surfaceContainer,
77 + backgroundColor: copied
78 + ? Theme.of(context).colorScheme.surfaceContainerHighest
79 + : Theme.of(context).colorScheme.primary,
80 ),
80 - ),),),
81 + ),
82 + ),
83 + ),
84 + ),
85 + ),
86 ModernButton.svg(
87 size: 60,
88 iconSize: 32,
@@ -105,4 +110,4 @@ class _ReceiveBottomButtonsState extends State<ReceiveBottomButtons> {
110 ),
111 );
112 }
108 -}
\ No newline at end of file
113 +}
lib/new-ui/widgets/receive_page/receive_info_box.dart
+25 -20
@@ -10,9 +10,16 @@ import 'package:flutter/material.dart';
10
11 class ReceiveInfoBox extends StatelessWidget {
12 ReceiveInfoBox(
13 - {super.key, required this.iconPath, required this.message, required this.onDismissed, this.bottomWidget});
13 + {super.key,
14 + required this.iconPath,
15 + required this.message,
16 + required this.onDismissed,
17 + this.bottomWidget});
18
15 - static ReceiveInfoBox? forWalletType(WalletType type, {required VoidCallback onDismissed, required AutoGenerateSubaddressStatus autoGenerateSubaddressStatus, List<CryptoCurrency>? supportedCurrencies}) {
19 + static ReceiveInfoBox? forWalletType(WalletType type,
20 + {required VoidCallback onDismissed,
21 + required AutoGenerateSubaddressStatus autoGenerateSubaddressStatus,
22 + List<CryptoCurrency>? supportedCurrencies}) {
23 switch (type) {
24 case WalletType.nano:
25 return null;
@@ -24,21 +31,18 @@ class ReceiveInfoBox extends StatelessWidget {
31 case WalletType.polygon:
32 case WalletType.zano:
33 case WalletType.bsc:
27 - if(autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.disabled)
28 - return null;
34 + if (autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.disabled) return null;
35 return ReceiveInfoBox(
30 - iconPath: "",
31 - message:
32 - "${S.current.infobox_multichain} ${walletTypeToString(type)}",
33 - onDismissed: onDismissed,
36 + iconPath: "",
37 + message: "${S.current.infobox_multichain} ${walletTypeToString(type)}",
38 + onDismissed: onDismissed,
39 bottomWidget: InfoboxCurrencyRow(
40 currencies: supportedCurrencies ?? [],
41 chainIconPath:
42 "assets/new-ui/chain_badges/${walletTypeToString(type).toLowerCase()}.svg",
43 ));
44 default:
40 - if(autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.disabled)
41 - return null;
45 + if (autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.disabled) return null;
46 return ReceiveInfoBox(
47 iconPath: "assets/new-ui/info.svg",
48 message: S.current.infobox_auto_address,
@@ -66,14 +70,14 @@ class ReceiveInfoBox extends StatelessWidget {
70 crossAxisAlignment: CrossAxisAlignment.start,
71 spacing: 10,
72 children: [
69 - if(iconPath.isNotEmpty)
70 - CakeImageWidget(imageUrl:
71 - iconPath,
72 - width: 16,
73 - height: 16,
74 - colorFilter: ColorFilter.mode(
75 - Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
76 - ),
73 + if (iconPath.isNotEmpty)
74 + CakeImageWidget(
75 + imageUrl: iconPath,
76 + width: 16,
77 + height: 16,
78 + colorFilter: ColorFilter.mode(
79 + Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
80 + ),
81 Flexible(
82 child: Column(
83 spacing: 10,
@@ -126,8 +130,9 @@ class InfoboxCurrencyRow extends StatelessWidget {
130
131 @override
132 Widget build(BuildContext context) {
129 - final currenciesWithImage = currencies.where((item)=>item.iconPath != null).toList();
130 - final currenciesLimited = currenciesWithImage.sublist(0, min(currenciesWithImage.length, maxCurrencies));
133 + final currenciesWithImage = currencies.where((item) => item.iconPath != null).toList();
134 + final currenciesLimited =
135 + currenciesWithImage.sublist(0, min(currenciesWithImage.length, maxCurrencies));
136
137 final double stackWidth = iconSize + (overlap * (currenciesLimited.length));
138
lib/new-ui/widgets/receive_page/receive_label_modal.dart
+8 -4
@@ -9,8 +9,6 @@ import 'package:flutter/material.dart';
9 import 'package:flutter_mobx/flutter_mobx.dart';
10 import 'package:mobx/mobx.dart';
11
12 -
13 -
12 class ReceiveLabelModal extends StatefulWidget {
13 const ReceiveLabelModal({super.key, required this.walletAddressEditOrCreateViewModel});
14
@@ -45,7 +43,13 @@ class _ReceiveLabelModalState extends State<ReceiveLabelModal> {
43
44 @override
45 Widget build(BuildContext context) {
48 - List<String> defaultLabels = [S.of(context).donation, S.of(context).savings, S.of(context).business, S.of(context).mining, S.of(context).salary];
46 + List<String> defaultLabels = [
47 + S.of(context).donation,
48 + S.of(context).savings,
49 + S.of(context).business,
50 + S.of(context).mining,
51 + S.of(context).salary
52 + ];
53
54 return Padding(
55 padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
@@ -54,7 +58,7 @@ class _ReceiveLabelModalState extends State<ReceiveLabelModal> {
58 color: Theme.of(context).colorScheme.surface,
59 borderRadius: BorderRadius.vertical(top: Radius.circular(16))),
60 child: SafeArea(
57 - top:false,
61 + top: false,
62 child: Column(
63 spacing: 24,
64 mainAxisSize: MainAxisSize.min,
lib/new-ui/widgets/receive_page/receive_label_widget.dart
+2 -1
@@ -23,7 +23,8 @@ class ReceiveLabelWidget extends StatelessWidget {
23 mainAxisSize: MainAxisSize.min,
24 children: [
25 ClipRect(
26 - child: CakeImageWidget(imageUrl:"assets/new-ui/label.svg",
26 + child: CakeImageWidget(
27 + imageUrl: "assets/new-ui/label.svg",
28 width: 24,
29 height: 24,
30 colorFilter: ColorFilter.mode(
lib/new-ui/widgets/receive_page/receive_large_amount_preview.dart
+2 -1
@@ -30,7 +30,8 @@ class ReceiveLargeAmountPreview extends StatelessWidget {
30 mainAxisAlignment: MainAxisAlignment.center,
31 spacing: 12,
32 children: [
33 - CakeImageWidget(imageUrl:"assets/new-ui/send.svg",
33 + CakeImageWidget(
34 + imageUrl: "assets/new-ui/send.svg",
35 width: 24,
36 height: 24,
37 colorFilter: ColorFilter.mode(
lib/new-ui/widgets/receive_page/receive_qr_code.dart
+7 -7
@@ -27,11 +27,11 @@ class ReceiveQrCode extends StatelessWidget {
27 static const Duration animDuration = Duration(milliseconds: 500);
28 final bool isLightMode = !(getIt.get<ThemeStore>().currentTheme.isDark);
29
30 -
30 @override
31 Widget build(BuildContext context) {
33 - final double targetY = largeQrMode ? largeQrModeBottomPadding+50 : 0;
34 - final double resolvedSize = min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height) * 0.5;
32 + final double targetY = largeQrMode ? largeQrModeBottomPadding + 50 : 0;
33 + final double resolvedSize =
34 + min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height) * 0.5;
35 final double resolvedScale = largeQrMode ? 1.7 : 1;
36
37 return Stack(
@@ -44,8 +44,8 @@ class ReceiveQrCode extends StatelessWidget {
44 child: AnimatedOpacity(
45 duration: animDuration,
46 opacity: largeQrMode ? 1 : 0,
47 - child: CakeImageWidget(imageUrl:
48 - isLightMode
47 + child: CakeImageWidget(
48 + imageUrl: isLightMode
49 ? "assets/new-ui/cakewallet-wordmark-light.svg"
50 : "assets/new-ui/cakewallet-wordmark.svg",
51 height: 45,
@@ -118,7 +118,7 @@ class ReceiveQrCode extends StatelessWidget {
118 mainAxisAlignment: MainAxisAlignment.center,
119 spacing: 4,
120 children: [
121 - CakeImageWidget(imageUrl:"assets/new-ui/payjoin.svg"),
121 + CakeImageWidget(imageUrl: "assets/new-ui/payjoin.svg"),
122 Text(S.of(context).payjoin_enabled)
123 ],
124 ),
@@ -126,7 +126,7 @@ class ReceiveQrCode extends StatelessWidget {
126 AnimatedSize(
127 duration: animDuration,
128 curve: Curves.easeOutCubic,
129 - child: SizedBox(height: largeQrMode ? largeQrModeBottomPadding+40 : 0))
129 + child: SizedBox(height: largeQrMode ? largeQrModeBottomPadding + 40 : 0))
130 ],
131 ),
132 )),
lib/new-ui/widgets/receive_page/receive_token_display.dart
+5 -6
@@ -12,8 +12,8 @@ class ReceiveTokenDisplay extends StatelessWidget {
12
13 @override
14 Widget build(BuildContext context) {
15 - return Observer(
16 - builder: (_)=>Row(
15 + return Observer(
16 + builder: (_) => Row(
17 mainAxisAlignment: MainAxisAlignment.center,
18 spacing: 8,
19 children: [
@@ -31,16 +31,15 @@ class ReceiveTokenDisplay extends StatelessWidget {
31 child: Padding(
32 padding: const EdgeInsets.all(4.0),
33 child: Row(
34 - spacing:4,
34 + spacing: 4,
35 children: [
36 CakeImageWidget(
37 imageUrl:
38 "assets/new-ui/chain_badges/${addressListViewModel.wallet.type == WalletType.bsc ? 'bnb' : walletTypeToString(addressListViewModel.wallet.type).toLowerCase()}.svg",
39 width: 16,
40 height: 16,
41 - colorFilter: ColorFilter.mode(
42 - Theme.of(context).colorScheme.primary,
43 - BlendMode.srcIn),
41 + colorFilter:
42 + ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
43 ),
44 Text(walletTypeToString(addressListViewModel.wallet.type),
45 style: TextStyle(
lib/new-ui/widgets/receive_page/receive_top_bar.dart
+25 -25
@@ -1,24 +1,24 @@
1 import 'package:cake_wallet/new-ui/widgets/modern_button.dart';
2 import 'package:flutter/material.dart';
3
4 -void nothing(){}
4 +void nothing() {}
5
6 class ModalTopBar extends StatelessWidget {
7 ModalTopBar(
8 {super.key,
9 - required this.title,
10 - this.subtitle,
11 - this.onLeadingPressed=nothing,
12 - this.onTrailingPressed=nothing,
13 - this.leadingIcon,
14 - this.trailingIcon,
15 - this.padding,
16 - this.leadingWidget,
17 - this.trailingWidget}) {
18 - if(leadingIcon != null && leadingWidget != null) {
9 + required this.title,
10 + this.subtitle,
11 + this.onLeadingPressed = nothing,
12 + this.onTrailingPressed = nothing,
13 + this.leadingIcon,
14 + this.trailingIcon,
15 + this.padding,
16 + this.leadingWidget,
17 + this.trailingWidget}) {
18 + if (leadingIcon != null && leadingWidget != null) {
19 throw Exception("Cannot have both leadingIcon and leadingWidget");
20 }
21 - if(trailingIcon != null && trailingWidget != null) {
21 + if (trailingIcon != null && trailingWidget != null) {
22 throw Exception("Cannot have both trailingIcon and trailingWidget");
23 }
24 }
@@ -38,7 +38,7 @@ class ModalTopBar extends StatelessWidget {
38 @override
39 Widget build(BuildContext context) {
40 return Padding(
41 - padding: padding??EdgeInsets.all(18),
41 + padding: padding ?? EdgeInsets.all(18),
42 child: Stack(
43 alignment: Alignment.topCenter,
44 children: [
@@ -58,8 +58,7 @@ class ModalTopBar extends StatelessWidget {
58 ),
59 ),
60 if (subtitle != null && subtitle!.isNotEmpty)
61 - Text(
62 - subtitle!,
61 + Text(subtitle!,
62 style: Theme.of(context)
63 .textTheme
64 .headlineMedium
@@ -74,11 +73,11 @@ class ModalTopBar extends StatelessWidget {
73 if (leadingIcon != null || leadingWidget != null)
74 leadingIcon != null
75 ? ModernButton(
77 - key: ValueKey(leadingIcon.hashCode),
78 - size: buttonSize,
79 - onPressed: onLeadingPressed,
80 - icon: leadingIcon!,
81 - iconColor: Theme.of(context).colorScheme.onSurfaceVariant)
76 + key: ValueKey(leadingIcon.hashCode),
77 + size: buttonSize,
78 + onPressed: onLeadingPressed,
79 + icon: leadingIcon!,
80 + iconColor: Theme.of(context).colorScheme.onSurfaceVariant)
81 : leadingWidget!
82 else
83 Container(width: buttonSize),
@@ -87,10 +86,11 @@ class ModalTopBar extends StatelessWidget {
86 duration: const Duration(milliseconds: 200),
87 child: trailingIcon != null
88 ? ModernButton(
90 - key: ValueKey(trailingIcon.hashCode),
91 - size: buttonSize,
92 - onPressed: onTrailingPressed,
93 - icon: trailingIcon!,)
89 + key: ValueKey(trailingIcon.hashCode),
90 + size: buttonSize,
91 + onPressed: onTrailingPressed,
92 + icon: trailingIcon!,
93 + )
94 : trailingWidget!,
95 )
96 else
@@ -101,4 +101,4 @@ class ModalTopBar extends StatelessWidget {
101 ),
102 );
103 }
104 -}
\ No newline at end of file
104 +}
lib/new-ui/widgets/send_page/fiat_amount_bar.dart
+10 -6
@@ -15,7 +15,9 @@ class FiatAmountBar extends StatelessWidget {
15 required this.fiatCurrencySymbol,
16 this.allAmount,
17 this.foregroundElementColor,
18 - this.textColor, this.allAmountColor, this.allAmountTextColor});
18 + this.textColor,
19 + this.allAmountColor,
20 + this.allAmountTextColor});
21
22 final bool fiatInputMode;
23 final VoidCallback onSwitchButtonPressed;
@@ -66,10 +68,11 @@ class FiatAmountBar extends StatelessWidget {
68 style: TextStyle(color: textColor ?? Theme.of(context).colorScheme.onSurface),
69 ),
70 Container(
69 - decoration: BoxDecoration(
70 - borderRadius: BorderRadius.circular(999999)),
71 + decoration: BoxDecoration(borderRadius: BorderRadius.circular(999999)),
72 child: Material(
72 - color: allAmountColor ?? foregroundElementColor ?? Theme.of(context).colorScheme.surfaceContainer,
73 + color: allAmountColor ??
74 + foregroundElementColor ??
75 + Theme.of(context).colorScheme.surfaceContainer,
76 borderRadius: BorderRadius.circular(99999),
77 child: InkWell(
78 borderRadius: BorderRadius.circular(99999),
@@ -78,7 +81,8 @@ class FiatAmountBar extends StatelessWidget {
81 padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4),
82 child: Text(
83 formatAmount(allAmount!),
81 - style: TextStyle(color: allAmountTextColor ?? Theme.of(context).colorScheme.primary),
84 + style: TextStyle(
85 + color: allAmountTextColor ?? Theme.of(context).colorScheme.primary),
86 ),
87 ),
88 )),
@@ -92,7 +96,7 @@ class FiatAmountBar extends StatelessWidget {
96 String formatAmount(String amount) {
97 try {
98 return double.parse(amount).toStringAsPrecision(8).replaceFirst(RegExp(r"\.?0+$"), "");
95 - } catch(e) {
99 + } catch (e) {
100 return amount;
101 }
102 }
lib/new-ui/widgets/send_page/floating_icon_button.dart
+7 -9
@@ -18,15 +18,13 @@ class FloatingIconButton extends StatelessWidget {
18 onTap: onPressed,
19 child: Padding(
20 padding: const EdgeInsets.all(4.0),
21 - child: CakeImageWidget(imageUrl:iconPath,
22 - width: 22, height: 22,
23 - colorFilter: ColorFilter.mode(Theme
24 - .of(context)
25 - .colorScheme
26 - .primary, BlendMode.srcIn),
21 + child: CakeImageWidget(
22 + imageUrl: iconPath,
23 + width: 22,
24 + height: 22,
25 + colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
26 ),
28 - )
29 - ),
27 + )),
28 );
29 }
32 -}
\ No newline at end of file
30 +}
lib/new-ui/widgets/send_page/l2_send_external_modal.dart
+21 -18
@@ -34,7 +34,7 @@ class _L2SendExternalModalState extends State<L2SendExternalModal> {
34 if (widget.sendViewModel.wallet.type == WalletType.bitcoin) {
35 await bitcoin!.setAddressType(widget.sendViewModel.wallet,
36 bitcoin!.getOptionToType(bitcoin!.getBitcoinLightningReceivePageOption()));
37 - } else if(widget.sendViewModel.wallet.type == WalletType.litecoin) {
37 + } else if (widget.sendViewModel.wallet.type == WalletType.litecoin) {
38 await bitcoin!.setAddressType(widget.sendViewModel.wallet,
39 bitcoin!.getOptionToType(bitcoin!.getLitecoinMwebReceivePageOption()));
40 }
@@ -64,8 +64,8 @@ class _L2SendExternalModalState extends State<L2SendExternalModal> {
64 leadingWidget: Row(
65 spacing: 12,
66 children: [
67 - if(widget.sendViewModel.walletType == WalletType.bitcoin)
68 - CakeImageWidget(imageUrl:"assets/new-ui/lightning_deposit_help.svg", height: 36),
67 + if (widget.sendViewModel.walletType == WalletType.bitcoin)
68 + CakeImageWidget(imageUrl: "assets/new-ui/lightning_deposit_help.svg", height: 36),
69 Text(
70 S.of(context).bitcoin_lightning_deposit,
71 style: TextStyle(fontWeight: FontWeight.w500, fontSize: 20),
@@ -140,23 +140,25 @@ class _L2SendExternalModalState extends State<L2SendExternalModal> {
140 largeQrMode = !largeQrMode;
141 });
142 },
143 - child: AnimatedContainer(
144 - duration: const Duration(milliseconds: 400),
145 - curve: Curves.easeOutCubic,
146 - width: resolvedSize,
147 - height: resolvedSize,
148 - child: ClipRRect(
149 - borderRadius: BorderRadius.circular(16),
150 - child: QrImage(
151 - embeddedImagePath: widget.sendViewModel.currency.iconPath,
152 - data: uri.toString(),
143 + child: AnimatedContainer(
144 + duration: const Duration(milliseconds: 400),
145 + curve: Curves.easeOutCubic,
146 + width: resolvedSize,
147 + height: resolvedSize,
148 + child: ClipRRect(
149 + borderRadius: BorderRadius.circular(16),
150 + child: QrImage(
151 + embeddedImagePath: widget.sendViewModel.currency.iconPath,
152 + data: uri.toString(),
153 + ),
154 + ),
155 + ),
156 ),
154 - ),
155 - ),
156 - ),
157 AddressFormatter.buildSegmentedAddress(
158 address: output.address,
159 - evenTextStyle: TextStyle(color: Theme.of(context).colorScheme.onSurface,fontFamily: "IBM Plex Mono"),
159 + evenTextStyle: TextStyle(
160 + color: Theme.of(context).colorScheme.onSurface,
161 + fontFamily: "IBM Plex Mono"),
162 textAlign: TextAlign.center),
163 Container(
164 decoration: BoxDecoration(
@@ -179,7 +181,8 @@ class _L2SendExternalModalState extends State<L2SendExternalModal> {
181 children: [
182 Flexible(
183 child: NewPrimaryButton(
182 - onPressed: () => ClipboardUtil.copyToClipboard(context, output.address),
184 + onPressed: () =>
185 + ClipboardUtil.copyToClipboard(context, output.address),
186 text: S.of(context).copy,
187 color: Theme.of(context).colorScheme.primary,
188 textColor: Theme.of(context).colorScheme.onPrimary),
lib/new-ui/widgets/send_page/recipient_dot_row.dart
+14 -12
@@ -42,7 +42,6 @@ class _RecipientDotRowState extends State<RecipientDotRow> {
42
43 @override
44 Widget build(BuildContext context) {
45 -
45 return LayoutBuilder(
46 builder: (context, constraints) {
47 final viewportWidth = constraints.maxWidth;
@@ -51,11 +50,11 @@ class _RecipientDotRowState extends State<RecipientDotRow> {
50 final totalContentWidth = (widget.numDots * itemExtent) - _outputDotSpacing;
51 final isScrollable = totalContentWidth > viewportWidth;
52
54 - final sidePadding = isScrollable ? viewportWidth * (_deadzoneSize/2) : 0.0;
53 + final sidePadding = isScrollable ? viewportWidth * (_deadzoneSize / 2) : 0.0;
54
55 if (isScrollable && !_wasScrollable) {
57 - _outputDotsController
58 - .jumpTo((widget.numDots * (_deadzoneSize/2)) * itemExtent - (_outputDotSpacing * (_deadzoneSize+1)));
56 + _outputDotsController.jumpTo((widget.numDots * (_deadzoneSize / 2)) * itemExtent -
57 + (_outputDotSpacing * (_deadzoneSize + 1)));
58 }
59
60 _wasScrollable = isScrollable;
@@ -141,7 +140,8 @@ class RecipientDot extends StatefulWidget {
140 required this.spacing,
141 required this.index,
142 required this.onTap,
144 - required this.selected, required this.textOpacity});
143 + required this.selected,
144 + required this.textOpacity});
145
146 final double size;
147 final double spacing;
@@ -197,13 +197,15 @@ class _RecipientDotState extends State<RecipientDot> {
197 alignment: Alignment.center,
198 child: Opacity(
199 opacity: widget.textOpacity,
200 - child: Text((widget.index+1).toString(),
201 - style: TextStyle(
202 - color: widget.selected
203 - ? Theme.of(context).colorScheme.onPrimary
204 - : Theme.of(context).colorScheme.onSurface,
205 - fontSize:14,fontWeight: FontWeight.w500
206 - ),),
200 + child: Text(
201 + (widget.index + 1).toString(),
202 + style: TextStyle(
203 + color: widget.selected
204 + ? Theme.of(context).colorScheme.onPrimary
205 + : Theme.of(context).colorScheme.onSurface,
206 + fontSize: 14,
207 + fontWeight: FontWeight.w500),
208 + ),
209 ),
210 ),
211 ),
lib/new-ui/widgets/send_page/send_address_input.dart
+1 -1
@@ -38,7 +38,7 @@ class NewSendAddressInput extends StatefulWidget {
38 final FormFieldValidator<String>? validator;
39 final FocusNode? focusNode;
40 final String? hintText;
41 -
41 +
42 @override
43 State<NewSendAddressInput> createState() => _NewSendAddressInputState();
44 }
lib/new-ui/widgets/send_page/send_amount_input.dart
+16 -14
@@ -7,16 +7,16 @@ import 'package:flutter/services.dart';
7 import 'package:flutter_mobx/flutter_mobx.dart';
8
9 class NewSendAmountInput extends StatefulWidget {
10 - const NewSendAmountInput(
11 - {super.key,
12 - required this.currency,
13 - required this.maxDecimals,
14 - required this.hasPicker,
15 - required this.onPickerClicked,
16 - required this.currencyIconPath,
17 - required this.amountController,
18 - this.validator,
19 - });
10 + const NewSendAmountInput({
11 + super.key,
12 + required this.currency,
13 + required this.maxDecimals,
14 + required this.hasPicker,
15 + required this.onPickerClicked,
16 + required this.currencyIconPath,
17 + required this.amountController,
18 + this.validator,
19 + });
20
21 final String currency;
22 final String currencyIconPath;
@@ -35,7 +35,8 @@ class _NewSendAmountInputState extends State<NewSendAmountInput> {
35
36 @override
37 void initState() {
38 - widget.amountController.addListener(()=>formFieldKey.currentState?.didChange(widget.amountController.text));
38 + widget.amountController
39 + .addListener(() => formFieldKey.currentState?.didChange(widget.amountController.text));
40 super.initState();
41 }
42
@@ -124,11 +125,12 @@ class _NewSendAmountInputState extends State<NewSendAmountInput> {
125 spacing: 8,
126 children: [
127 if (widget.hasPicker && widget.currencyIconPath.isNotEmpty)
127 - TokenImageWidget(imageUrl: widget.currencyIconPath, size: 24),
128 + TokenImageWidget(
129 + imageUrl: widget.currencyIconPath, size: 24),
130 Text(widget.currency),
131 if (widget.hasPicker)
130 - CakeImageWidget(imageUrl:
131 - "assets/new-ui/chooser.svg",
132 + CakeImageWidget(
133 + imageUrl: "assets/new-ui/chooser.svg",
134 width: 12,
135 height: 12,
136 colorFilter: ColorFilter.mode(
lib/new-ui/widgets/send_page/send_confirm_bottom_widget.dart
+2 -2
@@ -120,8 +120,8 @@ class TransactionErrorActions extends StatelessWidget {
120 mainAxisAlignment: MainAxisAlignment.center,
121 spacing: 8,
122 children: [
123 - CakeImageWidget(imageUrl:
124 - "assets/new-ui/warning.svg",
123 + CakeImageWidget(
124 + imageUrl: "assets/new-ui/warning.svg",
125 height: 24,
126 width: 24,
127 colorFilter:
lib/new-ui/widgets/send_page/send_confirm_sheet.dart
+69 -62
@@ -27,7 +27,8 @@ import 'package:flutter_mobx/flutter_mobx.dart';
27 import 'package:mobx/mobx.dart';
28
29 class SendConfirmSheet extends StatefulWidget {
30 - const SendConfirmSheet({super.key, required this.sendViewModel, this.isPage = false, this.title, this.iconPath});
30 + const SendConfirmSheet(
31 + {super.key, required this.sendViewModel, this.isPage = false, this.title, this.iconPath});
32
33 final SendViewModel sendViewModel;
34 final bool isPage;
@@ -43,8 +44,8 @@ class _SendConfirmSheetState extends State<SendConfirmSheet> {
44
45 void initState() {
46 super.initState();
46 - reaction((_)=>widget.sendViewModel.state, (state){
47 - if(state is TransactionCommitted) {
47 + reaction((_) => widget.sendViewModel.state, (state) {
48 + if (state is TransactionCommitted) {
49 setState(() {
50 _committed = true;
51 });
@@ -62,57 +63,55 @@ class _SendConfirmSheetState extends State<SendConfirmSheet> {
63 }
64 },
65 child: SafeArea(
65 - bottom:false,
66 + bottom: false,
67 minimum: widget.isPage ? EdgeInsets.zero : EdgeInsets.only(top: 64),
68 child: Container(
69 decoration: BoxDecoration(
70 color: Theme.of(context).colorScheme.surface,
71 borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
72 ),
72 - child: SafeArea(
73 - child: Observer(
74 - builder: (_) {
75 - return AnimatedSize(
76 - duration: const Duration(milliseconds: 300),
77 - curve: Curves.easeOutCubic,
78 - alignment: Alignment.topCenter,
79 - clipBehavior: Clip.hardEdge,
80 - child: Stack(
81 - clipBehavior: Clip.none,
82 - children: [
83 - Align(
84 - alignment: Alignment.topCenter,
85 - heightFactor: _committed ? 0.0 : 1.0,
86 - child: AnimatedSlide(
87 - offset: _committed ? const Offset(-1, 0) : Offset.zero,
88 - duration: const Duration(milliseconds: 300),
89 - curve: Curves.easeOutCubic,
90 - child: SendTransactionDetails(
91 - sendViewModel: widget.sendViewModel,
92 - isPage: widget.isPage,
93 - title: widget.title,
94 - iconPath: widget.iconPath,
95 - ),
73 + child: SafeArea(child: Observer(
74 + builder: (_) {
75 + return AnimatedSize(
76 + duration: const Duration(milliseconds: 300),
77 + curve: Curves.easeOutCubic,
78 + alignment: Alignment.topCenter,
79 + clipBehavior: Clip.hardEdge,
80 + child: Stack(
81 + clipBehavior: Clip.none,
82 + children: [
83 + Align(
84 + alignment: Alignment.topCenter,
85 + heightFactor: _committed ? 0.0 : 1.0,
86 + child: AnimatedSlide(
87 + offset: _committed ? const Offset(-1, 0) : Offset.zero,
88 + duration: const Duration(milliseconds: 300),
89 + curve: Curves.easeOutCubic,
90 + child: SendTransactionDetails(
91 + sendViewModel: widget.sendViewModel,
92 + isPage: widget.isPage,
93 + title: widget.title,
94 + iconPath: widget.iconPath,
95 ),
96 ),
98 - Align(
99 - alignment: Alignment.topCenter,
100 - heightFactor: _committed ? 1.0 : 0.0,
101 - child: AnimatedSlide(
102 - offset: _committed ? Offset.zero : const Offset(1, 0),
103 - duration: const Duration(milliseconds: 300),
104 - curve: Curves.easeOutCubic,
105 - child: TransactionCommitedScreen(
106 - sendViewModel: widget.sendViewModel,
107 - ),
97 + ),
98 + Align(
99 + alignment: Alignment.topCenter,
100 + heightFactor: _committed ? 1.0 : 0.0,
101 + child: AnimatedSlide(
102 + offset: _committed ? Offset.zero : const Offset(1, 0),
103 + duration: const Duration(milliseconds: 300),
104 + curve: Curves.easeOutCubic,
105 + child: TransactionCommitedScreen(
106 + sendViewModel: widget.sendViewModel,
107 ),
108 ),
110 - ],
111 - ),
112 - );
113 - },
114 - )
115 - ),
109 + ),
110 + ],
111 + ),
112 + );
113 + },
114 + )),
115 ),
116 ),
117 );
@@ -120,14 +119,14 @@ class _SendConfirmSheetState extends State<SendConfirmSheet> {
119 }
120
121 class SendTransactionDetails extends StatelessWidget {
123 - const SendTransactionDetails({super.key, required this.sendViewModel, required this.isPage, this.title, this.iconPath});
122 + const SendTransactionDetails(
123 + {super.key, required this.sendViewModel, required this.isPage, this.title, this.iconPath});
124
125 final SendViewModel sendViewModel;
126 final bool isPage;
127 final String? title;
128 final String? iconPath;
129
130 -
130 @override
131 Widget build(BuildContext context) {
132 final resolvedIconPath = iconPath ?? sendViewModel.currency.iconPath ?? "";
@@ -144,8 +143,8 @@ class SendTransactionDetails extends StatelessWidget {
143 spacing: 8,
144 children: [
145 if (resolvedIconPath.toLowerCase().endsWith(".svg"))
147 - CakeImageWidget(imageUrl:
148 - resolvedIconPath,
146 + CakeImageWidget(
147 + imageUrl: resolvedIconPath,
148 width: 28,
149 height: 28,
150 )
@@ -164,7 +163,9 @@ class SendTransactionDetails extends StatelessWidget {
163 trailingIcon: Icon(Icons.close),
164 onTrailingPressed: Navigator.of(context).maybePop,
165 ),
167 - isPage ? Expanded(child: _buildMainContent(context)) : Flexible(child: _buildMainContent(context))
166 + isPage
167 + ? Expanded(child: _buildMainContent(context))
168 + : Flexible(child: _buildMainContent(context))
169 ]);
170 },
171 );
@@ -176,8 +177,7 @@ class SendTransactionDetails extends StatelessWidget {
177 Money sumByMoney<T>(List<T> list, Money Function(T) picker, CryptoCurrency currency) =>
178 list.map(picker).fold(Money.zero(currency), (a, b) => a + b);
179
179 - String sumStr<T>(List<T> list, double Function(T) picker) =>
180 - sumBy(list, picker).toString();
180 + String sumStr<T>(List<T> list, double Function(T) picker) => sumBy(list, picker).toString();
181
182 String sumWithUnit<T>(List<T> list, double Function(T) picker, String unit, {int? decimals}) {
183 final str = sumStr(list, picker);
@@ -227,14 +227,17 @@ class SendTransactionDetails extends StatelessWidget {
227 decimals: 2)
228 : sendViewModel.pendingTransactionFeeFiatAmountFormatted;
229
230 - final showAddress = !sendViewModel.outputs.any((e) =>
231 - RegExp(AddressValidator.bolt11InvoiceMatcher).hasMatch(e.address.toLowerCase()) ||
232 - RegExp(AddressValidator.lnurlMatcher).hasMatch(e.address.toLowerCase()) ||
233 - (e.isParsedAddress &&
234 - e.parsedAddress.parsedAddressByCurrencyMap[sendViewModel.selectedCryptoCurrency] != null &&
235 - e.parsedAddress.parsedAddressByCurrencyMap[sendViewModel.selectedCryptoCurrency]!.isNotEmpty &&
236 - RegExp(AddressValidator.lnurlMatcher)
237 - .hasMatch(e.parsedAddress.parsedAddressByCurrencyMap[sendViewModel.selectedCryptoCurrency]!.toLowerCase())));
230 + final showAddress = !sendViewModel.outputs.any((e) =>
231 + RegExp(AddressValidator.bolt11InvoiceMatcher).hasMatch(e.address.toLowerCase()) ||
232 + RegExp(AddressValidator.lnurlMatcher).hasMatch(e.address.toLowerCase()) ||
233 + (e.isParsedAddress &&
234 + e.parsedAddress.parsedAddressByCurrencyMap[sendViewModel.selectedCryptoCurrency] !=
235 + null &&
236 + e.parsedAddress.parsedAddressByCurrencyMap[sendViewModel.selectedCryptoCurrency]!
237 + .isNotEmpty &&
238 + RegExp(AddressValidator.lnurlMatcher).hasMatch(e
239 + .parsedAddress.parsedAddressByCurrencyMap[sendViewModel.selectedCryptoCurrency]!
240 + .toLowerCase())));
241
242 final outputs = sendViewModel.outputs;
243
@@ -426,7 +429,7 @@ class SendTransactionDetails extends StatelessWidget {
429 String formatAmount(String amount) {
430 try {
431 return amount.withMaxDecimals(8);
429 - } catch(e) {
432 + } catch (e) {
433 return amount;
434 }
435 }
@@ -452,7 +455,9 @@ class _TransactionCommitedScreenState extends State<TransactionCommitedScreen> {
455 mainAxisSize: MainAxisSize.min,
456 mainAxisAlignment: MainAxisAlignment.spaceAround,
457 children: [
455 - SizedBox(height: 12,),
458 + SizedBox(
459 + height: 12,
460 + ),
461 Text(
462 S.of(context).transaction_sent_new,
463 style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
@@ -517,7 +522,9 @@ class _TransactionCommitedScreenState extends State<TransactionCommitedScreen> {
522 text: S.of(context).done,
523 color: Theme.of(context).colorScheme.primary,
524 textColor: Theme.of(context).colorScheme.onPrimary),
520 - SizedBox(height: 12,)
525 + SizedBox(
526 + height: 12,
527 + )
528 ],
529 ),
530 ),
lib/new-ui/widgets/send_page/send_memo_input.dart
+1 -2
@@ -59,8 +59,7 @@ class NewSendMemoInput extends StatelessWidget {
59 Expanded(
60 child: Text(disclaimerText ?? S.of(context).memo_disclaimer,
61 style: TextStyle(
62 - fontSize: 12,
63 - color: Theme.of(context).colorScheme.onSurfaceVariant)),
62 + fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant)),
63 ),
64 Text("${memoController.text.length} / ${maxMemoLength}",
65 style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.primary))
lib/new-ui/widgets/send_page/send_syncing_indicator.dart
+15 -20
@@ -9,40 +9,35 @@ class SendSyncingIndicator extends StatelessWidget {
9 static const outlineColor = Color(0xFFFFB84E);
10 static const backgroundColor = Color(0xFF8E5800);
11
12 -
12 @override
13 Widget build(BuildContext context) {
14 late final String eta;
16 - if(status is SyncingSyncStatus) {
17 - eta = (status as SyncingSyncStatus).getFormattedEta()??"";
15 + if (status is SyncingSyncStatus) {
16 + eta = (status as SyncingSyncStatus).getFormattedEta() ?? "";
17 } else {
18 eta = "";
19 }
20
21 return Container(
23 - height:48,
24 - decoration: BoxDecoration(
25 - color: backgroundColor,
26 - borderRadius: BorderRadius.circular(99999)
27 - ),
28 - child:
29 - Padding(
22 + height: 48,
23 + decoration: BoxDecoration(color: backgroundColor, borderRadius: BorderRadius.circular(99999)),
24 + child: Padding(
25 padding: const EdgeInsets.symmetric(horizontal: 12.0),
26 child: Row(
27 mainAxisSize: MainAxisSize.min,
28 spacing: 10,
29 children: [
35 - if(status.progress() > 0)
36 - SizedBox(
37 - width: 24,
38 - height: 24,
39 - child: CircularProgressIndicator(
40 - value: status.progress(),
41 - strokeWidth: 3,
42 - strokeCap: StrokeCap.round,
43 - color: outlineColor,
30 + if (status.progress() > 0)
31 + SizedBox(
32 + width: 24,
33 + height: 24,
34 + child: CircularProgressIndicator(
35 + value: status.progress(),
36 + strokeWidth: 3,
37 + strokeCap: StrokeCap.round,
38 + color: outlineColor,
39 + ),
40 ),
45 - ),
41 Text("Synchronizing... ${eta}", style: TextStyle(color: outlineColor)),
42 ],
43 ),
lib/new-ui/widgets/swap_page/provider_options_page.dart
+9 -5
@@ -162,10 +162,14 @@ class ProviderOptionsPage extends StatelessWidget {
162 label: item.title,
163 showArrow: item.title == "Trocador",
164 value: exchangeViewModel.selectedProviders.contains(item),
165 - subtitle: item.title == "Trocador" ? S.of(context).manage_providers : null,
166 - onTap: item.title == "Trocador" ? (){
167 - _openTrocadorProvidersPage(context);
168 - } : null,
165 + subtitle: item.title == "Trocador"
166 + ? S.of(context).manage_providers
167 + : null,
168 + onTap: item.title == "Trocador"
169 + ? () {
170 + _openTrocadorProvidersPage(context);
171 + }
172 + : null,
173 onChanged: (val) {
174 _switchProviderStatus(item, val, context);
175 });
@@ -180,7 +184,7 @@ class ProviderOptionsPage extends StatelessWidget {
184 ))
185 ],
186 ),
183 - SizedBox(height:36)
187 + SizedBox(height: 36)
188 ],
189 ),
190 ),
lib/new-ui/widgets/swap_page/refund_address_modal.dart
+5 -3
@@ -53,7 +53,7 @@ class _RefundAddressModalState extends State<RefundAddressModal> {
53 spacing: 24,
54 children: [
55 CakeImageWidget(
56 - imageUrl:"assets/new-ui/refund_address.svg",
56 + imageUrl: "assets/new-ui/refund_address.svg",
57 colorFilter:
58 ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
59 ),
@@ -72,7 +72,7 @@ class _RefundAddressModalState extends State<RefundAddressModal> {
72 spacing: 12,
73 children: [
74 NewSendAddressInput(
75 - bottomPadding: true,
75 + bottomPadding: true,
76 addressController: addressController,
77 selectedCurrency: widget.selectedCurrency,
78 onEditingComplete: () {}),
@@ -81,7 +81,9 @@ class _RefundAddressModalState extends State<RefundAddressModal> {
81 onPressed: () {
82 Navigator.of(context).pop(addressController.text);
83 },
84 - text: !_textEntered ? S.of(context).skip_set_later : S.of(context).continue_text,
84 + text: !_textEntered
85 + ? S.of(context).skip_set_later
86 + : S.of(context).continue_text,
87 color: addressController.text.isEmpty
88 ? Theme.of(context).colorScheme.surfaceContainer
89 : Theme.of(context).colorScheme.primary,
lib/new-ui/widgets/swap_page/swap_address_selection_modal.dart
+45 -36
@@ -64,7 +64,9 @@ class _SwapAddressSelectionModalState extends State<SwapAddressSelectionModal> {
64
65 @override
66 Widget build(BuildContext context) {
67 - final currency = widget.isSelectingReceiver ? widget.exchangeViewModel.receiveCurrency : widget.exchangeViewModel.depositCurrency;
67 + final currency = widget.isSelectingReceiver
68 + ? widget.exchangeViewModel.receiveCurrency
69 + : widget.exchangeViewModel.depositCurrency;
70
71 if (!_itemsLoaded) return SizedBox.shrink();
72 return Container(
@@ -76,7 +78,9 @@ class _SwapAddressSelectionModalState extends State<SwapAddressSelectionModal> {
78 mainAxisSize: MainAxisSize.min,
79 children: [
80 ModalTopBar(
79 - title: widget.isSelectingReceiver ? "${S.of(context).receive_to}..." : "${S.of(context).send_from}...",
81 + title: widget.isSelectingReceiver
82 + ? "${S.of(context).receive_to}..."
83 + : "${S.of(context).send_from}...",
84 leadingIcon: Icon(Icons.close),
85 onLeadingPressed: Navigator.of(context).pop,
86 ),
@@ -90,46 +94,47 @@ class _SwapAddressSelectionModalState extends State<SwapAddressSelectionModal> {
94 style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant),
95 ))
96 : ListView.builder(
93 - padding: EdgeInsets.only(bottom: 12),
94 - shrinkWrap: true,
97 + padding: EdgeInsets.only(bottom: 12),
98 + shrinkWrap: true,
99 controller: ModalScrollController.of(context),
100 itemCount: items.length,
97 - itemBuilder: (context, index) {
98 - final item = items[index];
101 + itemBuilder: (context, index) {
102 + final item = items[index];
103
100 - late final bool selected;
101 - if (widget.isSelectingReceiver) {
102 - selected = widget.exchangeViewModel.receiveAddress == item.address;
103 - } else {
104 - selected = widget.exchangeViewModel.wallet.name == item.name &&
105 - !widget.exchangeViewModel.isSendFromExternal;
106 - }
104 + late final bool selected;
105 + if (widget.isSelectingReceiver) {
106 + selected = widget.exchangeViewModel.receiveAddress == item.address;
107 + } else {
108 + selected = widget.exchangeViewModel.wallet.name == item.name &&
109 + !widget.exchangeViewModel.isSendFromExternal;
110 + }
111
108 - final String currencyIconPath = getCryptoCurrencyIconForWalletListItem(item.type);
112 + final String currencyIconPath =
113 + getCryptoCurrencyIconForWalletListItem(item.type);
114
115 final bool hasAccounts =
116 item.type == WalletType.monero && widget.isSelectingReceiver;
117
118 List<WalletInfoAddressInfo>? accounts =
114 - hasAccounts ? this.accounts[item.id] : null;
119 + hasAccounts ? this.accounts[item.id] : null;
120
116 - return Padding(
117 - padding: const EdgeInsets.symmetric(vertical: 6.0),
118 - child: SwapAddressSelectionModalRow(
119 - wallet: item,
120 - iconPath: currencyIconPath,
121 - isSelected: selected,
122 - accounts: accounts,
123 - onAddressChosen: (address, accountName) {
121 + return Padding(
122 + padding: const EdgeInsets.symmetric(vertical: 6.0),
123 + child: SwapAddressSelectionModalRow(
124 + wallet: item,
125 + iconPath: currencyIconPath,
126 + isSelected: selected,
127 + accounts: accounts,
128 + onAddressChosen: (address, accountName) {
129 Navigator.of(context).pop(SwapAddressSelectionResult(
130 address: address,
131 walletInfo: item,
132 accountName: accountName));
133 },
134 + ),
135 + );
136 + },
137 ),
130 - );
131 - },
132 - ),
138 ),
139 ),
140 Container(
@@ -137,7 +142,7 @@ class _SwapAddressSelectionModalState extends State<SwapAddressSelectionModal> {
142 color: Theme.of(context).colorScheme.surfaceContainerHigh,
143 ),
144 Padding(
140 - padding: const EdgeInsets.symmetric(horizontal: 24.0,vertical: 18),
145 + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 18),
146 child: !widget.isSelectingReceiver
147 ? GestureDetector(
148 behavior: HitTestBehavior.opaque,
@@ -153,7 +158,8 @@ class _SwapAddressSelectionModalState extends State<SwapAddressSelectionModal> {
158 mainAxisAlignment: MainAxisAlignment.center,
159 spacing: 10,
160 children: [
156 - CakeImageWidget(imageUrl:"assets/new-ui/send_from_external.svg",
161 + CakeImageWidget(
162 + imageUrl: "assets/new-ui/send_from_external.svg",
163 colorFilter: ColorFilter.mode(
164 Theme.of(context).colorScheme.primary, BlendMode.srcIn)),
165 Text(S.of(context).send_from_external,
@@ -169,9 +175,11 @@ class _SwapAddressSelectionModalState extends State<SwapAddressSelectionModal> {
175 children: [
176 Flexible(
177 child: NewSendAddressInput(
172 - addressController: addressController,
173 - selectedCurrency: widget.exchangeViewModel.receiveCurrency,
174 - onEditingComplete: () {}, bottomPadding: true,),
178 + addressController: addressController,
179 + selectedCurrency: widget.exchangeViewModel.receiveCurrency,
180 + onEditingComplete: () {},
181 + bottomPadding: true,
182 + ),
183 ),
184 AnimatedScale(
185 alignment: Alignment.centerLeft,
@@ -183,7 +191,8 @@ class _SwapAddressSelectionModalState extends State<SwapAddressSelectionModal> {
191 SizedBox(width: textEntered ? 8 : 0),
192 GestureDetector(
193 onTap: () {
186 - Navigator.of(context).pop(SwapAddressSelectionResult(address:addressController.text));
194 + Navigator.of(context).pop(SwapAddressSelectionResult(
195 + address: addressController.text));
196 },
197 child: AnimatedContainer(
198 duration: const Duration(milliseconds: 200),
@@ -272,8 +281,8 @@ class _SwapAddressSelectionModalRowState extends State<SwapAddressSelectionModal
281 duration: Duration(milliseconds: 200),
282 curve: Curves.easeOutCubic,
283 turns: _isExpanded ? 0 : 0.5,
275 - child:CakeImageWidget(imageUrl:
276 - "assets/new-ui/dropdown_arrow.svg",
284 + child: CakeImageWidget(
285 + imageUrl: "assets/new-ui/dropdown_arrow.svg",
286 colorFilter: ColorFilter.mode(
287 Theme.of(context).colorScheme.onSurfaceVariant, BlendMode.srcIn),
288 ))
@@ -316,8 +325,8 @@ class _SwapAddressSelectionModalRowState extends State<SwapAddressSelectionModal
325 child: Row(
326 spacing: 12,
327 children: [
319 - CakeImageWidget(imageUrl:
320 - "assets/new-ui/account.svg",
328 + CakeImageWidget(
329 + imageUrl: "assets/new-ui/account.svg",
330 colorFilter: ColorFilter.mode(
331 Theme.of(context).colorScheme.onSurfaceVariant,
332 BlendMode.srcIn),
lib/new-ui/widgets/swap_page/swap_options_page.dart
+13 -4
@@ -75,7 +75,7 @@ class SwapOptionsPage extends StatelessWidget {
75 label: S.of(context).set_refund_address,
76 onTap: () {
77 showModalBottomSheet(
78 - isScrollControlled: true,
78 + isScrollControlled: true,
79 context: context,
80 builder: (context) {
81 return RefundAddressModal(
@@ -101,9 +101,18 @@ class SwapOptionsPage extends StatelessWidget {
101 keyValue: "coin control",
102 label: "Coin Control",
103 onTap: () {
104 - showCupertinoModalBottomSheet(enableDrag: false, useRootNavigator: true, isDismissible: false, context: context, builder: (context){
105 - return NewCoinControlPage(unspentCoinsListViewModel: exchangeViewModel.unspentCoinsListViewModel,canEdit: true,);
106 - });
104 + showCupertinoModalBottomSheet(
105 + enableDrag: false,
106 + useRootNavigator: true,
107 + isDismissible: false,
108 + context: context,
109 + builder: (context) {
110 + return NewCoinControlPage(
111 + unspentCoinsListViewModel:
112 + exchangeViewModel.unspentCoinsListViewModel,
113 + canEdit: true,
114 + );
115 + });
116 }),
117 ListItemSelector(
118 keyValue: "curr",
lib/new-ui/widgets/swap_page/swap_provider_initial_preference_modal.dart
+1 -1
@@ -24,7 +24,7 @@ class SwapProviderInitialPreferenceModal extends StatelessWidget {
24 child: Column(
25 spacing: 12,
26 children: [
27 - CakeImageWidget(imageUrl:"assets/new-ui/exchange_providers.svg"),
27 + CakeImageWidget(imageUrl: "assets/new-ui/exchange_providers.svg"),
28 Text(
29 "${S.of(context).swap_provider_initial_desc} Cake Wallet.",
30 textAlign: TextAlign.center,
lib/new-ui/widgets/swap_page/swap_send_external_modal.dart
+6 -4
@@ -16,7 +16,8 @@ class SwapSendExternalModal extends StatefulWidget {
16 required this.amount,
17 required this.from,
18 required this.to,
19 - required this.address, required this.exchangeTradeViewModel});
19 + required this.address,
20 + required this.exchangeTradeViewModel});
21
22 final String amount;
23 final ExchangeTradeViewModel exchangeTradeViewModel;
@@ -164,18 +165,19 @@ class _SwapSendExternalModalState extends State<SwapSendExternalModal> {
165 color: warningTextColor, fontSize: 14, fontWeight: FontWeight.w500),
166 ),
167 )),
167 - if(widget.exchangeTradeViewModel.trade.extraId != null)
168 + if (widget.exchangeTradeViewModel.trade.extraId != null)
169 Text(
170 "${S.of(context).destination_tag} ${widget.exchangeTradeViewModel.trade.extraId}",
171 style: TextStyle(
172 fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),
173 ),
174 Row(
174 - spacing:8,
175 + spacing: 8,
176 children: [
177 Flexible(
178 child: NewPrimaryButton(
178 - onPressed: () => ClipboardUtil.copyToClipboard(context, widget.address),
179 + onPressed: () =>
180 + ClipboardUtil.copyToClipboard(context, widget.address),
181 text: S.of(context).copy,
182 color: Theme.of(context).colorScheme.primary,
183 textColor: Theme.of(context).colorScheme.onPrimary),
lib/new-ui/widgets/swap_page/trocador_providers_settings.dart
+1 -2
@@ -39,8 +39,7 @@ class TrocadorProvidersSettings extends StatelessWidget {
39 ModalHeader(
40 title: "${S.of(context).about} Trocador",
41 iconPath: "assets/new-ui/trade_providers/trocador.svg",
42 - message:
43 - "Trocador ${S.of(context).trocador_desc}"),
42 + message: "Trocador ${S.of(context).trocador_desc}"),
43 SizedBox(),
44 Text(S.of(context).providers),
45 Text(
lib/order/order.part.dart
+1 -3
@@ -71,7 +71,5 @@ class OrderAdapter extends TypeAdapter<Order> {
71 @override
72 bool operator ==(Object other) =>
73 identical(this, other) ||
74 - other is OrderAdapter &&
75 - runtimeType == other.runtimeType &&
76 - typeId == other.typeId;
74 + other is OrderAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
75 }
lib/order/order_provider_description.dart
+2 -2
@@ -9,8 +9,8 @@ class OrderProviderDescription extends EnumerableItem<int> with Serializable<int
9
10 final String image;
11
12 - static const cakePay = OrderProviderDescription(
13 - title: 'Cake Pay', raw: 0, image: 'assets/images/cake_pay_icon.png');
12 + static const cakePay =
13 + OrderProviderDescription(title: 'Cake Pay', raw: 0, image: 'assets/images/cake_pay_icon.png');
14
15 static OrderProviderDescription deserialize({required int raw}) {
16 switch (raw) {
lib/order/order_source_description.dart
+1 -1
@@ -17,4 +17,4 @@ class OrderSourceDescription extends EnumerableItem<int> with Serializable<int>
17 throw Exception('Invalid OrderSourceDescription raw value: $raw');
18 }
19 }
20 -}
\ No newline at end of file
20 +}
lib/reactions/bootstrap.dart
+1 -1
@@ -46,4 +46,4 @@ void bootstrapOnline(GlobalKey<NavigatorState> navigatorKey, {required bool load
46 if (FeatureFlag.isAutomaticNodeSwitchingEnabled) {
47 getIt.get<NodeSwitchingService>().startHealthCheckTimer();
48 }
49 -}
\ No newline at end of file
49 +}
lib/reactions/fiat_rate_update.dart
+1 -2
@@ -35,8 +35,7 @@ Future<void> startFiatRateUpdate(
35
36 Iterable<CryptoCurrency>? currencies;
37 if (isEVMCompatibleChain(appStore.wallet!.type)) {
38 - currencies =
39 - evm!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled);
38 + currencies = evm!.getERC20Currencies(appStore.wallet!).where((element) => element.enabled);
39 }
40
41 if (appStore.wallet!.type == WalletType.solana) {
lib/reactions/on_authentication_state_change.dart
+1 -2
@@ -25,8 +25,7 @@ import 'package:rxdart/subjects.dart';
25 ReactionDisposer? _onAuthenticationStateChange;
26
27 dynamic loginError;
28 -StreamController<dynamic> authenticatedErrorStreamController =
29 - BehaviorSubject<dynamic>();
28 +StreamController<dynamic> authenticatedErrorStreamController = BehaviorSubject<dynamic>();
29
30 void startAuthenticationStateChange(
31 AuthenticationStore authenticationStore,
lib/reactions/on_current_fiat_api_mode_change.dart
+8 -9
@@ -7,19 +7,18 @@ import 'package:cake_wallet/store/app_store.dart';
7
8 ReactionDisposer? _onCurrentFiatCurrencyChangeDisposer;
9
10 -void startCurrentFiatApiModeChangeReaction(AppStore appStore,
11 - SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
10 +void startCurrentFiatApiModeChangeReaction(
11 + AppStore appStore, SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
12 _onCurrentFiatCurrencyChangeDisposer?.reaction.dispose();
13 - _onCurrentFiatCurrencyChangeDisposer = reaction(
14 - (_) => settingsStore.fiatApiMode, (FiatApiMode fiatApiMode) async {
13 + _onCurrentFiatCurrencyChangeDisposer =
14 + reaction((_) => settingsStore.fiatApiMode, (FiatApiMode fiatApiMode) async {
15 if (appStore.wallet == null || fiatApiMode == FiatApiMode.disabled) {
16 return;
17 }
18
19 - fiatConversionStore.prices[appStore.wallet!.currency] =
20 - await FiatConversionService.fetchPrice(
21 - crypto: appStore.wallet!.currency,
22 - fiat: settingsStore.fiatCurrency,
23 - torOnly: fiatApiMode == FiatApiMode.torOnly);
19 + fiatConversionStore.prices[appStore.wallet!.currency] = await FiatConversionService.fetchPrice(
20 + crypto: appStore.wallet!.currency,
21 + fiat: settingsStore.fiatCurrency,
22 + torOnly: fiatApiMode == FiatApiMode.torOnly);
23 });
24 }
lib/reactions/on_current_fiat_change.dart
+8 -9
@@ -8,20 +8,19 @@ import 'package:cake_wallet/entities/fiat_currency.dart';
8
9 ReactionDisposer? _onCurrentFiatCurrencyChangeDisposer;
10
11 -void startCurrentFiatChangeReaction(AppStore appStore,
12 - SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
11 +void startCurrentFiatChangeReaction(
12 + AppStore appStore, SettingsStore settingsStore, FiatConversionStore fiatConversionStore) {
13 _onCurrentFiatCurrencyChangeDisposer?.reaction.dispose();
14 - _onCurrentFiatCurrencyChangeDisposer = reaction(
15 - (_) => settingsStore.fiatCurrency, (FiatCurrency fiatCurrency) async {
14 + _onCurrentFiatCurrencyChangeDisposer =
15 + reaction((_) => settingsStore.fiatCurrency, (FiatCurrency fiatCurrency) async {
16 if (appStore.wallet == null || settingsStore.fiatApiMode == FiatApiMode.disabled) {
17 return;
18 }
19
20 final cryptoCurrency = appStore.wallet!.currency;
21 - fiatConversionStore.prices[cryptoCurrency] =
22 - await FiatConversionService.fetchPrice(
23 - crypto: cryptoCurrency,
24 - fiat: fiatCurrency,
25 - torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly);
21 + fiatConversionStore.prices[cryptoCurrency] = await FiatConversionService.fetchPrice(
22 + crypto: cryptoCurrency,
23 + fiat: fiatCurrency,
24 + torOnly: settingsStore.fiatApiMode == FiatApiMode.torOnly);
25 });
26 }
lib/reactions/on_current_wallet_change.dart
+1 -2
@@ -113,8 +113,7 @@ void startCurrentWalletChangeReaction(
113 }
114
115 if (wallet.type == WalletType.solana) {
116 - await solana!
117 - .discoverAndAddWalletTokens(wallet);
116 + await solana!.discoverAndAddWalletTokens(wallet);
117 }
118 } catch (e) {
119 printV(e.toString());
lib/router.dart
+18 -16
@@ -172,13 +172,15 @@ late RouteSettings currentRouteSettings;
172
173 Route<T> handleRouteWithPlatformAwareness<T>(
174 Widget Function(BuildContext) builder, {
175 - RouteSettings? settings,
175 + RouteSettings? settings,
176 bool fullscreenDialog = false,
177 }) {
178 if (Platform.isIOS) {
179 - return CupertinoPageRoute<T>(builder: builder, fullscreenDialog: fullscreenDialog, settings: settings);
179 + return CupertinoPageRoute<T>(
180 + builder: builder, fullscreenDialog: fullscreenDialog, settings: settings);
181 } else {
181 - return MaterialPageRoute<T>(builder: builder, fullscreenDialog: fullscreenDialog, settings: settings);
182 + return MaterialPageRoute<T>(
183 + builder: builder, fullscreenDialog: fullscreenDialog, settings: settings);
184 }
185 }
186
@@ -446,7 +448,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
448 return handleRouteWithPlatformAwareness(
449 (context) => Material(
450 child: getIt.get<NewSendPage>(
449 - param1: SendPageParams(initialPaymentRequest: initialPaymentRequest,unspentCoinType: coinTypeToSpendFrom ?? UnspentCoinType.any),
451 + param1: SendPageParams(
452 + initialPaymentRequest: initialPaymentRequest,
453 + unspentCoinType: coinTypeToSpendFrom ?? UnspentCoinType.any),
454 ),
455 ),
456 settings: settings,
@@ -457,11 +461,12 @@ Route<dynamic> createRoute(RouteSettings settings) {
461 fullscreenDialog: true, builder: (_) => getIt.get<SendTemplatePage>());
462
463 case Routes.receive:
460 - return CupertinoPageRoute<void>(builder: (context) => getIt.get<ReceivePage>(), settings: settings);
464 + return CupertinoPageRoute<void>(
465 + builder: (context) => getIt.get<ReceivePage>(), settings: settings);
466
467 case Routes.addressPage:
463 - return handleRouteWithPlatformAwareness(
464 - (context) => getIt.get<AddressPage>(), settings: settings);
468 + return handleRouteWithPlatformAwareness((context) => getIt.get<AddressPage>(),
469 + settings: settings);
470
471 case Routes.transactionDetails:
472 return CupertinoPageRoute<void>(
@@ -586,10 +591,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
591
592 case Routes.securityBackupDuressPin:
593 return handleRouteWithPlatformAwareness(
589 - (context) => getIt.get<SecurityBackupPage>(),
594 + (context) => getIt.get<SecurityBackupPage>(),
595 );
596
592 -
597 case Routes.privacyPage:
598 return handleRouteWithPlatformAwareness(
599 (context) => getIt.get<PrivacyPage>(),
@@ -616,9 +620,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
620 case Routes.newNode:
621 final args = settings.arguments as Map<String, dynamic>?;
622 final page = getIt.get<NodeCreateOrEditPage>(
619 - param1: args?['editingNode'] as Node?, param2: args?['isSelected'] as bool?);
620 - return CupertinoPageRoute<void>(
621 - builder: (_) => page);
623 + param1: args?['editingNode'] as Node?, param2: args?['isSelected'] as bool?);
624 + return CupertinoPageRoute<void>(builder: (_) => page);
625
626 case Routes.login:
627 return CupertinoPageRoute<void>(
@@ -635,9 +638,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
638 case Routes.newPowNode:
639 final args = settings.arguments as Map<String, dynamic>?;
640 final page = getIt.get<PowNodeCreateOrEditPage>(
638 - param1: args?['editingNode'] as Node?, param2: args?['isSelected'] as bool?);
639 - return CupertinoPageRoute<void>(
640 - builder: (_) => page);
641 + param1: args?['editingNode'] as Node?, param2: args?['isSelected'] as bool?);
642 + return CupertinoPageRoute<void>(builder: (_) => page);
643
644 case Routes.accountCreation:
645 return CupertinoPageRoute<String>(
@@ -822,7 +824,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
824 final toggleTestnet = args['toggleTestnet'] as Function(bool? val);
825 final restoredWallet = args['restoredWallet'] as RestoredWallet?;
826
825 - final viewModelParam = {'type' : type, 'isPow' : false};
827 + final viewModelParam = {'type': type, 'isPow': false};
828
829 return handleRouteWithPlatformAwareness(
830 (context) => AdvancedPrivacySettingsPage(
lib/solana/cw_solana.dart
+2 -2
@@ -123,8 +123,8 @@ class CWSolana extends Solana {
123 }
124
125 return (wallet as SolanaWallet).splTokenCurrencies.firstWhere(
126 - (element) => transaction.amount.currency.symbol == element.symbol,
127 - );
126 + (element) => transaction.amount.currency.symbol == element.symbol,
127 + );
128 }
129
130 @override
lib/src/screens/Info_page.dart
+1 -1
@@ -26,7 +26,7 @@ abstract class InfoPage extends BasePage {
26
27 @override
28 Widget Function(BuildContext, Widget) get rootWrapper =>
29 - (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
29 + (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
30
31 @override
32 Widget? leading(BuildContext context) => null;
lib/src/screens/auth/auth_page.dart
+6 -2
@@ -97,7 +97,7 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
97 @override
98 void changeProcessText(String text) {
99 dismissFlushBar(_authBar);
100 - _progressBar = createBar<void>(text,context, duration: null)..show(_key.currentContext!);
100 + _progressBar = createBar<void>(text, context, duration: null)..show(_key.currentContext!);
101 }
102
103 @override
@@ -137,7 +137,11 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
137 key: _key,
138 appBar: CupertinoNavigationBar(
139 leading: widget.closable
140 - ? ModernButton(size: 36, icon: Icon(Icons.close), onPressed: Navigator.of(context).pop, iconColor: Theme.of(context).colorScheme.onSurfaceVariant)
140 + ? ModernButton(
141 + size: 36,
142 + icon: Icon(Icons.close),
143 + onPressed: Navigator.of(context).pop,
144 + iconColor: Theme.of(context).colorScheme.onSurfaceVariant)
145 : Container(),
146 backgroundColor: Theme.of(context).colorScheme.surface,
147 border: null),
lib/src/screens/backup/backup_page.dart
+5 -6
@@ -108,7 +108,7 @@ class BackupPage extends BasePage {
108 }
109
110 void onExportBackup(BuildContext context) {
111 - if(backupViewModelBase.backupPassword.isEmpty) return;
111 + if (backupViewModelBase.backupPassword.isEmpty) return;
112 showPopUp<void>(
113 context: context,
114 builder: (dialogContext) {
@@ -175,11 +175,10 @@ class BackupPage extends BasePage {
175 }
176
177 Future<void> _saveFile(BackupExportFile backup) async {
178 - String? outputFile = await FilePicker.platform
179 - .saveFile(
180 - dialogTitle: 'Save Your File to desired location',
181 - fileName: backup.name,
182 - lockParentWindow: true);
178 + String? outputFile = await FilePicker.platform.saveFile(
179 + dialogTitle: 'Save Your File to desired location',
180 + fileName: backup.name,
181 + lockParentWindow: true);
182
183 if (outputFile == null) return;
184
lib/src/screens/backup/edit_backup_password_page.dart
+2 -3
@@ -23,9 +23,8 @@ class _EditBackupPasswordPageState extends State<EditBackupPasswordPage> {
23 void initState() {
24 super.initState();
25 textEditingController.text = widget.editBackupPasswordViewModel.backupPassword;
26 - textEditingController
27 - .addListener(() {
28 - if(textEditingController.text != widget.editBackupPasswordViewModel.backupPassword) {
26 + textEditingController.addListener(() {
27 + if (textEditingController.text != widget.editBackupPasswordViewModel.backupPassword) {
28 widget.editBackupPasswordViewModel.backupPassword = textEditingController.text;
29 }
30 });
lib/src/screens/buy/buy_sell_page.dart
+6 -11
@@ -276,8 +276,7 @@ class BuySellPage extends BasePage {
276 (_) => _onWalletNameChange(
277 buySellViewModel, buySellViewModel.cryptoCurrency, cryptoCurrencyKey));
278
279 - reaction(
280 - (_) => buySellViewModel.cryptoCurrency,
279 + reaction((_) => buySellViewModel.cryptoCurrency,
280 (currency) => _onCurrencyChange(currency, buySellViewModel, cryptoCurrencyKey));
281
282 reaction((_) => buySellViewModel.fiatCurrency,
@@ -360,8 +359,7 @@ class BuySellPage extends BasePage {
359 key.currentState!.changeWalletName(isCurrentTypeWallet ? buySellViewModel.wallet.name : '');
360
361 key.currentState!.changeAddress(
363 - address:
364 - isCurrentTypeWallet ? buySellViewModel.wallet.walletAddresses.addressForBuy : '');
362 + address: isCurrentTypeWallet ? buySellViewModel.wallet.walletAddresses.addressForBuy : '');
363
364 key.currentState!.changeAmount(amount: '');
365 }
@@ -414,17 +412,14 @@ class BuySellPage extends BasePage {
412 borderColor: Theme.of(context).colorScheme.outlineVariant,
413 onPushPasteButton: (context) async {
414 final domain = cryptoCurrencyKey.currentState!.addressController.text;
417 - final parsed =
418 - await fetchParsedAddress(context, domain, buySellViewModel.cryptoCurrency);
415 + final parsed = await fetchParsedAddress(context, domain, buySellViewModel.cryptoCurrency);
416 if (parsed.isNotEmpty) {
417 buySellViewModel.cryptoCurrencyAddress = parsed;
418 }
419 },
423 -
420 onPushAddressBookButton: (context) async {
421 final domain = cryptoCurrencyKey.currentState!.addressController.text;
426 - final parsed =
427 - await fetchParsedAddress(context, domain, buySellViewModel.cryptoCurrency);
422 + final parsed = await fetchParsedAddress(context, domain, buySellViewModel.cryptoCurrency);
423 if (parsed.isNotEmpty) {
424 buySellViewModel.cryptoCurrencyAddress = parsed;
425 }
@@ -554,8 +549,8 @@ class BuySellPage extends BasePage {
549 String domain,
550 CryptoCurrency currency,
551 ) async {
557 - final parsedAddresses = await _resolver.resolve(
558 - query: domain, wallet: buySellViewModel.wallet, currency: currency);
552 + final parsedAddresses =
553 + await _resolver.resolve(query: domain, wallet: buySellViewModel.wallet, currency: currency);
554 return parsedAddresses.isNotEmpty
555 ? parsedAddresses.first.parsedAddressByCurrencyMap[currency] ?? ''
556 : '';
lib/src/screens/buy/webview_page.dart
+2 -3
@@ -78,9 +78,8 @@ class WebViewPageBodyState extends State<WebViewPageBody> {
78
79 return PermissionResponse(
80 resources: request.resources,
81 - action: permissionGranted
82 - ? PermissionResponseAction.GRANT
83 - : PermissionResponseAction.DENY,
81 + action:
82 + permissionGranted ? PermissionResponseAction.GRANT : PermissionResponseAction.DENY,
83 );
84 },
85 );
lib/src/screens/connect_device/connect_device_page.dart
+2 -1
@@ -164,7 +164,8 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
164 final isConnected = await widget.hardwareWalletVM.connectDevice(device, widget.walletType);
165
166 WidgetsBinding.instance.addPostFrameCallback((_) {
167 - if (isConnected) widget.onConnectDevice(navigatorKey.currentContext!, widget.hardwareWalletVM);
167 + if (isConnected)
168 + widget.onConnectDevice(navigatorKey.currentContext!, widget.hardwareWalletVM);
169 });
170 }
171
lib/src/screens/connect_device/monero_hardware_wallet_options_page.dart
+1 -1
@@ -31,7 +31,7 @@ class _MoneroHardwareWalletOptionsForm extends StatefulWidget {
31 const _MoneroHardwareWalletOptionsForm(this._walletHardwareRestoreVM);
32
33 final WalletHardwareRestoreViewModel _walletHardwareRestoreVM;
34 -
34 +
35 @override
36 _MoneroHardwareWalletOptionsFormState createState() =>
37 _MoneroHardwareWalletOptionsFormState(_walletHardwareRestoreVM);
lib/src/screens/connect_device/widgets/device_tile.dart
+3 -3
@@ -56,9 +56,9 @@ class DeviceTile extends StatelessWidget {
56 child: Text(
57 title,
58 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
59 - fontSize: 20,
60 - fontWeight: FontWeight.w500,
61 - ),
59 + fontSize: 20,
60 + fontWeight: FontWeight.w500,
61 + ),
62 ),
63 ),
64 ),
lib/src/screens/contact/contact_list_page.dart
+30 -30
@@ -41,7 +41,7 @@ class ContactListPage extends BasePage {
41
42 @override
43 Widget? trailing(BuildContext context) {
44 - if(!showAddButton) return SizedBox.shrink();
44 + if (!showAddButton) return SizedBox.shrink();
45 return MergeSemantics(
46 child: Container(
47 width: 36.0,
@@ -417,32 +417,32 @@ class _ContactListBodyState extends State<ContactListBody> {
417
418 ActionPane _actionPane(BuildContext context, ContactRecord contact) {
419 return ActionPane(
420 - motion: const ScrollMotion(),
421 - extentRatio: 0.4,
422 - children: [
423 - SlidableAction(
424 - onPressed: (_) async => await Navigator.of(context)
425 - .pushNamed(Routes.addressBookAddContact, arguments: contact),
426 - backgroundColor: Theme.of(context).colorScheme.primary,
427 - foregroundColor: Theme.of(context).colorScheme.onSurface,
428 - icon: Icons.edit,
429 - label: S.of(context).edit,
430 - ),
431 - SlidableAction(
432 - onPressed: (_) async {
433 - final isDelete = await DialogService.showAlertDialog(context);
434 -
435 - if (isDelete) {
436 - await widget.contactListViewModel.delete(contact);
437 - }
438 - },
439 - backgroundColor: Theme.of(context).colorScheme.error,
440 - foregroundColor: Theme.of(context).colorScheme.onSurface,
441 - icon: CupertinoIcons.delete,
442 - label: S.of(context).delete,
443 - ),
444 - ],
445 - );
420 + motion: const ScrollMotion(),
421 + extentRatio: 0.4,
422 + children: [
423 + SlidableAction(
424 + onPressed: (_) async => await Navigator.of(context)
425 + .pushNamed(Routes.addressBookAddContact, arguments: contact),
426 + backgroundColor: Theme.of(context).colorScheme.primary,
427 + foregroundColor: Theme.of(context).colorScheme.onSurface,
428 + icon: Icons.edit,
429 + label: S.of(context).edit,
430 + ),
431 + SlidableAction(
432 + onPressed: (_) async {
433 + final isDelete = await DialogService.showAlertDialog(context);
434 +
435 + if (isDelete) {
436 + await widget.contactListViewModel.delete(contact);
437 + }
438 + },
439 + backgroundColor: Theme.of(context).colorScheme.error,
440 + foregroundColor: Theme.of(context).colorScheme.onSurface,
441 + icon: CupertinoIcons.delete,
442 + label: S.of(context).delete,
443 + ),
444 + ],
445 + );
446 }
447
448 Widget filterButtonWidget(BuildContext context, ContactListViewModel contactListViewModel) {
@@ -525,9 +525,9 @@ class DialogService {
525 textAlign: TextAlign.center,
526 walletType: cryptoCurrencyOrTokenToWalletType(contact.type),
527 evenTextStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
528 - fontSize: 16,
529 - decoration: TextDecoration.none,
530 - ),
528 + fontSize: 16,
529 + decoration: TextDecoration.none,
530 + ),
531 ),
532 rightButtonText: S.of(context).copy,
533 leftButtonText: S.of(context).cancel,
lib/src/screens/contact/contact_page.dart
+17 -16
@@ -24,7 +24,7 @@ class ContactPage extends BasePage {
24 _nameController = TextEditingController(),
25 _addressController = TextEditingController(),
26 _currencyTypeController = TextEditingController(),
27 - addressFocusNode = FocusNode(){
27 + addressFocusNode = FocusNode() {
28 _nameController.text = contactViewModel.name;
29 _addressController.text = contactViewModel.address;
30 _nameController.addListener(() => contactViewModel.name = _nameController.text);
@@ -38,7 +38,8 @@ class ContactPage extends BasePage {
38 contactViewModel.address = address;
39 });
40
41 - autorun((_) => _currencyTypeController.text = "${contactViewModel.currency?.toString() ?? ""} ${contactViewModel.currency?.tag != null ? "(${contactViewModel.currency?.tag})" : ""}");
41 + autorun((_) => _currencyTypeController.text =
42 + "${contactViewModel.currency?.toString() ?? ""} ${contactViewModel.currency?.tag != null ? "(${contactViewModel.currency?.tag})" : ""}");
43 }
44
45 @override
@@ -105,13 +106,13 @@ class ContactPage extends BasePage {
106 builder: (_) {
107 return NewSendAddressInput(
108 focusNode: addressFocusNode,
108 - displayName: contactViewModel.displayName,
109 - addressController: _addressController,
110 - onEditingComplete: () {},
111 - onPushPasteButton: (context) => _extractParsedAddress(context),
112 - validator: AddressValidator(type: contactViewModel.currency!),
113 - selectedCurrency: contactViewModel.currency!,
114 - );
109 + displayName: contactViewModel.displayName,
110 + addressController: _addressController,
111 + onEditingComplete: () {},
112 + onPushPasteButton: (context) => _extractParsedAddress(context),
113 + validator: AddressValidator(type: contactViewModel.currency!),
114 + selectedCurrency: contactViewModel.currency!,
115 + );
116 },
117 ),
118 )
@@ -216,17 +217,17 @@ class ContactPage extends BasePage {
217 }
218 });
219
219 - reaction((_)=>contactViewModel.address, (val){
220 - if(val != _addressController.text) {
220 + reaction((_) => contactViewModel.address, (val) {
221 + if (val != _addressController.text) {
222 _addressController.text = val;
223 }
224 });
225 }
226
227 Future<bool> showParsedAddressConfirmationAlert(
227 - BuildContext context,
228 - ParsedAddress parsedAddress,
229 - ) async {
228 + BuildContext context,
229 + ParsedAddress parsedAddress,
230 + ) async {
231 final confirmed = await showPopUp<bool>(
232 context: context,
233 builder: (BuildContext context) {
@@ -237,8 +238,8 @@ class ContactPage extends BasePage {
238 ? parsedAddress.addressSource.iconPath
239 : parsedAddress.profileImageUrl,
240 alertContent: S.of(context).extracted_address_content(
240 - '${parsedAddress.handle} (${parsedAddress.addressSource.label})',
241 - ),
241 + '${parsedAddress.handle} (${parsedAddress.addressSource.label})',
242 + ),
243 buttonText: S.of(context).ok,
244 buttonAction: () => Navigator.of(context).pop(true),
245 );
lib/src/screens/dashboard/dashboard_page.dart
+3 -4
@@ -305,10 +305,9 @@ class _DashboardPageView extends BasePage {
305 ),
306 ),
307 NewMainNavBar(
308 - dashboardViewModel: dashboardViewModel,
309 - selectedIndex: 0,
310 - onItemTap: (index) {}
311 - ),
308 + dashboardViewModel: dashboardViewModel,
309 + selectedIndex: 0,
310 + onItemTap: (index) {}),
311 ],
312 ),
313 ],
lib/src/screens/dashboard/desktop_dashboard_page.dart
+1 -1
@@ -121,7 +121,7 @@ class DesktopDashboardPage extends StatelessWidget {
121 if (affectedWalletNames.isNotEmpty) {
122 Future<void>.delayed(
123 Duration(seconds: 1),
124 - () {
124 + () {
125 showPopUp<void>(
126 context: context,
127 builder: (BuildContext context) {
lib/src/screens/dashboard/desktop_widgets/desktop_action_button.dart
+7 -7
@@ -50,13 +50,13 @@ class DesktopActionButton extends StatelessWidget {
50 AutoSizeText(
51 title,
52 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
53 - fontSize: 24,
54 - fontWeight: FontWeight.bold,
55 - color: isEnabled
56 - ? Theme.of(context).colorScheme.onPrimaryContainer
57 - : Theme.of(context).colorScheme.onSurfaceVariant,
58 - height: 1,
59 - ),
53 + fontSize: 24,
54 + fontWeight: FontWeight.bold,
55 + color: isEnabled
56 + ? Theme.of(context).colorScheme.onPrimaryContainer
57 + : Theme.of(context).colorScheme.onSurfaceVariant,
58 + height: 1,
59 + ),
60 maxLines: 1,
61 textAlign: TextAlign.center,
62 )
lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart
+57 -57
@@ -16,72 +16,72 @@ class DesktopDashboardActions extends StatelessWidget {
16 Widget build(BuildContext context) {
17 return Container(
18 color: Theme.of(context).colorScheme.surface,
19 - child: Observer(
20 - builder: (_) {
21 - return Column(
22 - children: [
23 - const SizedBox(height: 16),
24 - DesktopActionButton(
25 - title: MainActions.showWalletsAction.name(context),
26 - image: MainActions.showWalletsAction.image,
27 - canShow: MainActions.showWalletsAction.canShow?.call(dashboardViewModel),
28 - isEnabled: MainActions.showWalletsAction.isEnabled?.call(dashboardViewModel),
29 - onTap: () async =>
30 - await MainActions.showWalletsAction.onTap(context, dashboardViewModel),
31 - ),
32 - DesktopActionButton(
33 - title: MainActions.swapAction.name(context),
34 - image: MainActions.swapAction.image,
35 - canShow: MainActions.swapAction.canShow?.call(dashboardViewModel),
36 - isEnabled: MainActions.swapAction.isEnabled?.call(dashboardViewModel),
37 - onTap: () async => await MainActions.swapAction.onTap(context, dashboardViewModel),
38 - ),
39 - Row(
40 - children: [
41 - Expanded(
42 - child: DesktopActionButton(
43 - title: MainActions.receiveAction.name(context),
44 - image: MainActions.receiveAction.image,
45 - canShow: MainActions.receiveAction.canShow?.call(dashboardViewModel),
46 - isEnabled: MainActions.receiveAction.isEnabled?.call(dashboardViewModel),
47 - onTap: () async =>
48 - await MainActions.receiveAction.onTap(context, dashboardViewModel),
49 - ),
19 + child: Observer(builder: (_) {
20 + return Column(
21 + children: [
22 + const SizedBox(height: 16),
23 + DesktopActionButton(
24 + title: MainActions.showWalletsAction.name(context),
25 + image: MainActions.showWalletsAction.image,
26 + canShow: MainActions.showWalletsAction.canShow?.call(dashboardViewModel),
27 + isEnabled: MainActions.showWalletsAction.isEnabled?.call(dashboardViewModel),
28 + onTap: () async =>
29 + await MainActions.showWalletsAction.onTap(context, dashboardViewModel),
30 + ),
31 + DesktopActionButton(
32 + title: MainActions.swapAction.name(context),
33 + image: MainActions.swapAction.image,
34 + canShow: MainActions.swapAction.canShow?.call(dashboardViewModel),
35 + isEnabled: MainActions.swapAction.isEnabled?.call(dashboardViewModel),
36 + onTap: () async => await MainActions.swapAction.onTap(context, dashboardViewModel),
37 + ),
38 + Row(
39 + children: [
40 + Expanded(
41 + child: DesktopActionButton(
42 + title: MainActions.receiveAction.name(context),
43 + image: MainActions.receiveAction.image,
44 + canShow: MainActions.receiveAction.canShow?.call(dashboardViewModel),
45 + isEnabled: MainActions.receiveAction.isEnabled?.call(dashboardViewModel),
46 + onTap: () async =>
47 + await MainActions.receiveAction.onTap(context, dashboardViewModel),
48 ),
51 - Expanded(
52 - child: DesktopActionButton(
53 - title: MainActions.sendAction.name(context),
54 - image: MainActions.sendAction.image,
55 - canShow: MainActions.sendAction.canShow?.call(dashboardViewModel),
56 - isEnabled: MainActions.sendAction.isEnabled?.call(dashboardViewModel),
57 - onTap: () async => await MainActions.sendAction.onTap(context, dashboardViewModel),
58 - ),
49 + ),
50 + Expanded(
51 + child: DesktopActionButton(
52 + title: MainActions.sendAction.name(context),
53 + image: MainActions.sendAction.image,
54 + canShow: MainActions.sendAction.canShow?.call(dashboardViewModel),
55 + isEnabled: MainActions.sendAction.isEnabled?.call(dashboardViewModel),
56 + onTap: () async =>
57 + await MainActions.sendAction.onTap(context, dashboardViewModel),
58 ),
60 - ],
61 - ),
62 - Row(
63 - children: [
64 - Expanded(
65 - child: DesktopActionButton(
66 - title: MainActions.tradeAction.name(context),
67 - image: MainActions.tradeAction.image,
68 - canShow: MainActions.tradeAction.canShow?.call(dashboardViewModel),
69 - isEnabled: MainActions.tradeAction.isEnabled?.call(dashboardViewModel),
70 - onTap: () async => await MainActions.tradeAction.onTap(context, dashboardViewModel),
71 - ),
59 + ),
60 + ],
61 + ),
62 + Row(
63 + children: [
64 + Expanded(
65 + child: DesktopActionButton(
66 + title: MainActions.tradeAction.name(context),
67 + image: MainActions.tradeAction.image,
68 + canShow: MainActions.tradeAction.canShow?.call(dashboardViewModel),
69 + isEnabled: MainActions.tradeAction.isEnabled?.call(dashboardViewModel),
70 + onTap: () async =>
71 + await MainActions.tradeAction.onTap(context, dashboardViewModel),
72 ),
73 - ],
74 - ),
73 + ),
74 + ],
75 + ),
76 Expanded(
77 child: CakeFeaturesPage(
78 dashboardViewModel: dashboardViewModel,
79 cakeFeaturesViewModel: getIt.get<CakeFeaturesViewModel>(),
80 ),
81 ),
81 - ],
82 - );
83 - }
84 - ),
82 + ],
83 + );
84 + }),
85 );
86 }
87 }
lib/src/screens/dashboard/desktop_widgets/desktop_dashboard_navbar.dart
+1 -2
@@ -20,7 +20,6 @@ class DesktopDashboardNavbar extends StatelessWidget implements ObstructingPrefe
20
21 @override
22 Widget build(BuildContext context) {
23 -
23 return Container(
24 padding: const EdgeInsetsDirectional.only(end: 24),
25 color: Theme.of(context).colorScheme.surfaceContainerLowest.withOpacity(0.1),
@@ -40,7 +39,7 @@ class DesktopDashboardNavbar extends StatelessWidget implements ObstructingPrefe
39
40 @override
41 Size get preferredSize => Size.fromHeight(60);
43 -
42 +
43 @override
44 bool shouldFullyObstruct(BuildContext context) => false;
45 }
lib/src/screens/dashboard/desktop_widgets/desktop_sidebar/side_menu.dart
+1 -1
@@ -8,7 +8,7 @@ class SideMenu extends StatelessWidget {
8 required this.bottomItems,
9 required this.width,
10 });
11 -
11 +
12 final List<SideMenuItem> topItems;
13 final List<SideMenuItem> bottomItems;
14 final double width;
lib/src/screens/dashboard/desktop_widgets/desktop_wallet_selection_dropdown.dart
+23 -12
@@ -31,25 +31,36 @@ class DesktopWalletSelectionDropDown extends StatefulWidget {
31 }
32
33 class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionDropDown> {
34 - final moneroIcon = Image.asset('assets/new-ui/crypto_full_icons/monero.svg', height: 24, width: 24);
35 - final bitcoinIcon = Image.asset('assets/new-ui/crypto_full_icons/bitcoin.svg', height: 24, width: 24);
34 + final moneroIcon =
35 + Image.asset('assets/new-ui/crypto_full_icons/monero.svg', height: 24, width: 24);
36 + final bitcoinIcon =
37 + Image.asset('assets/new-ui/crypto_full_icons/bitcoin.svg', height: 24, width: 24);
38 final tBitcoinIcon = Image.asset('assets/images/tbtc.png', height: 24, width: 24);
37 - final litecoinIcon = Image.asset('assets/new-ui/crypto_full_icons/litecoin.svg', height: 24, width: 24);
39 + final litecoinIcon =
40 + Image.asset('assets/new-ui/crypto_full_icons/litecoin.svg', height: 24, width: 24);
41 final havenIcon = Image.asset('assets/images/haven_logo.webp', height: 24, width: 24);
39 - final ethereumIcon = Image.asset('assets/new-ui/crypto_full_icons/ethereum.svg', height: 24, width: 24);
40 - final polygonIcon = Image.asset('assets/new-ui/crypto_full_icons/polygon.svg', height: 24, width: 24);
41 - final bitcoinCashIcon = Image.asset('assets/new-ui/crypto_full_icons/bitcoin-cash.svg', height: 24, width: 24);
42 + final ethereumIcon =
43 + Image.asset('assets/new-ui/crypto_full_icons/ethereum.svg', height: 24, width: 24);
44 + final polygonIcon =
45 + Image.asset('assets/new-ui/crypto_full_icons/polygon.svg', height: 24, width: 24);
46 + final bitcoinCashIcon =
47 + Image.asset('assets/new-ui/crypto_full_icons/bitcoin-cash.svg', height: 24, width: 24);
48 final baseIcon = Image.asset('assets/new-ui/crypto_full_icons/base.svg', height: 24, width: 24);
43 - final arbitrumIcon = Image.asset('assets/new-ui/crypto_full_icons/arbitrum.svg', height: 24, width: 24);
49 + final arbitrumIcon =
50 + Image.asset('assets/new-ui/crypto_full_icons/arbitrum.svg', height: 24, width: 24);
51 final bscIcon = Image.asset('assets/new-ui/crypto_full_icons/bnb.svg', height: 24, width: 24);
52 final nanoIcon = Image.asset('assets/new-ui/crypto_full_icons/nano.svg', height: 24, width: 24);
53 final bananoIcon = Image.asset('assets/new-ui/crypto_full_icons/nano.svg', height: 24, width: 24);
47 - final solanaIcon = Image.asset('assets/new-ui/crypto_full_icons/solana.svg', height: 24, width: 24);
54 + final solanaIcon =
55 + Image.asset('assets/new-ui/crypto_full_icons/solana.svg', height: 24, width: 24);
56 final tronIcon = Image.asset('assets/new-ui/crypto_full_icons/tron.svg', height: 24, width: 24);
49 - final wowneroIcon = Image.asset('assets/new-ui/crypto_full_icons/wownero.svg', height: 24, width: 24);
57 + final wowneroIcon =
58 + Image.asset('assets/new-ui/crypto_full_icons/wownero.svg', height: 24, width: 24);
59 final zanoIcon = Image.asset('assets/new-ui/crypto_full_icons/zano.svg', height: 24, width: 24);
51 - final decredIcon = Image.asset('assets/new-ui/crypto_full_icons/decred.svg', height: 24, width: 24);
52 - final dogeIcon = Image.asset('assets/new-ui/crypto_full_icons/dogecoin.svg', height: 24, width: 24);
60 + final decredIcon =
61 + Image.asset('assets/new-ui/crypto_full_icons/decred.svg', height: 24, width: 24);
62 + final dogeIcon =
63 + Image.asset('assets/new-ui/crypto_full_icons/dogecoin.svg', height: 24, width: 24);
64 final zcashIcon = Image.asset('assets/new-ui/crypto_full_icons/zcash.svg', height: 24, width: 24);
65 final nonWalletTypeIcon = Image.asset('assets/images/close.png', height: 24, width: 24);
66
@@ -264,7 +275,7 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
275 }
276
277 void changeProcessText(String text) {
267 - _progressBar = createBar<void>(text,context, duration: null)..show(context);
278 + _progressBar = createBar<void>(text, context, duration: null)..show(context);
279 }
280
281 void hideProgressText() {
lib/src/screens/dashboard/favorite_token_modal.dart
+2 -3
@@ -14,9 +14,8 @@ class FavoriteTokenModal extends StatelessWidget {
14 Widget build(BuildContext context) {
15 return Container(
16 decoration: BoxDecoration(
17 - color: Theme.of(context).colorScheme.surface,
18 - borderRadius: BorderRadius.vertical(top: Radius.circular(18))
19 - ),
17 + color: Theme.of(context).colorScheme.surface,
18 + borderRadius: BorderRadius.vertical(top: Radius.circular(18))),
19 child: SafeArea(
20 child: Column(
21 children: [
lib/src/screens/dashboard/pages/balance/balance_page.dart
+2 -1
@@ -22,7 +22,8 @@ class BalancePage extends StatelessWidget {
22 Widget build(BuildContext context) {
23 return Observer(
24 builder: (context) {
25 - final isNFTActivated = isNFTACtivatedChain(dashboardViewModel.type, chainId: dashboardViewModel.wallet.chainId);
25 + final isNFTActivated = isNFTACtivatedChain(dashboardViewModel.type,
26 + chainId: dashboardViewModel.wallet.chainId);
27 return DefaultTabController(
28 key: ValueKey<bool>(isNFTActivated),
29 length: isNFTActivated ? 2 : 1,
lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart
+5 -5
@@ -334,7 +334,7 @@ class CryptoBalanceWidget extends StatelessWidget {
334 ),
335 ),
336 ],
337 - if (dashboardViewModel.showZcashMissingFundsCard) ...[
337 + if (dashboardViewModel.showZcashMissingFundsCard) ...[
338 SizedBox(height: 10),
339 Padding(
340 padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
@@ -349,7 +349,8 @@ class CryptoBalanceWidget extends StatelessWidget {
349 hintWidget: GestureDetector(
350 behavior: HitTestBehavior.opaque,
351 onTap: () => launchUrl(
352 - Uri.parse("https://docs.cakewallet.com/tutorials/zashi/#creating-a-new-zcash-wallet-on-cake"),
352 + Uri.parse(
353 + "https://docs.cakewallet.com/tutorials/zashi/#creating-a-new-zcash-wallet-on-cake"),
354 mode: LaunchMode.externalApplication,
355 ),
356 child: Text(
@@ -492,7 +493,7 @@ class CryptoBalanceWidget extends StatelessWidget {
493 }
494 dashboardViewModel.setMwebEnabled();
495 }
495 -
496 +
497 Future<void> _rescanInternalChangeZcash(BuildContext context) async {
498 dashboardViewModel.rescanInternalChangeZcash();
499 await showPopUp<void>(
@@ -507,7 +508,6 @@ class CryptoBalanceWidget extends StatelessWidget {
508 ),
509 );
510 }
510 -
511
512 Future<void> _dismissMweb(BuildContext context) async {
513 await showPopUp<void>(
@@ -522,7 +522,7 @@ class CryptoBalanceWidget extends StatelessWidget {
522 ));
523 dashboardViewModel.dismissMweb();
524 }
525 -
525 +
526 Future<void> _dismissZcash(BuildContext context) async {
527 await showPopUp<void>(
528 context: context,
lib/src/screens/dashboard/pages/cake_features_page.dart
+35 -31
@@ -27,27 +27,27 @@ class CakeFeaturesPage extends StatelessWidget {
27 Widget build(BuildContext context) {
28 return GradientBackground(
29 scaffold: SafeArea(
30 - child: Column(
31 - crossAxisAlignment: CrossAxisAlignment.start,
32 - children: [
33 - _buildHeader(context),
34 - Expanded(
35 - child: LayoutBuilder(
36 - builder: (context, constraints) {
37 - return SingleChildScrollView(
38 - child: ConstrainedBox(
39 - constraints: BoxConstraints(minHeight: constraints.maxHeight),
40 - child: IntrinsicHeight(
41 - child: !FeatureFlag.hasNewUi ? _buildOldUi(context) : _buildNewUi(context),
42 - ),
30 + child: Column(
31 + crossAxisAlignment: CrossAxisAlignment.start,
32 + children: [
33 + _buildHeader(context),
34 + Expanded(
35 + child: LayoutBuilder(
36 + builder: (context, constraints) {
37 + return SingleChildScrollView(
38 + child: ConstrainedBox(
39 + constraints: BoxConstraints(minHeight: constraints.maxHeight),
40 + child: IntrinsicHeight(
41 + child: !FeatureFlag.hasNewUi ? _buildOldUi(context) : _buildNewUi(context),
42 ),
44 - );
45 - },
46 - ),
43 + ),
44 + );
45 + },
46 ),
48 - ],
49 - ),
47 + ),
48 + ],
49 ),
50 + ),
51 );
52 }
53
@@ -58,9 +58,9 @@ class CakeFeaturesPage extends StatelessWidget {
58 child: Text(
59 S.of(context).apps,
60 style: Theme.of(context).textTheme.headlineLarge?.copyWith(
61 - fontWeight: FontWeight.w500,
62 - color: Theme.of(context).colorScheme.onSurface,
63 - ),
61 + fontWeight: FontWeight.w500,
62 + color: Theme.of(context).colorScheme.onSurface,
63 + ),
64 ),
65 );
66 }
@@ -72,10 +72,10 @@ class CakeFeaturesPage extends StatelessWidget {
72 child: Text(
73 S.of(context).apps,
74 style: Theme.of(context).textTheme.titleLarge?.copyWith(
75 - fontSize: 18.0,
76 - fontWeight: FontWeight.w600,
77 - color: Theme.of(context).colorScheme.onSurface,
78 - ),
75 + fontSize: 18.0,
76 + fontWeight: FontWeight.w600,
77 + color: Theme.of(context).colorScheme.onSurface,
78 + ),
79 ),
80 ),
81 );
@@ -101,7 +101,8 @@ class CakeFeaturesPage extends StatelessWidget {
101 onTap: () => Navigator.of(context).pushNamed(Routes.dEuroSavings),
102 title: S.of(context).deuro_savings,
103 subTitle: S.of(context).deuro_savings_subtitle,
104 - image: Image.asset('assets/images/deuro_icon.png', height: 80, width: 80, fit: BoxFit.cover),
104 + image: Image.asset('assets/images/deuro_icon.png',
105 + height: 80, width: 80, fit: BoxFit.cover),
106 );
107 }
108 return const SizedBox();
@@ -128,7 +129,10 @@ class CakeFeaturesPage extends StatelessWidget {
129 alignment: Alignment.centerLeft,
130 child: Padding(
131 padding: const EdgeInsets.only(left: 24, bottom: 8),
131 - child: CakeImageWidget(imageUrl: "assets/new-ui/by-cakelabs.svg", height: 20, color: Theme.of(context).colorScheme.onSurfaceVariant),
132 + child: CakeImageWidget(
133 + imageUrl: "assets/new-ui/by-cakelabs.svg",
134 + height: 20,
135 + color: Theme.of(context).colorScheme.onSurfaceVariant),
136 ),
137 ),
138 AppsWidget(
@@ -163,9 +167,9 @@ class CakeFeaturesPage extends StatelessWidget {
167 child: Text(
168 "Featured Apps",
169 style: Theme.of(context).textTheme.headlineMedium?.copyWith(
166 - fontWeight: FontWeight.w500,
167 - color: Theme.of(context).colorScheme.onSurface,
168 - ),
170 + fontWeight: FontWeight.w500,
171 + color: Theme.of(context).colorScheme.onSurface,
172 + ),
173 ),
174 ),
175 AppsWidget(
@@ -225,4 +229,4 @@ class CakeFeaturesPage extends StatelessWidget {
229 Navigator.pushNamed(context, Routes.cakePayCardsPage);
230 }
231 }
228 -}
\ No newline at end of file
232 +}
lib/src/screens/dashboard/pages/navigation_dock.dart
+8 -19
@@ -42,39 +42,28 @@ class NavigationDock extends StatelessWidget {
42 mainAxisAlignment: MainAxisAlignment.spaceBetween,
43 crossAxisAlignment: CrossAxisAlignment.center,
44 children: MainActions.all
45 - .where((element) =>
46 - element.canShow?.call(dashboardViewModel) ??
47 - true)
45 + .where((element) => element.canShow?.call(dashboardViewModel) ?? true)
46 .map(
47 (action) => Expanded(
48 child: Semantics(
49 button: true,
52 - enabled: (action.isEnabled
53 - ?.call(dashboardViewModel) ??
54 - true),
50 + enabled: (action.isEnabled?.call(dashboardViewModel) ?? true),
51 child: ActionButton(
52 key: action.key,
53 image: Image.asset(
54 action.image,
55 height: 24,
56 width: 24,
61 - color:
62 - Theme.of(context).colorScheme.primary,
57 + color: Theme.of(context).colorScheme.primary,
58 ),
59 title: action.name(context),
65 - onClick: (action.isEnabled
66 - ?.call(dashboardViewModel) ??
67 - true)
68 - ? () async => await action.onTap(
69 - context, dashboardViewModel)
60 + onClick: (action.isEnabled?.call(dashboardViewModel) ?? true)
61 + ? () async =>
62 + await action.onTap(context, dashboardViewModel)
63 : null,
71 - textColor: action.isEnabled
72 - ?.call(dashboardViewModel) ??
73 - true
64 + textColor: action.isEnabled?.call(dashboardViewModel) ?? true
65 ? null
75 - : Theme.of(context)
76 - .colorScheme
77 - .onSurface,
66 + : Theme.of(context).colorScheme.onSurface,
67 ),
68 ),
69 ),
lib/src/screens/dashboard/pages/nft_listing_page.dart
+2 -4
@@ -94,8 +94,7 @@ class NFTListWidget extends StatelessWidget {
94 if (nftViewModel.solanaNftAssetModels.isEmpty) return emptyMessage;
95
96 return Padding(
97 - padding: EdgeInsets.only(
98 - bottom: 64),
97 + padding: EdgeInsets.only(bottom: 64),
98 child: ListView.separated(
99 shrinkWrap: true,
100 physics: NeverScrollableScrollPhysics(),
@@ -112,8 +111,7 @@ class NFTListWidget extends StatelessWidget {
111 if (nftViewModel.nftAssetByWalletModels.isEmpty) return emptyMessage;
112
113 return Padding(
115 - padding: EdgeInsets.only(
116 - bottom: 64),
114 + padding: EdgeInsets.only(bottom: 64),
115 child: ListView.separated(
116 shrinkWrap: true,
117 physics: NeverScrollableScrollPhysics(),
lib/src/screens/dashboard/pages/transactions_page.dart
+4 -5
@@ -66,8 +66,7 @@ class TransactionsPage extends StatelessWidget {
66 }),
67 HeaderRow(
68 dashboardViewModel: dashboardViewModel,
69 - onExportCsv: () =>
70 - CsvExportService().exportToCsv(dashboardViewModel.items, context),
69 + onExportCsv: () => CsvExportService().exportToCsv(dashboardViewModel.items, context),
70 key: ValueKey('transactions_page_header_row_key'),
71 ),
72 Expanded(
@@ -159,7 +158,8 @@ class TransactionsPage extends StatelessWidget {
158 currency: "BTC",
159 state: item.status,
160 amount: dashboardViewModel.appStore.amountParsingProxy
162 - .getDisplayCryptoString(session.amount.toInt(), CryptoCurrency.btc),
161 + .getDisplayCryptoString(
162 + session.amount.toInt(), CryptoCurrency.btc),
163 createdAt: DateFormat('HH:mm').format(session.inProgressSince!),
164 isSending: session.isSenderSession,
165 );
@@ -168,8 +168,7 @@ class TransactionsPage extends StatelessWidget {
168 if (item is TradeListItem) {
169 final trade = item.trade;
170
171 - final tradeFrom =
172 - trade.from;
171 + final tradeFrom = trade.from;
172
173 final tradeTo = trade.to;
174
lib/src/screens/dashboard/sign_page.dart
+6 -8
@@ -17,10 +17,8 @@ import 'package:smooth_page_indicator/smooth_page_indicator.dart';
17 class SignPage extends StatefulWidget {
18 SignPage(this.signViewModel);
19
20 -
20 final SignViewModel signViewModel;
21
23 -
22 @override
23 State<SignPage> createState() => _SignPageState();
24 }
@@ -29,7 +27,7 @@ class _SignPageState extends State<SignPage> {
27 List<Widget> _pages = [];
28 final signFormKey = GlobalKey<SignFormState>();
29 final verifyFormKey = GlobalKey<VerifyFormState>();
32 - final PageController _controller = PageController(initialPage: 0) ;
30 + final PageController _controller = PageController(initialPage: 0);
31
32 bool _isEffectsInstalled = false;
33
@@ -55,14 +53,14 @@ class _SignPageState extends State<SignPage> {
53 return Container(
54 color: Theme.of(context).colorScheme.surface,
55 child: SafeArea(
58 - top:false,
56 + top: false,
57 child: Column(
58 children: [
61 - ModalTopBar(title: S.current.sign_verify_title,
59 + ModalTopBar(
60 + title: S.current.sign_verify_title,
61 leadingIcon: Icon(Icons.arrow_back_ios_new),
63 - onLeadingPressed: Navigator
64 - .of(context)
65 - .pop,),
62 + onLeadingPressed: Navigator.of(context).pop,
63 + ),
64 Expanded(
65 child: KeyboardHideOverlay(
66 child: Container(
lib/src/screens/dashboard/widgets/action_button.dart
+1 -2
@@ -53,8 +53,7 @@ class ActionButton extends StatelessWidget {
53 softWrap: false,
54 textAlign: TextAlign.center,
55 style: Theme.of(context).textTheme.labelSmall?.copyWith(
56 - color: textColor ??
57 - Theme.of(context).colorScheme.onSurface,
56 + color: textColor ?? Theme.of(context).colorScheme.onSurface,
57 ),
58 ),
59 ),
lib/src/screens/dashboard/widgets/date_section_raw.dart
+2 -2
@@ -17,8 +17,8 @@ class DateSectionRaw extends StatelessWidget {
17 child: Text(
18 title,
19 style: Theme.of(context).textTheme.bodySmall?.copyWith(
20 - color: Theme.of(context).colorScheme.onSurfaceVariant,
21 - ),
20 + color: Theme.of(context).colorScheme.onSurfaceVariant,
21 + ),
22 ),
23 );
24 }
lib/src/screens/dashboard/widgets/filter_tile.dart
+1 -1
@@ -13,4 +13,4 @@ class FilterTile extends StatelessWidget {
13 child: child,
14 );
15 }
16 -}
\ No newline at end of file
16 +}
lib/src/screens/dashboard/widgets/filter_widget.dart
+10 -9
@@ -71,9 +71,9 @@ class _FilterWidgetState extends State<FilterWidget> {
71 child: Text(
72 S.of(context).filter_by,
73 style: Theme.of(context).textTheme.titleMedium?.copyWith(
74 - color: Theme.of(context).colorScheme.onSurface,
75 - fontWeight: FontWeight.bold,
76 - ),
74 + color: Theme.of(context).colorScheme.onSurface,
75 + fontWeight: FontWeight.bold,
76 + ),
77 ),
78 ),
79 ),
@@ -97,14 +97,15 @@ class _FilterWidgetState extends State<FilterWidget> {
97 child: Text(
98 title,
99 style: Theme.of(context).textTheme.titleMedium?.copyWith(
100 - color: Theme.of(context).colorScheme.onSurface,
101 - fontWeight: FontWeight.bold,
102 - decoration: TextDecoration.none,
103 - ),
100 + color: Theme.of(context).colorScheme.onSurface,
101 + fontWeight: FontWeight.bold,
102 + decoration: TextDecoration.none,
103 + ),
104 ),
105 ),
106 ListView.builder(
107 - padding: const EdgeInsets.symmetric(horizontal: 28.0, vertical: 8.0),
107 + padding:
108 + const EdgeInsets.symmetric(horizontal: 28.0, vertical: 8.0),
109 shrinkWrap: true,
110 physics: const NeverScrollableScrollPhysics(),
111 itemCount: section.length,
@@ -138,4 +139,4 @@ class _FilterWidgetState extends State<FilterWidget> {
139 ),
140 );
141 }
141 -}
\ No newline at end of file
142 +}
lib/src/screens/dashboard/widgets/header_row.dart
+3 -5
@@ -26,8 +26,7 @@ class HeaderRow extends StatelessWidget {
26 Text(
27 S.of(context).history,
28 style: Theme.of(context).textTheme.titleLarge?.copyWith(
29 - fontWeight: FontWeight.w500,
30 - color: Theme.of(context).colorScheme.onSurface),
29 + fontWeight: FontWeight.w500, color: Theme.of(context).colorScheme.onSurface),
30 ),
31 Row(
32 children: [
@@ -61,8 +60,7 @@ class HeaderRow extends StatelessWidget {
60 container: true,
61 child: GestureDetector(
62 key: ValueKey('transactions_page_header_row_transaction_filter_button_key'),
64 - onTap: () {
65 - },
63 + onTap: () {},
64 child: Semantics(
65 label: 'Transaction Filter',
66 button: true,
@@ -85,4 +83,4 @@ class HeaderRow extends StatelessWidget {
83 ),
84 );
85 }
88 -}
\ No newline at end of file
86 +}
lib/src/screens/dashboard/widgets/new_main_navbar_widget.dart
+98 -95
@@ -27,8 +27,6 @@ class NewMainNavBar extends StatefulWidget {
27 }
28
29 class _NEWNewMainNavBarState extends State<NewMainNavBar> {
30 -
31 -
30 static const iconBoxWidth = 48.0;
31 static const iconWidth = 28.0;
32 static const iconHeight = 28.0;
@@ -82,9 +80,7 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
80 }
81
82 // Estimate pill width based on text length
85 - double _estimatePillWidthForAction(
86 - BuildContext context, NewMainActions action,
87 - {Color? color}) {
83 + double _estimatePillWidthForAction(BuildContext context, NewMainActions action, {Color? color}) {
84 final text = action.name(context);
85 final textPainter = TextPainter(
86 text: TextSpan(
@@ -94,10 +90,7 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
90 maxLines: 1,
91 textDirection: TextDirection.ltr,
92 )..layout();
97 - return pillIconWidth +
98 - pillIconSpacing +
99 - textPainter.width +
100 - pillHorizontalPadding;
93 + return pillIconWidth + pillIconSpacing + textPainter.width + pillHorizontalPadding;
94 }
95
96 double calcLeft(int index, double pillWidth) {
@@ -113,7 +106,11 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
106 }
107
108 double calcBarWidth(double pillWidth, int visibleActionsLength) {
116 - return (iconWidth + iconHorizontalPadding) * visibleActionsLength + (pillWidth - iconWidth) + barHorizontalPadding + pillIconSpacing / double.infinity - 2;
109 + return (iconWidth + iconHorizontalPadding) * visibleActionsLength +
110 + (pillWidth - iconWidth) +
111 + barHorizontalPadding +
112 + pillIconSpacing / double.infinity -
113 + 2;
114 }
115
116 @override
@@ -138,86 +135,92 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
135 final currentAction = visibleActions[widget.selectedIndex];
136
137 return Align(
141 - alignment: Alignment.bottomCenter,
142 - child: SafeArea(
143 - bottom: !(Platform.isIOS),
144 - top: false,
145 - child: Padding(
146 - // tux PLEASE consult me (malik) before removing this padding.
147 - padding: EdgeInsets.only(bottom: NewMainNavBar.barBottomPadding),
148 - child: AnimatedContainer(
149 - duration: barResizeDuration,
150 - curve: Curves.easeOutCubic,
151 - width: barWidth,
152 - child: ClipRSuperellipse(
153 - borderRadius: BorderRadius.circular(barBorderRadius),
154 - child: BackdropFilter(
155 - filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
156 - child: Container(
157 - height: NewMainNavBar.barHeight,
158 - decoration: ShapeDecoration(
159 - color: backgroundColor,
160 - shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(barBorderRadius),
161 - side: const BorderSide(color: Color(0x14FFFFFF), width: 1),
138 + alignment: Alignment.bottomCenter,
139 + child: SafeArea(
140 + bottom: !(Platform.isIOS),
141 + top: false,
142 + child: Padding(
143 + // tux PLEASE consult me (malik) before removing this padding.
144 + padding: EdgeInsets.only(bottom: NewMainNavBar.barBottomPadding),
145 + child: AnimatedContainer(
146 + duration: barResizeDuration,
147 + curve: Curves.easeOutCubic,
148 + width: barWidth,
149 + child: ClipRSuperellipse(
150 + borderRadius: BorderRadius.circular(barBorderRadius),
151 + child: BackdropFilter(
152 + filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
153 + child: Container(
154 + height: NewMainNavBar.barHeight,
155 + decoration: ShapeDecoration(
156 + color: backgroundColor,
157 + shape: RoundedSuperellipseBorder(
158 + borderRadius: BorderRadius.circular(barBorderRadius),
159 + side: const BorderSide(color: Color(0x14FFFFFF), width: 1),
160 + ),
161 ),
163 - ),
164 - child: Padding(
165 - padding: const EdgeInsets.symmetric(horizontal: barHorizontalPadding),
166 - child: Stack(
167 - alignment: Alignment.center,
168 - children: [
169 - AnimatedPill(
170 - left: calcLeft(widget.selectedIndex, pillWidth),
171 - pillColor: pillColor,
172 - currentAction: currentAction,
173 - pillIconHeight: pillIconHeight,
174 - pillIconWidth: pillIconWidth,
175 - pillIconSpacing: pillIconSpacing,
176 - pillBorderRadius: pillBorderRadius,
177 - contentColor: activeColor,
178 - estimateWidthForAction: pillWidth,
179 - pillTextStyle: pillTextStyle,
180 - pillMoveDuration: pillMoveDuration,
181 - pillResizeDuration: pillResizeDuration,
182 - ),
183 - for (int i = 0; i < visibleActions.length; i++)
184 - AnimatedPositioned(
185 - duration: pillResizeDuration,
186 - width: iconBoxWidth,
187 - left: calcLeft(i, pillWidth)+((i == widget.selectedIndex) ? iconHorizontalPadding/100 : 0),
188 - curve: Curves.easeOutCubic,
189 - child: InkWell(
190 - splashFactory: NoSplash.splashFactory,
191 - splashColor: Colors.transparent,
192 - borderRadius: BorderRadius.circular(pillBorderRadius),
193 - onTap: () => _onItemTap(i),
194 - child: AnimatedContainer(
195 - duration: _firstFrame
196 - ? Duration.zero
197 - : inactiveIconMoveDuration,
198 - curve: Curves.easeOutCubic,
199 - width:
200 - i == widget.selectedIndex ? pillWidth : iconBoxWidth,
201 - alignment: Alignment.center,
202 - child: AnimatedAlign(
203 - duration: inactiveIconFadeDuration,
162 + child: Padding(
163 + padding: const EdgeInsets.symmetric(horizontal: barHorizontalPadding),
164 + child: Stack(
165 + alignment: Alignment.center,
166 + children: [
167 + AnimatedPill(
168 + left: calcLeft(widget.selectedIndex, pillWidth),
169 + pillColor: pillColor,
170 + currentAction: currentAction,
171 + pillIconHeight: pillIconHeight,
172 + pillIconWidth: pillIconWidth,
173 + pillIconSpacing: pillIconSpacing,
174 + pillBorderRadius: pillBorderRadius,
175 + contentColor: activeColor,
176 + estimateWidthForAction: pillWidth,
177 + pillTextStyle: pillTextStyle,
178 + pillMoveDuration: pillMoveDuration,
179 + pillResizeDuration: pillResizeDuration,
180 + ),
181 + for (int i = 0; i < visibleActions.length; i++)
182 + AnimatedPositioned(
183 + duration: pillResizeDuration,
184 + width: iconBoxWidth,
185 + left: calcLeft(i, pillWidth) +
186 + ((i == widget.selectedIndex)
187 + ? iconHorizontalPadding / 100
188 + : 0),
189 + curve: Curves.easeOutCubic,
190 + child: InkWell(
191 + splashFactory: NoSplash.splashFactory,
192 + splashColor: Colors.transparent,
193 + borderRadius: BorderRadius.circular(pillBorderRadius),
194 + onTap: () => _onItemTap(i),
195 + child: AnimatedContainer(
196 + duration:
197 + _firstFrame ? Duration.zero : inactiveIconMoveDuration,
198 curve: Curves.easeOutCubic,
199 + width: i == widget.selectedIndex ? pillWidth : iconBoxWidth,
200 alignment: Alignment.center,
206 - child: AnimatedScale(
207 - duration: inactiveIconAppearDuration,
201 + child: AnimatedAlign(
202 + duration: inactiveIconFadeDuration,
203 curve: Curves.easeOutCubic,
209 - scale: (i == widget.selectedIndex) ? 0.857 : 1.0,
210 - child: TweenAnimationBuilder<Color?>(
211 - tween: ColorTween(
212 - begin: (i == widget.selectedIndex) ? inactiveColor : activeColor,
213 - end: (i==widget.selectedIndex) ? activeColor : inactiveColor,
214 - ),
215 - duration: iconColorChangeDuration,
216 - builder: (context, value, child) {
217 - return Container(
218 - height: NewMainNavBar.barHeight,
219 - child: CakeImageWidget(imageUrl:
220 - visibleActions[i].image,
204 + alignment: Alignment.center,
205 + child: AnimatedScale(
206 + duration: inactiveIconAppearDuration,
207 + curve: Curves.easeOutCubic,
208 + scale: (i == widget.selectedIndex) ? 0.857 : 1.0,
209 + child: TweenAnimationBuilder<Color?>(
210 + tween: ColorTween(
211 + begin: (i == widget.selectedIndex)
212 + ? inactiveColor
213 + : activeColor,
214 + end: (i == widget.selectedIndex)
215 + ? activeColor
216 + : inactiveColor,
217 + ),
218 + duration: iconColorChangeDuration,
219 + builder: (context, value, child) {
220 + return Container(
221 + height: NewMainNavBar.barHeight,
222 + child: CakeImageWidget(
223 + imageUrl: visibleActions[i].image,
224 width: iconWidth,
225 height: iconHeight,
226 //fit: BoxFit.scaleDown,
@@ -226,23 +229,22 @@ class _NEWNewMainNavBarState extends State<NewMainNavBar> {
229 BlendMode.srcIn,
230 ),
231 ),
229 - );
230 - }
232 + );
233 + }),
234 ),
235 ),
236 ),
237 ),
238 ),
236 - ),
237 - ],
238 - ),
239 - )),
239 + ],
240 + ),
241 + )),
242 + ),
243 ),
244 ),
245 ),
246 ),
244 - ),
245 - );
247 + );
248 },
249 );
250 }
@@ -302,7 +304,8 @@ class AnimatedPill extends StatelessWidget {
304 mainAxisSize: MainAxisSize.min,
305 mainAxisAlignment: MainAxisAlignment.center,
306 children: [
305 - Padding(padding: EdgeInsets.only(left: pillIconWidth + 2),
307 + Padding(
308 + padding: EdgeInsets.only(left: pillIconWidth + 2),
309 child: Text(
310 currentAction.name(context),
311 style: pillTextStyle.copyWith(color: contentColor),
lib/src/screens/dashboard/widgets/order_row.dart
+10 -10
@@ -44,18 +44,18 @@ class OrderRow extends StatelessWidget {
44 children: [
45 _ProviderIcon(path: providerIconPath, title: providerTitle),
46 if (state != null)
47 - Positioned(
48 - right: 0,
49 - bottom: 2,
50 - child: Container(
51 - height: 8,
52 - width: 8,
53 - decoration: BoxDecoration(
54 - color: _statusColor(context, state!),
55 - borderRadius: BorderRadius.circular(12),
47 + Positioned(
48 + right: 0,
49 + bottom: 2,
50 + child: Container(
51 + height: 8,
52 + width: 8,
53 + decoration: BoxDecoration(
54 + color: _statusColor(context, state!),
55 + borderRadius: BorderRadius.circular(12),
56 + ),
57 ),
58 ),
58 - ),
59 ],
60 ),
61 const SizedBox(width: 12),
lib/src/screens/dashboard/widgets/page_indicator.dart
+20 -44
@@ -76,8 +76,7 @@ class _PageIndicatorState extends State<PageIndicator> {
76 );
77 }
78
79 - double _estimateItemWidthForAction(
80 - BuildContext context, PageIndicatorActions action,
79 + double _estimateItemWidthForAction(BuildContext context, PageIndicatorActions action,
80 {Color? color}) {
81 final text = action.name(context);
82 final textPainter = TextPainter(
@@ -86,15 +85,11 @@ class _PageIndicatorState extends State<PageIndicator> {
85 textDirection: Directionality.of(context),
86 textScaler: MediaQuery.of(context).textScaler,
87 )..layout();
89 - return iconWidth +
90 - iconSpacing +
91 - textPainter.width +
92 - pillHorizontalPadding * 2;
88 + return iconWidth + iconSpacing + textPainter.width + pillHorizontalPadding * 2;
89 }
90
91 @override
92 Widget build(BuildContext context) {
97 -
93 final visibleActions = PageIndicatorActions.all.where((action) {
94 return action.isEnabled?.call(widget.dashboardViewModel) ?? true;
95 }).toList();
@@ -127,34 +122,28 @@ class _PageIndicatorState extends State<PageIndicator> {
122 ];
123
124 final totalItemsWidth =
130 - actionWidths.fold(0.0, (sum, width) => sum + width) +
131 - barHorizontalPadding * 2;
125 + actionWidths.fold(0.0, (sum, width) => sum + width) + barHorizontalPadding * 2;
126
127 final barWidth = math.min(totalItemsWidth, screenWidth * 0.95);
128
129 final count = visibleActions.length;
130 final firstLeft = edgePadding;
137 - final secondLeft =
138 - barWidth - (isRTL ? actionWidths.first : actionWidths[1]) - edgePadding;
131 + final secondLeft = barWidth - (isRTL ? actionWidths.first : actionWidths[1]) - edgePadding;
132
133 final List<double> positions;
134
135 if (count == 2) {
136 positions = [firstLeft, secondLeft];
137 } else {
145 - final lastLeft = barWidth -
146 - (isRTL ? actionWidths.first : actionWidths.last) -
147 - edgePadding;
138 + final lastLeft = barWidth - (isRTL ? actionWidths.first : actionWidths.last) - edgePadding;
139
149 - final centerLeft = (isRTL
150 - ? actionWidths.last + edgePadding
151 - : actionWidths.first + edgePadding);
140 + final centerLeft =
141 + (isRTL ? actionWidths.last + edgePadding : actionWidths.first + edgePadding);
142
143 positions = [firstLeft, centerLeft, lastLeft];
144 }
145
156 - final left =
157 - (isRTL ? positions.reversed.toList() : positions)[selectedIndex];
146 + final left = (isRTL ? positions.reversed.toList() : positions)[selectedIndex];
147 final currentAction = visibleActions[selectedIndex];
148
149 return Align(
@@ -191,8 +180,7 @@ class _PageIndicatorState extends State<PageIndicator> {
180 pillResizeDuration: pillResizeDuration,
181 ),
182 Padding(
194 - padding: const EdgeInsets.symmetric(
195 - horizontal: barHorizontalPadding),
183 + padding: const EdgeInsets.symmetric(horizontal: barHorizontalPadding),
184 child: Row(
185 mainAxisAlignment: MainAxisAlignment.spaceBetween,
186 children: [
@@ -210,47 +198,36 @@ class _PageIndicatorState extends State<PageIndicator> {
198 height: barHeight,
199 width: i == selectedIndex
200 ? pillWidth
213 - : _estimateItemWidthForAction(
214 - context, visibleActions[i]),
201 + : _estimateItemWidthForAction(context, visibleActions[i]),
202 alignment: Alignment.center,
203 child: Row(
204 mainAxisSize: MainAxisSize.min,
205 children: [
206 TweenAnimationBuilder<Color?>(
220 - duration: const Duration(
221 - milliseconds: 300),
207 + duration: const Duration(milliseconds: 300),
208 curve: Curves.easeOutCubic,
209 tween: ColorTween(
210 begin: inactiveColor,
225 - end: i == selectedIndex
226 - ? activeColor
227 - : inactiveColor,
211 + end: i == selectedIndex ? activeColor : inactiveColor,
212 ),
229 - builder: (context, color, _) =>
230 - SvgPicture.asset(
213 + builder: (context, color, _) => SvgPicture.asset(
214 visibleActions[i].image,
215 width: iconWidth,
216 height: iconHeight,
234 - colorFilter: ColorFilter.mode(
235 - color!, BlendMode.srcIn),
217 + colorFilter: ColorFilter.mode(color!, BlendMode.srcIn),
218 ),
219 ),
220 SizedBox(width: iconSpacing),
221 TweenAnimationBuilder<Color?>(
240 - duration: const Duration(
241 - milliseconds: 300),
222 + duration: const Duration(milliseconds: 300),
223 curve: Curves.easeOutCubic,
224 tween: ColorTween(
225 begin: inactiveColor,
245 - end: i == selectedIndex
246 - ? activeColor
247 - : inactiveColor,
226 + end: i == selectedIndex ? activeColor : inactiveColor,
227 ),
249 - builder: (context, color, _) =>
250 - Text(
228 + builder: (context, color, _) => Text(
229 visibleActions[i].name(context),
252 - style: textStyle.copyWith(
253 - color: color),
230 + style: textStyle.copyWith(color: color),
231 overflow: TextOverflow.fade,
232 softWrap: false,
233 ),
@@ -315,9 +292,8 @@ class AnimatedPill extends StatelessWidget {
292 duration: pillResizeDuration,
293 curve: Curves.easeOutCubic,
294 width: estimateWidthForAction,
318 - decoration: BoxDecoration(
319 - color: pillColor,
320 - borderRadius: BorderRadius.circular(pillBorderRadius)),
295 + decoration:
296 + BoxDecoration(color: pillColor, borderRadius: BorderRadius.circular(pillBorderRadius)),
297 clipBehavior: Clip.hardEdge,
298 alignment: Alignment.center,
299 ),
lib/src/screens/dashboard/widgets/sign_form.dart
+4 -6
@@ -18,7 +18,7 @@ class SignForm extends StatefulWidget {
18 final WalletType type;
19 final bool includeAddress;
20 final int? chainId;
21 -
21 +
22 @override
23 SignFormState createState() => SignFormState();
24 }
@@ -66,15 +66,13 @@ class SignFormState extends State<SignForm> with AutomaticKeepAliveClientMixin {
66 const SizedBox(height: 20),
67 AddressTextField(
68 controller: addressController,
69 - options: [
70 - AddressTextFieldOption.paste,
71 - AddressTextFieldOption.walletAddresses
72 - ],
69 + options: [AddressTextFieldOption.paste, AddressTextFieldOption.walletAddresses],
70 buttonColor: Theme.of(context).colorScheme.surfaceContainerHighest,
71 onSelectedContact: (contact) {
72 addressController.text = contact.address;
73 },
77 - selectedCurrency: walletTypeToCryptoCurrency(widget.type, chainId: widget.chainId),
74 + selectedCurrency:
75 + walletTypeToCryptoCurrency(widget.type, chainId: widget.chainId),
76 fillColor: Theme.of(context).colorScheme.surface,
77 ),
78 ],
lib/src/screens/dashboard/widgets/solana_nft_tile_widget.dart
+7 -7
@@ -61,9 +61,9 @@ class SolanaNFTTileWidget extends StatelessWidget {
61 Text(
62 'Symbol: ${nftAsset.symbol ?? '---'}',
63 style: Theme.of(context).textTheme.bodySmall?.copyWith(
64 - color: Theme.of(context).colorScheme.onSurfaceVariant,
65 - height: 1,
66 - ),
64 + color: Theme.of(context).colorScheme.onSurfaceVariant,
65 + height: 1,
66 + ),
67 ),
68 const SizedBox(height: 8),
69 Text(
@@ -71,10 +71,10 @@ class SolanaNFTTileWidget extends StatelessWidget {
71 ? nftAsset.name!
72 : (nftAsset.symbol ?? '---'),
73 style: Theme.of(context).textTheme.titleLarge?.copyWith(
74 - fontWeight: FontWeight.w900,
75 - color: Theme.of(context).colorScheme.onSurface,
76 - height: 1,
77 - ),
74 + fontWeight: FontWeight.w900,
75 + color: Theme.of(context).colorScheme.onSurface,
76 + height: 1,
77 + ),
78 ),
79 ],
80 ),
lib/src/screens/dashboard/widgets/sync_indicator.dart
+2 -1
@@ -20,7 +20,8 @@ class SyncIndicator extends StatelessWidget {
20 return Observer(builder: (_) {
21 final syncIndicatorWidth = 237.0;
22 final status = dashboardViewModel.status;
23 - final statusText = syncStatusTitle(status, dashboardViewModel.settingsStore.syncStatusDisplayMode);
23 + final statusText =
24 + syncStatusTitle(status, dashboardViewModel.settingsStore.syncStatusDisplayMode);
25 final progress = status.progress();
26 final indicatorOffset = progress * syncIndicatorWidth;
27 final indicatorWidth = progress < 1
lib/src/screens/dashboard/widgets/transaction_raw.dart
+9 -8
@@ -42,13 +42,14 @@ class TransactionRow extends StatelessWidget {
42 shape: BoxShape.circle,
43 color: Theme.of(context).colorScheme.surfaceContainerHighest,
44 ),
45 - child: (isShield) ? Padding(
46 - padding: const EdgeInsets.all(8.0),
47 - child: SvgPicture.asset('assets/images/tx_shield.svg'),
48 - ) :
49 - Image.asset(direction == TransactionDirection.incoming
50 - ? 'assets/images/down_arrow.png'
51 - : 'assets/images/up_arrow.png'),
45 + child: (isShield)
46 + ? Padding(
47 + padding: const EdgeInsets.all(8.0),
48 + child: SvgPicture.asset('assets/images/tx_shield.svg'),
49 + )
50 + : Image.asset(direction == TransactionDirection.incoming
51 + ? 'assets/images/down_arrow.png'
52 + : 'assets/images/up_arrow.png'),
53 ),
54 SizedBox(width: 12),
55 Expanded(
@@ -66,7 +67,7 @@ class TransactionRow extends StatelessWidget {
67 title,
68 style: Theme.of(context).textTheme.bodyLarge?.copyWith(
69 fontWeight: FontWeight.w600,
69 - overflow: TextOverflow.fade,
70 + overflow: TextOverflow.fade,
71 ),
72 ),
73 ),
lib/src/screens/dashboard/widgets/verify_form.dart
+1 -1
@@ -13,7 +13,7 @@ class VerifyForm extends StatefulWidget {
13
14 final WalletType type;
15 final int? chainId;
16 -
16 +
17 @override
18 VerifyFormState createState() => VerifyFormState();
19 }
lib/src/screens/dev/moneroc_cache_debug.dart
+20 -25
@@ -100,7 +100,8 @@ class JsonExplorerPage extends StatelessWidget {
100 final appDir = await getAppDir();
101 final filePath = appDir.path + '/.json_dump_temp.json';
102 await File(filePath).writeAsString(jsonString);
103 - await ShareUtil.shareFile(filePath: filePath, fileName: path.basename(filePath), context: context);
103 + await ShareUtil.shareFile(
104 + filePath: filePath, fileName: path.basename(filePath), context: context);
105 } catch (e) {
106 ScaffoldMessenger.of(context).showSnackBar(
107 SnackBar(content: Text('Failed to share file: $e')),
@@ -143,11 +144,11 @@ class _JsonExplorerState extends State<JsonExplorer> {
144
145 void _buildItemList() {
146 _allItems.clear();
146 -
147 +
148 if (widget.data is Map) {
149 final map = widget.data as Map<String, dynamic>;
150 final sortedKeys = map.keys.toList()..sort();
150 -
151 +
152 for (final key in sortedKeys) {
153 _allItems.add(CacheItem(
154 key: key,
@@ -165,7 +166,7 @@ class _JsonExplorerState extends State<JsonExplorer> {
166 ));
167 }
168 }
168 -
169 +
170 _applyFilter();
171 }
172
@@ -175,7 +176,7 @@ class _JsonExplorerState extends State<JsonExplorer> {
176 } else {
177 _filteredItems = _allItems.where((item) {
178 return item.displayKey.toLowerCase().contains(_searchQuery.toLowerCase()) ||
178 - _valueContainsSearch(item.value, _searchQuery.toLowerCase());
179 + _valueContainsSearch(item.value, _searchQuery.toLowerCase());
180 }).toList();
181 }
182 }
@@ -210,10 +211,10 @@ class _JsonExplorerState extends State<JsonExplorer> {
211 @override
212 Widget build(BuildContext context) {
213 final theme = Theme.of(context);
213 - final totalItems = widget.data is Map
214 - ? (widget.data as Map).length
215 - : widget.data is List
216 - ? (widget.data as List).length
214 + final totalItems = widget.data is Map
215 + ? (widget.data as Map).length
216 + : widget.data is List
217 + ? (widget.data as List).length
218 : 0;
219
220 return Column(
@@ -230,9 +231,7 @@ class _JsonExplorerState extends State<JsonExplorer> {
231 prefixIcon: const Icon(Icons.search),
232 border: const OutlineInputBorder(),
233 isDense: true,
233 - suffixText: _searchQuery.isNotEmpty
234 - ? '${_filteredItems.length} found'
235 - : null,
234 + suffixText: _searchQuery.isNotEmpty ? '${_filteredItems.length} found' : null,
235 ),
236 onChanged: (value) {
237 setState(() {
@@ -245,7 +244,6 @@ class _JsonExplorerState extends State<JsonExplorer> {
244 ],
245 ),
246 ),
248 -
247 Expanded(
248 child: _filteredItems.isEmpty && _searchQuery.isNotEmpty
249 ? Center(
@@ -311,11 +309,11 @@ class CacheItemTile extends StatelessWidget {
309 Color _getTypeColor(BuildContext context, dynamic value) {
310 final theme = Theme.of(context);
311 final isDark = theme.brightness == Brightness.dark;
314 -
312 +
313 if (value == null) {
314 return Colors.grey;
315 }
318 -
316 +
317 switch (value.runtimeType) {
318 case String:
319 return Colors.green;
@@ -337,22 +335,22 @@ class CacheItemTile extends StatelessWidget {
335
336 String _getValuePreview(dynamic value) {
337 if (value == null) return 'null';
340 -
338 +
339 if (value is Map) {
340 return '{${value.length} items}';
341 }
344 -
342 +
343 if (value is List) {
344 return '[${value.length} items]';
345 }
348 -
346 +
347 if (value is String) {
348 if (value.length > 100) {
349 return '"${value.substring(0, 97)}..."';
350 }
351 return '"$value"';
352 }
355 -
353 +
354 final str = value.toString();
355 if (str.length > 100) {
356 return '${str.substring(0, 97)}...';
@@ -407,9 +405,7 @@ class CacheItemTile extends StatelessWidget {
405 margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
406 child: ListTile(
407 leading: Icon(
410 - canNavigate
411 - ? (item.value is Map ? Icons.folder : Icons.list)
412 - : Icons.description,
408 + canNavigate ? (item.value is Map ? Icons.folder : Icons.list) : Icons.description,
409 color: _getTypeColor(context, item.value),
410 ),
411 title: _buildHighlightedText(
@@ -433,8 +429,7 @@ class CacheItemTile extends StatelessWidget {
429 icon: const Icon(Icons.copy, size: 18),
430 tooltip: 'Copy ${item.displayKey}',
431 ),
436 - if (canNavigate)
437 - const Icon(Icons.chevron_right),
432 + if (canNavigate) const Icon(Icons.chevron_right),
433 ],
434 ),
435 onTap: canNavigate ? onTap : null,
@@ -442,4 +437,4 @@ class CacheItemTile extends StatelessWidget {
437 ),
438 );
439 }
445 -}
\ No newline at end of file
440 +}
lib/src/screens/dev/moneroc_call_profiler.dart
+8 -17
@@ -24,8 +24,6 @@ class DevMoneroCallProfilerPage extends BasePage {
24 }
25 }
26
27 -
28 -
27 class PerformanceDebug extends StatefulWidget {
28 const PerformanceDebug({super.key});
29
@@ -68,7 +66,7 @@ class _PerformanceDebugState extends State<PerformanceDebug> {
66 return debugCallLength["MONERO_Wallet_init"]!.last;
67 }
68
71 -late final String perfInfo = """
69 + late final String perfInfo = """
70 ---- Performance tuning
71 This page lists all calls that take place during the app runtime.-
72 As per Flutter docs we can read:
@@ -93,8 +91,8 @@ min: fastest execution (% of frame)
91 max: slowest execution (% of frame)
92 95th: 95% of the time, the function is faster than this amount of time (% of frame)
93 """
96 - .split("-\n")
97 - .join(" ");
94 + .split("-\n")
95 + .join(" ");
96
97 late final frameTime = 8333;
98 late final frameGreenTier = frameTime ~/ 100;
@@ -113,7 +111,6 @@ max: slowest execution (% of frame)
111 return Colors.red;
112 }
113
116 -
114 @override
115 void initState() {
116 super.initState();
@@ -144,9 +141,7 @@ max: slowest execution (% of frame)
141 ],
142 ));
143 final keys = debugCallLength.keys.toList();
147 - keys.sort((s1, s2) =>
148 - _n95th(debugCallLength[s2]!) -
149 - _n95th(debugCallLength[s1]!));
144 + keys.sort((s1, s2) => _n95th(debugCallLength[s2]!) - _n95th(debugCallLength[s1]!));
145 for (var key in keys) {
146 final value = debugCallLength[key];
147 if (value == null) continue;
@@ -172,14 +167,10 @@ max: slowest execution (% of frame)
167 const Spacer(),
168 cw("${_str(total / 1000)}ms", perfc(total)),
169 ]),
175 - cw("average: ${_str(avg)}µs (~${_str(avg / (frameTime))}f)",
176 - perfc(avg)),
177 - cw("min: $minµs (~${_str(min / (frameTime) * 100)})",
178 - perfc(min)),
179 - cw("max: $maxµs (~${_str(max / (frameTime) * 100)}%)",
180 - perfc(max)),
181 - cw("95th: $npµs (~${_str(np / (frameTime) * 100)}%)",
182 - perfc(np)),
170 + cw("average: ${_str(avg)}µs (~${_str(avg / (frameTime))}f)", perfc(avg)),
171 + cw("min: $minµs (~${_str(min / (frameTime) * 100)})", perfc(min)),
172 + cw("max: $maxµs (~${_str(max / (frameTime) * 100)}%)", perfc(max)),
173 + cw("95th: $npµs (~${_str(np / (frameTime) * 100)}%)", perfc(np)),
174 ],
175 ),
176 ),
lib/src/screens/dev/network_requests.dart
+25 -33
@@ -75,14 +75,16 @@ class DevNetworkRequests extends BasePage {
75 RequestMethod.delete => Text("DELETE"),
76 RequestMethod.newHttpClient ||
77 RequestMethod.newHttpIOClient ||
78 - RequestMethod.newProxySocket => null,
78 + RequestMethod.newProxySocket =>
79 + null,
80 },
81 title: Text(item.time.toIso8601String()),
82 subtitle: switch (item.method) {
83 RequestMethod.get ||
84 RequestMethod.post ||
85 RequestMethod.put ||
85 - RequestMethod.delete => Text("${item.uri}"),
86 + RequestMethod.delete =>
87 + Text("${item.uri}"),
88 RequestMethod.newHttpClient => Text("newHttpClient"),
89 RequestMethod.newHttpIOClient => Text("newHttpIOClient"),
90 RequestMethod.newProxySocket => Text("newProxySocket"),
@@ -115,35 +117,26 @@ class DevRequestDetails extends BasePage {
117 children: [
118 _sectionTitle("Time"),
119 SelectableText(req.time.toString()),
118 -
120 _sectionTitle("Method"),
121 SelectableText(req.method.toString()),
121 -
122 _sectionTitle("URI"),
123 SelectableText(req.uri?.toString() ?? "null"),
124 -
124 _sectionTitle("Network"),
125 SelectableText(req.network.toString()),
127 -
128 - if (req.network == RequestNetwork.tor)
129 - ...[
130 - _sectionTitle("Tor socks server"),
131 - SelectableText(CakeTor.instance.runtimeType.toString()),
132 - _sectionTitle("Tor socks details"),
133 - SelectableText(CakeTor.instance.toString()),
134 - ],
135 -
126 + if (req.network == RequestNetwork.tor) ...[
127 + _sectionTitle("Tor socks server"),
128 + SelectableText(CakeTor.instance.runtimeType.toString()),
129 + _sectionTitle("Tor socks details"),
130 + SelectableText(CakeTor.instance.toString()),
131 + ],
132 _sectionTitle("Body (as UTF-8)"),
133 SelectableText(_tryDecodeBody(req.body)),
134 _buildJsonExplorer(context, _tryDecodeBody(req.body)),
139 -
135 _sectionTitle("Response"),
136 SelectableText(req.response?.body ?? "null"),
137 _buildJsonExplorer(context, req.response?.body ?? "{}"),
143 -
138 _sectionTitle("Error"),
139 SelectableText(req.error ?? "No error"),
146 -
140 _sectionTitle("Stack Trace"),
141 SelectableText(req.trace.toString()),
142 ],
@@ -152,22 +145,21 @@ class DevRequestDetails extends BasePage {
145
146 Widget _buildJsonExplorer(BuildContext context, String body) {
147 try {
155 - final jsonData = json.decode(body);
156 - return PrimaryButton(
157 - text: "View JSON",
158 - color: Colors.blue,
159 - textColor: Colors.white,
160 - onPressed: () {
161 - Navigator.of(context).push(
162 - MaterialPageRoute(
163 - builder: (context) {
164 - return JsonExplorerPage(data: jsonData, title: "body");
165 - },
166 - ),
167 - );
168 - },
169 - );
170 -
148 + final jsonData = json.decode(body);
149 + return PrimaryButton(
150 + text: "View JSON",
151 + color: Colors.blue,
152 + textColor: Colors.white,
153 + onPressed: () {
154 + Navigator.of(context).push(
155 + MaterialPageRoute(
156 + builder: (context) {
157 + return JsonExplorerPage(data: jsonData, title: "body");
158 + },
159 + ),
160 + );
161 + },
162 + );
163 } catch (e) {
164 return SelectableText("Invalid JSON: $e");
165 }
lib/src/screens/dev/qr_tools_page.dart
+8 -9
@@ -19,21 +19,20 @@ class DevQRToolsPage extends BasePage {
19 mainAxisSize: MainAxisSize.min,
20 children: [
21 TextField(
22 - controller: textCtrl,
23 - maxLines: 8,
24 - onChanged: (value) {
25 - viewModel.input = value;
26 - }
27 - ),
22 + controller: textCtrl,
23 + maxLines: 8,
24 + onChanged: (value) {
25 + viewModel.input = value;
26 + }),
27 Observer(
28 builder: (_) {
29 return Expanded(
31 - child: JsonExplorer(data: viewModel.data, title: "result"),
32 - );
30 + child: JsonExplorer(data: viewModel.data, title: "result"),
31 + );
32 },
33 ),
34 ],
35 ),
36 );
37 }
39 -}
\ No newline at end of file
38 +}
lib/src/screens/dev/secure_preferences_page.dart
+14 -8
@@ -38,10 +38,14 @@ class DevSecurePreferencesPage extends BasePage {
38 Clipboard.setData(ClipboardData(text: key + ": " + values[key].toString()));
39 },
40 title: switch (type) {
41 - PreferenceType.bool => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.blue)),
42 - PreferenceType.int => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.green)),
43 - PreferenceType.double => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.yellow)),
44 - PreferenceType.listString => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.purple)),
41 + PreferenceType.bool => Text(key,
42 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.blue)),
43 + PreferenceType.int => Text(key,
44 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.green)),
45 + PreferenceType.double => Text(key,
46 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.yellow)),
47 + PreferenceType.listString => Text(key,
48 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.purple)),
49 PreferenceType.string => Text(key),
50 PreferenceType.unknown => Text(key),
51 },
@@ -49,9 +53,12 @@ class DevSecurePreferencesPage extends BasePage {
53 PreferenceType.bool => Text("bool: ${values[key]}"),
54 PreferenceType.int => Text("int: ${values[key]}"),
55 PreferenceType.double => Text("double: ${values[key]}"),
52 - PreferenceType.listString => values[key].isEmpty as bool ? Text("listString: []") : Text("listString:\n- ${values[key].join("\n- ")}"),
56 + PreferenceType.listString => values[key].isEmpty as bool
57 + ? Text("listString: []")
58 + : Text("listString:\n- ${values[key].join("\n- ")}"),
59 PreferenceType.string => Text("string: ${values[key]}"),
54 - PreferenceType.unknown => Text("UNKNOWN(${values[key].runtimeType}): ${values[key]}"),
60 + PreferenceType.unknown =>
61 + Text("UNKNOWN(${values[key].runtimeType}): ${values[key]}"),
62 },
63 );
64 },
@@ -59,5 +66,4 @@ class DevSecurePreferencesPage extends BasePage {
66 },
67 );
68 }
62 -
63 -}
\ No newline at end of file
69 +}
lib/src/screens/dev/shared_preferences_page.dart
+40 -33
@@ -50,10 +50,14 @@ class DevSharedPreferencesPage extends BasePage {
50 _showEditDialog(context, key, type, values[key]);
51 },
52 title: switch (type) {
53 - PreferenceType.bool => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.blue)),
54 - PreferenceType.int => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.green)),
55 - PreferenceType.double => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.yellow)),
56 - PreferenceType.listString => Text(key, style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.purple)),
53 + PreferenceType.bool => Text(key,
54 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.blue)),
55 + PreferenceType.int => Text(key,
56 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.green)),
57 + PreferenceType.double => Text(key,
58 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.yellow)),
59 + PreferenceType.listString => Text(key,
60 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(color: Colors.purple)),
61 PreferenceType.string => Text(key),
62 PreferenceType.unknown => Text(key),
63 },
@@ -61,9 +65,12 @@ class DevSharedPreferencesPage extends BasePage {
65 PreferenceType.bool => Text("bool: ${values[key]}"),
66 PreferenceType.int => Text("int: ${values[key]}"),
67 PreferenceType.double => Text("double: ${values[key]}"),
64 - PreferenceType.listString => values[key].isEmpty as bool ? Text("listString: []") : Text("listString:\n- ${values[key].join("\n- ")}"),
68 + PreferenceType.listString => values[key].isEmpty as bool
69 + ? Text("listString: []")
70 + : Text("listString:\n- ${values[key].join("\n- ")}"),
71 PreferenceType.string => Text("string: ${values[key]}"),
66 - PreferenceType.unknown => Text("UNKNOWN(${values[key].runtimeType}): ${values[key]}"),
72 + PreferenceType.unknown =>
73 + Text("UNKNOWN(${values[key].runtimeType}): ${values[key]}"),
74 },
75 );
76 },
@@ -72,12 +79,14 @@ class DevSharedPreferencesPage extends BasePage {
79 );
80 }
81
75 - void _showEditDialog(BuildContext context, String key, PreferenceType type, dynamic currentValue) {
82 + void _showEditDialog(
83 + BuildContext context, String key, PreferenceType type, dynamic currentValue) {
84 dynamic newValue = currentValue;
85 bool isListString = type == PreferenceType.listString;
78 - List<String> listItems = isListString ? List<String>.from(currentValue as Iterable<dynamic>) : [];
79 - TextEditingController textController = TextEditingController(
80 - text: isListString ? '' : currentValue?.toString() ?? '');
86 + List<String> listItems =
87 + isListString ? List<String>.from(currentValue as Iterable<dynamic>) : [];
88 + TextEditingController textController =
89 + TextEditingController(text: isListString ? '' : currentValue?.toString() ?? '');
90
91 showDialog(
92 context: context,
@@ -91,10 +100,10 @@ class DevSharedPreferencesPage extends BasePage {
100 height: double.maxFinite,
101 child: SingleChildScrollView(
102 child: _buildDialogContent(
94 - type,
95 - newValue,
96 - listItems,
97 - textController,
103 + type,
104 + newValue,
105 + listItems,
106 + textController,
107 (value) => setState(() => newValue = value),
108 (items) => setState(() => listItems = items),
109 ),
@@ -116,12 +125,7 @@ class DevSharedPreferencesPage extends BasePage {
125 child: Text('Save'),
126 onPressed: () async {
127 if (_validateAndUpdateValue(
119 - context,
120 - type,
121 - textController,
122 - listItems,
123 - (value) => newValue = value
124 - )) {
128 + context, type, textController, listItems, (value) => newValue = value)) {
129 await viewModel.set(key, type, newValue);
130 Navigator.of(context).pop();
131 }
@@ -210,9 +214,8 @@ class DevSharedPreferencesPage extends BasePage {
214 BaseTextFormField(
215 controller: controller,
216 hintText: label,
213 - keyboardType: isInteger
214 - ? TextInputType.number
215 - : TextInputType.numberWithOptions(decimal: true),
217 + keyboardType:
218 + isInteger ? TextInputType.number : TextInputType.numberWithOptions(decimal: true),
219 inputFormatters: isInteger
220 ? [FilteringTextInputFormatter.digitsOnly]
221 : [FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d*$'))],
@@ -222,7 +225,7 @@ class DevSharedPreferencesPage extends BasePage {
225 }
226
227 Widget _buildListEditor(
225 - List<String> items,
228 + List<String> items,
229 TextEditingController controller,
230 Function(List<String>) onListChanged,
231 ) {
@@ -358,7 +361,8 @@ class DevSharedPreferencesPage extends BasePage {
361 DropdownMenuItem(value: PreferenceType.bool, child: Text('Boolean')),
362 DropdownMenuItem(value: PreferenceType.int, child: Text('Integer')),
363 DropdownMenuItem(value: PreferenceType.double, child: Text('Double')),
361 - DropdownMenuItem(value: PreferenceType.listString, child: Text('List of Strings')),
364 + DropdownMenuItem(
365 + value: PreferenceType.listString, child: Text('List of Strings')),
366 ],
367 onChanged: (value) {
368 if (value != null) {
@@ -384,14 +388,17 @@ class DevSharedPreferencesPage extends BasePage {
388 return;
389 }
390
387 - viewModel.set(keyController.text, selectedType, switch (selectedType) {
388 - PreferenceType.bool => false,
389 - PreferenceType.int => 0,
390 - PreferenceType.double => 0.0,
391 - PreferenceType.string => '',
392 - PreferenceType.listString => [],
393 - PreferenceType.unknown => null,
394 - });
391 + viewModel.set(
392 + keyController.text,
393 + selectedType,
394 + switch (selectedType) {
395 + PreferenceType.bool => false,
396 + PreferenceType.int => 0,
397 + PreferenceType.double => 0.0,
398 + PreferenceType.string => '',
399 + PreferenceType.listString => [],
400 + PreferenceType.unknown => null,
401 + });
402 Navigator.of(context).pop();
403 },
404 ),
lib/src/screens/disclaimer/disclaimer_page.dart
+1 -1
@@ -147,7 +147,7 @@ class DisclaimerBodyState extends State<DisclaimerPageBody> {
147 EdgeInsets.only(left: 24.0, top: 10.0, right: 24.0, bottom: 10.0),
148 child: InkWell(
149 key: ValueKey('disclaimer_check_key'),
150 - onTap: () => setState(() =>_checked = !_checked),
150 + onTap: () => setState(() => _checked = !_checked),
151 child: Row(
152 mainAxisAlignment: MainAxisAlignment.start,
153 children: <Widget>[
lib/src/screens/exchange/exchange_page.dart
+7 -3
@@ -40,7 +40,8 @@ import 'package:cake_wallet/src/screens/exchange/widgets/present_provider_picker
40 import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.dart';
41
42 class ExchangePage extends BasePage {
43 - ExchangePage(this.exchangeViewModel, this.authService, this.adrResService, this.initialPaymentRequest) {
43 + ExchangePage(
44 + this.exchangeViewModel, this.authService, this.adrResService, this.initialPaymentRequest) {
45 depositWalletName = exchangeViewModel.depositCurrency == CryptoCurrency.xmr
46 ? exchangeViewModel.wallet.name
47 : null;
@@ -655,8 +656,11 @@ class ExchangePage extends BasePage {
656
657 Future<String> fetchParsedAddress(
658 BuildContext context, String domain, CryptoCurrency currency) async {
658 - final parsedAddresses = await adrResService.resolve(query: domain, wallet:exchangeViewModel.wallet, currency: currency);
659 - return parsedAddresses.isNotEmpty ? parsedAddresses.first.parsedAddressByCurrencyMap[currency] ?? '' : '';
659 + final parsedAddresses = await adrResService.resolve(
660 + query: domain, wallet: exchangeViewModel.wallet, currency: currency);
661 + return parsedAddresses.isNotEmpty
662 + ? parsedAddresses.first.parsedAddressByCurrencyMap[currency] ?? ''
663 + : '';
664 }
665
666 void _showFeeAlert(BuildContext context) async {
lib/src/screens/exchange/widgets/currency_picker_widget.dart
+1 -1
@@ -39,7 +39,7 @@ class CurrencyPickerWidget extends StatelessWidget {
39 pickListItem(index);
40 },
41 title: pickerItemsList[index].name,
42 - iconPath: pickerItemsList[index].iconPath,
42 + iconPath: pickerItemsList[index].iconPath,
43 tag: pickerItemsList[index].tag,
44 );
45 }),
lib/src/screens/exchange/widgets/mobile_exchange_cards_section.dart
+2 -2
@@ -86,7 +86,7 @@ class _BuySellOptionButtonsState extends State<BuySellOptionButtons> {
86 Expanded(
87 flex: 5,
88 child: SelectButton(
89 - center:true,
89 + center: true,
90 height: 44,
91 text: S.of(context).buy,
92 isSelected: isBuySelected,
@@ -108,7 +108,7 @@ class _BuySellOptionButtonsState extends State<BuySellOptionButtons> {
108 Expanded(
109 flex: 5,
110 child: SelectButton(
111 - center:true,
111 + center: true,
112 height: 44,
113 text: S.of(context).sell,
114 isSelected: !isBuySelected,
lib/src/screens/exchange/widgets/picker_item.dart
+1 -4
@@ -1,9 +1,6 @@
1 class PickerItem<T> {
2 PickerItem(this.original,
3 - {required this.title,
4 - required this.iconPath,
5 - required this.tag,
6 - required this.description});
3 + {required this.title, required this.iconPath, required this.tag, required this.description});
4
5 final String title;
6 final String iconPath;
lib/src/screens/exchange_trade/exchange_trade_external_send_page.dart
+4 -2
@@ -72,7 +72,8 @@ class ExchangeTradeExternalSendPage extends BasePage {
72 context,
73 Routes.fullscreenQR,
74 arguments: QrViewData(
75 - embeddedImagePath: exchangeTradeViewModel.trade.from?.iconPath,
75 + embeddedImagePath:
76 + exchangeTradeViewModel.trade.from?.iconPath,
77 data: exchangeTradeViewModel.paymentUri?.toString() ??
78 exchangeTradeViewModel.trade.inputAddress ??
79 fetchingLabel,
@@ -96,7 +97,8 @@ class ExchangeTradeExternalSendPage extends BasePage {
97 data: exchangeTradeViewModel.paymentUri?.toString() ??
98 exchangeTradeViewModel.trade.inputAddress ??
99 fetchingLabel,
99 - embeddedImagePath: exchangeTradeViewModel.trade.from?.iconPath,
100 + embeddedImagePath:
101 + exchangeTradeViewModel.trade.from?.iconPath,
102 size: 230,
103 ),
104 ),
lib/src/screens/exchange_trade/exchange_trade_item.dart
+1 -1
@@ -12,4 +12,4 @@ class ExchangeTradeItem {
12 bool isCopied;
13 bool isReceiveDetail;
14 bool isExternalSendDetail;
15 -}
\ No newline at end of file
15 +}
lib/src/screens/exchange_trade/exchange_trade_page.dart
+12 -7
@@ -177,7 +177,6 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
177 ? Theme.of(context).colorScheme.onSecondaryContainer
178 : Theme.of(context).colorScheme.onPrimary,
179 ),
180 -
180 SizedBox(height: 16),
181 Observer(
182 builder: (_) {
@@ -297,12 +296,17 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
296 final isSwapsXyz = trade.provider == ExchangeProviderDescription.swapsXyz;
297 final isEVMWallet = widget.exchangeTradeViewModel.sendViewModel.isEVMWallet;
298
300 - final amountValue = isSwapsXyz && isEVMWallet && !widget.exchangeTradeViewModel.isSwapsXYZCanSendFromExternal
299 + final amountValue = isSwapsXyz &&
300 + isEVMWallet &&
301 + !widget.exchangeTradeViewModel.isSwapsXYZCanSendFromExternal
302 ? trade.amount
303 : widget.exchangeTradeViewModel.sendViewModel.pendingTransaction!.amountFormatted;
304
304 - final fiatAmountValue = isSwapsXyz && isEVMWallet && !widget.exchangeTradeViewModel.isSwapsXYZCanSendFromExternal
305 - ? widget.exchangeTradeViewModel.sendViewModel.calculateTransactionFiatAmount(amountValue)
305 + final fiatAmountValue = isSwapsXyz &&
306 + isEVMWallet &&
307 + !widget.exchangeTradeViewModel.isSwapsXYZCanSendFromExternal
308 + ? widget.exchangeTradeViewModel.sendViewModel
309 + .calculateTransactionFiatAmount(amountValue)
310 : widget.exchangeTradeViewModel.sendViewModel.pendingTransactionFiatAmountFormatted;
311
312 if (context.mounted) {
@@ -328,12 +332,13 @@ class ExchangeTradeState extends State<ExchangeTradeForm> {
332 fee: isEVMCompatibleChain(sendVM.walletType)
333 ? S.of(bottomSheetContext).send_estimated_fee
334 : S.of(bottomSheetContext).send_fee,
331 - feeValue: sendVM.amountParsingProxy.asDisplayStringWithSymbol(
332 - sendVM.pendingTransaction!.fee),
335 + feeValue: sendVM.amountParsingProxy
336 + .asDisplayStringWithSymbol(sendVM.pendingTransaction!.fee),
337 feeFiatAmount: sendVM.pendingTransactionFeeFiatAmountFormatted,
338 outputs: sendVM.outputs,
339 onSlideActionComplete: () async {
336 - if (bottomSheetContext.mounted && Navigator.canPop(bottomSheetContext)) Navigator.of(bottomSheetContext).pop(true);
340 + if (bottomSheetContext.mounted && Navigator.canPop(bottomSheetContext))
341 + Navigator.of(bottomSheetContext).pop(true);
342
343 sendVM.commitTransaction(context);
344 },
lib/src/screens/exchange_trade/widgets/timer_widget.dart
+3 -3
@@ -59,9 +59,9 @@ class TimerWidgetState extends State<TimerWidget> {
59 ? Text(
60 S.of(context).expired,
61 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
62 - fontWeight: FontWeight.w500,
63 - color: Theme.of(context).colorScheme.errorContainer,
64 - ),
62 + fontWeight: FontWeight.w500,
63 + color: Theme.of(context).colorScheme.errorContainer,
64 + ),
65 )
66 : Text(
67 S.of(context).time(_minutes.toString(), _seconds.toString()),
lib/src/screens/integrations/deuro/savings_page.dart
+2 -4
@@ -149,7 +149,7 @@ class DEuroSavingsPage extends BasePage {
149 await _requireHardwareWallet(context);
150 _dEuroViewModel.prepareSavingsEdit(amount, false);
151 }
152 - _editSheetIsOpen = false;
152 + _editSheetIsOpen = false;
153 }
154
155 Future<void> _onReinvestInterest(BuildContext context) async {
@@ -425,9 +425,7 @@ class DEuroSavingsPage extends BasePage {
425 balanceTitle: isAdding
426 ? S.of(context).deuro_savings_available_to_add
427 : S.of(context).deuro_savings_available_to_remove,
428 - balance: isAdding
429 - ? _dEuroViewModel.accountBalance
430 - : _dEuroViewModel.savingsBalance,
428 + balance: isAdding ? _dEuroViewModel.accountBalance : _dEuroViewModel.savingsBalance,
429 footerType: FooterType.none,
430 maxHeight: MediaQuery.of(context).size.height * 0.8,
431 ),
lib/src/screens/integrations/deuro/widgets/numpad.dart
+6 -8
@@ -25,8 +25,7 @@ class NumberPad extends StatelessWidget {
25 return onDeletePressed();
26 }
27
28 - if ([".", ","].contains(keyEvent.logicalKey.keyLabel) &&
29 - onDecimalPressed != null) {
28 + if ([".", ","].contains(keyEvent.logicalKey.keyLabel) && onDecimalPressed != null) {
29 return onDecimalPressed!();
30 }
31
@@ -50,10 +49,10 @@ class NumberPad extends StatelessWidget {
49 child: Text(
50 '.',
51 style: Theme.of(context).textTheme.headlineMedium?.copyWith(
53 - fontWeight: FontWeight.w600,
54 - fontSize: 30,
55 - color: Theme.of(context).colorScheme.onSurfaceVariant,
56 - ),
52 + fontWeight: FontWeight.w600,
53 + fontSize: 30,
54 + color: Theme.of(context).colorScheme.onSurfaceVariant,
55 + ),
56 textAlign: TextAlign.center,
57 ),
58 ),
@@ -70,8 +69,7 @@ class NumberPad extends StatelessWidget {
69 child: TextButton(
70 onPressed: onDeletePressed,
71 style: TextButton.styleFrom(
73 - backgroundColor:
74 - Colors.transparent,
72 + backgroundColor: Colors.transparent,
73 shape: CircleBorder(),
74 ),
75 child: Image.asset(
lib/src/screens/monero_accounts/widgets/account_tile.dart
+1 -1
@@ -64,7 +64,7 @@ class AccountTile extends StatelessWidget {
64 ? Theme.of(context).colorScheme.onSurface
65 : Theme.of(context).colorScheme.onSurfaceVariant,
66 decoration: TextDecoration.none,
67 - ),
67 + ),
68 ),
69 ),
70 ],
lib/src/screens/new_wallet/wallet_group_description_page.dart
+1 -1
@@ -18,7 +18,7 @@ class WalletGroupDescriptionPage extends BasePage {
18
19 @override
20 Widget Function(BuildContext, Widget) get rootWrapper =>
21 - (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
21 + (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
22
23 @override
24 String get title => S.current.wallet_list_create_new_wallet;
lib/src/screens/new_wallet/wallet_group_existing_seed_description_page.dart
+9 -8
@@ -14,7 +14,7 @@ class WalletGroupExistingSeedDescriptionPage extends BasePage {
14
15 @override
16 Widget Function(BuildContext, Widget) get rootWrapper =>
17 - (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
17 + (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
18
19 @override
20 String get title => S.current.wallet_group;
@@ -34,9 +34,10 @@ class WalletGroupExistingSeedDescriptionPage extends BasePage {
34 child: Column(
35 children: [
36 CakeImageWidget(
37 - imageUrl: currentTheme.isDark ? walletGroupConfirmedImageDark : walletGroupConfirmedImageLight,
38 - height: 200
39 - ),
37 + imageUrl: currentTheme.isDark
38 + ? walletGroupConfirmedImageDark
39 + : walletGroupConfirmedImageLight,
40 + height: 200),
41 SizedBox(height: 32),
42 Expanded(
43 child: SingleChildScrollView(
@@ -55,10 +56,10 @@ class WalletGroupExistingSeedDescriptionPage extends BasePage {
56 TextSpan(
57 text: S.current.seed_display_path,
58 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
58 - fontSize: 16,
59 - fontWeight: FontWeight.w800,
60 - color: Theme.of(context).colorScheme.onSurfaceVariant,
61 - ),
59 + fontSize: 16,
60 + fontWeight: FontWeight.w800,
61 + color: Theme.of(context).colorScheme.onSurfaceVariant,
62 + ),
63 ),
64 ],
65 ),
lib/src/screens/new_wallet/widgets/select_button.dart
+12 -8
@@ -17,7 +17,8 @@ class SelectButton extends StatelessWidget {
17 this.deviceConnectionTypes,
18 this.borderRadius,
19 this.padding,
20 - super.key, this.center = false,
20 + super.key,
21 + this.center = false,
22 });
23
24 final Widget? image;
@@ -38,7 +39,10 @@ class SelectButton extends StatelessWidget {
39
40 @override
41 Widget build(BuildContext context) {
41 - final backgroundColor = color ?? (isSelected ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.surfaceContainer);
42 + final backgroundColor = color ??
43 + (isSelected
44 + ? Theme.of(context).colorScheme.primary
45 + : Theme.of(context).colorScheme.surfaceContainer);
46 final effectiveTextColor = textColor ??
47 (isSelected
48 ? Theme.of(context).colorScheme.onPrimary
@@ -81,24 +85,24 @@ class SelectButton extends StatelessWidget {
85 mainAxisAlignment: center ? MainAxisAlignment.center : MainAxisAlignment.start,
86 crossAxisAlignment: CrossAxisAlignment.center,
87 children: <Widget>[
84 - if(!center) SizedBox(width:16),
88 + if (!center) SizedBox(width: 16),
89 image ?? Offstage(),
90 Padding(
91 padding: image != null ? EdgeInsets.only(left: 14) : EdgeInsets.only(left: 0),
92 child: Text(
93 text,
94 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
91 - fontSize: textSize,
92 - fontWeight: FontWeight.w500,
93 - color: effectiveTextColor,
94 - ),
95 + fontSize: textSize,
96 + fontWeight: FontWeight.w500,
97 + color: effectiveTextColor,
98 + ),
99 ),
100 )
101 ],
102 ),
103 ),
104 ...trailingIcons,
101 - if(!center) SizedBox(width:16),
105 + if (!center) SizedBox(width: 16),
106 ],
107 ),
108 ),
lib/src/screens/nodes/node_create_or_edit_page.dart
+54 -50
@@ -37,16 +37,15 @@ class NodeCreateOrEditPage extends StatefulWidget {
37 class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
38 final _nodeFormKey = GlobalKey<NodeFormState>();
39
40 -
40 @override
41 void initState() {
42 super.initState();
43 reaction(
45 - (_) => widget.nodeCreateOrEditViewModel.connectionState,
46 - (ExecutionState state) {
44 + (_) => widget.nodeCreateOrEditViewModel.connectionState,
45 + (ExecutionState state) {
46 if (state is ExecutedSuccessfullyState) {
47 WidgetsBinding.instance.addPostFrameCallback(
49 - (_) => showPopUp<void>(
48 + (_) => showPopUp<void>(
49 context: context,
50 builder: (context) => AlertWithOneAction(
51 alertTitle: S.of(context).new_node_testing,
@@ -62,7 +61,7 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
61
62 if (state is FailureState) {
63 WidgetsBinding.instance.addPostFrameCallback(
65 - (_) => showPopUp<void>(
64 + (_) => showPopUp<void>(
65 context: context,
66 builder: (context) => AlertWithOneAction(
67 alertTitle: S.of(context).error,
@@ -76,19 +75,16 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
75 },
76 );
77
79 -
80 - reaction((_)=>widget.nodeCreateOrEditViewModel.state, (state) async {
81 - if(state is ExecutedSuccessfullyState) {
78 + reaction((_) => widget.nodeCreateOrEditViewModel.state, (state) async {
79 + if (state is ExecutedSuccessfullyState) {
80 await Future.delayed(Duration(milliseconds: 100));
81 if (mounted) Navigator.of(context).pop(widget.nodeCreateOrEditViewModel.editingNode);
82 }
85 -
83 });
84 }
85
86 @override
87 Widget build(BuildContext context) {
91 -
88 return Container(
89 color: Theme.of(context).colorScheme.surface,
90 child: SafeArea(
@@ -112,49 +108,57 @@ class _NodeCreateOrEditPageState extends State<NodeCreateOrEditPage> {
108 child: KeyboardHideOverlay(
109 child: Container(
110 padding: const EdgeInsets.only(left: 18, right: 18),
115 - child: Column(
116 - spacing: 18,
117 - children: [NodeForm(
111 + child: Column(spacing: 18, children: [
112 + NodeForm(
113 key: _nodeFormKey,
114 nodeViewModel: widget.nodeCreateOrEditViewModel,
115 ),
121 - NewListSections(sections: {"":[
122 - if(widget.editingNode != null)
123 -
124 - ListItemRegularRow(keyValue: "share", label: S.of(context).share_this_node, foregroundColor: Theme.of(context).colorScheme.primary, showArrow: false, onTap: (){
125 -
126 - Navigator.of(context).push(CupertinoPageRoute(builder: (context)=>NodeSharePage(uri: widget.editingNode!.uri, currency: walletTypeToCryptoCurrency(widget.type!))));
127 -
128 -
129 - }),
130 - if(!(widget.editingNode == null ||
131 - !widget.nodeCreateOrEditViewModel.isReady ||
132 - widget.editingNode!.isBuiltin ||
133 - (widget.isSelected ?? false)))
134 - ListItemRegularRow(keyValue: "delete", label: S.of(context).delete_this_node, foregroundColor: Theme.of(context).colorScheme.errorContainer, showArrow: false, onTap: ()async{
135 - final confirmed = await showPopUp<bool>(
136 - context: context,
137 - builder: (context) => AlertWithTwoActions(
138 - alertTitle: S.of(context).remove_node,
139 - alertContent: S.of(context).remove_node_message,
140 - rightButtonText: S.of(context).remove,
141 - leftButtonText: S.of(context).cancel,
142 - actionRightButton: () => Navigator.pop(context, true),
143 - actionLeftButton: () => Navigator.pop(context, false),
144 - ),
145 - ) ??
146 - false;
147 -
148 - if (confirmed) {
149 - await widget.nodeCreateOrEditViewModel.delete(editingNode: widget.editingNode!);
150 - Navigator.of(context).pop();
151 - }
152 -
153 - })
154 - ]})
155 -
156 - ]
157 - ),
116 + NewListSections(sections: {
117 + "": [
118 + if (widget.editingNode != null)
119 + ListItemRegularRow(
120 + keyValue: "share",
121 + label: S.of(context).share_this_node,
122 + foregroundColor: Theme.of(context).colorScheme.primary,
123 + showArrow: false,
124 + onTap: () {
125 + Navigator.of(context).push(CupertinoPageRoute(
126 + builder: (context) => NodeSharePage(
127 + uri: widget.editingNode!.uri,
128 + currency: walletTypeToCryptoCurrency(widget.type!))));
129 + }),
130 + if (!(widget.editingNode == null ||
131 + !widget.nodeCreateOrEditViewModel.isReady ||
132 + widget.editingNode!.isBuiltin ||
133 + (widget.isSelected ?? false)))
134 + ListItemRegularRow(
135 + keyValue: "delete",
136 + label: S.of(context).delete_this_node,
137 + foregroundColor: Theme.of(context).colorScheme.errorContainer,
138 + showArrow: false,
139 + onTap: () async {
140 + final confirmed = await showPopUp<bool>(
141 + context: context,
142 + builder: (context) => AlertWithTwoActions(
143 + alertTitle: S.of(context).remove_node,
144 + alertContent: S.of(context).remove_node_message,
145 + rightButtonText: S.of(context).remove,
146 + leftButtonText: S.of(context).cancel,
147 + actionRightButton: () => Navigator.pop(context, true),
148 + actionLeftButton: () => Navigator.pop(context, false),
149 + ),
150 + ) ??
151 + false;
152 +
153 + if (confirmed) {
154 + await widget.nodeCreateOrEditViewModel
155 + .delete(editingNode: widget.editingNode!);
156 + Navigator.of(context).pop();
157 + }
158 + })
159 + ]
160 + })
161 + ]),
162 ),
163 ),
164 ),
lib/src/screens/nodes/pow_node_create_or_edit_page.dart
+23 -20
@@ -18,11 +18,7 @@ import 'package:cake_wallet/src/widgets/scrollable_with_bottom_section.dart';
18
19 class PowNodeCreateOrEditPage extends StatefulWidget {
20 PowNodeCreateOrEditPage(
21 - {required this.nodeCreateOrEditViewModel, this.editingNode, this.isSelected})
22 - ;
23 -
24 -
25 -
21 + {required this.nodeCreateOrEditViewModel, this.editingNode, this.isSelected});
22
23 final NodeCreateOrEditViewModel nodeCreateOrEditViewModel;
24 final Node? editingNode;
@@ -35,7 +31,6 @@ class PowNodeCreateOrEditPage extends StatefulWidget {
31 class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
32 final _formKey = GlobalKey<NodeFormState>();
33
38 -
34 @override
35 void initState() {
36 super.initState();
@@ -72,7 +67,6 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
67
68 @override
69 Widget build(BuildContext context) {
75 -
70 return Container(
71 color: Theme.of(context).colorScheme.surface,
72 child: KeyboardHideOverlay(
@@ -82,11 +76,15 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
76 title: widget.editingNode != null ? S.current.edit_node : S.current.node_new,
77 leadingIcon: Icon(Icons.arrow_back_ios_new),
78 onLeadingPressed: Navigator.of(context).pop,
85 - trailingIcon: CakeImageWidget(imageUrl:
86 - "assets/new-ui/scan.svg",width:24,height:24,
87 - colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
79 + trailingIcon: CakeImageWidget(
80 + imageUrl: "assets/new-ui/scan.svg",
81 + width: 24,
82 + height: 24,
83 + colorFilter:
84 + ColorFilter.mode(Theme.of(context).colorScheme.primary, BlendMode.srcIn),
85 ),
89 - onTrailingPressed: () => widget.nodeCreateOrEditViewModel.scanQRCodeForNewNode(context),
86 + onTrailingPressed: () =>
87 + widget.nodeCreateOrEditViewModel.scanQRCodeForNewNode(context),
88 ),
89 Expanded(
90 child: Container(
@@ -112,21 +110,25 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
110 builder: (BuildContext context) {
111 return AlertWithTwoActions(
112 alertTitle: S.of(context).remove_node,
115 - alertContent: S.of(context).remove_node_message,
113 + alertContent:
114 + S.of(context).remove_node_message,
115 rightButtonText: S.of(context).remove,
116 leftButtonText: S.of(context).cancel,
118 - actionRightButton: () => Navigator.pop(context, true),
119 - actionLeftButton: () => Navigator.pop(context, false));
117 + actionRightButton: () =>
118 + Navigator.pop(context, true),
119 + actionLeftButton: () =>
120 + Navigator.pop(context, false));
121 }) ??
122 false;
122 -
123 +
124 if (confirmed) {
125 await widget.editingNode!.delete();
126 Navigator.of(context).pop();
127 }
128 },
129 text: S.of(context).delete,
129 - isDisabled: !widget.nodeCreateOrEditViewModel.isReady || (widget.isSelected ?? false),
130 + isDisabled: !widget.nodeCreateOrEditViewModel.isReady ||
131 + (widget.isSelected ?? false),
132 color: Theme.of(context).colorScheme.errorContainer,
133 textColor: Theme.of(context).colorScheme.onPrimary,
134 ),
@@ -141,16 +143,17 @@ class _PowNodeCreateOrEditPageState extends State<PowNodeCreateOrEditPage> {
143 !_formKey.currentState!.validate()) {
144 return;
145 }
144 -
145 - await widget.nodeCreateOrEditViewModel.save(
146 - saveAsCurrent: widget.isSelected ?? false);
146 +
147 + await widget.nodeCreateOrEditViewModel
148 + .save(saveAsCurrent: widget.isSelected ?? false);
149 Navigator.of(context).pop();
150 },
151 text: S.of(context).save,
152 color: Theme.of(context).colorScheme.primary,
153 textColor: Theme.of(context).colorScheme.onPrimary,
154 isDisabled: (!widget.nodeCreateOrEditViewModel.isReady) ||
153 - (widget.nodeCreateOrEditViewModel.connectionState is IsExecutingState),
155 + (widget.nodeCreateOrEditViewModel.connectionState
156 + is IsExecutingState),
157 ),
158 )),
159 ],
lib/src/screens/nodes/widgets/node_form.dart
+90 -93
@@ -34,7 +34,7 @@ class NodeFormState extends State<NodeForm> {
34 void initState() {
35 super.initState();
36
37 - for(final key in vm.textFieldKeys) {
37 + for (final key in vm.textFieldKeys) {
38 _controllers[key] = TextEditingController();
39
40 _controllers[key]!.text = vm.getTextValue(key);
@@ -61,114 +61,112 @@ class NodeFormState extends State<NodeForm> {
61 @override
62 Widget build(BuildContext context) {
63 return Observer(
64 - builder: (_)=>Form(
64 + builder: (_) => Form(
65 key: _formKey,
66 child: NewListSections(
67 - sections: {
68 - if(!(vm.editingNode?.isBuiltin ?? false)) ...{
69 - 'main': [
70 - ListItemTextField(
71 - keyValue: vm.nodeLabelUIKey,
72 - label: 'Node label',
73 - initialValue: vm.label,
74 - ),
75 - ListItemTextField(
76 - keyValue: vm.nodeAddressUIKey,
77 - label: S.current.node_address,
78 - initialValue: vm.address,
79 - validator: vm.walletType == WalletType.decred
80 - ? NodeAddressValidatorDecredBlankException()
81 - : NodeAddressValidator(),
82 - ),
83 - if (vm.hasPathSupport)
67 + sections: {
68 + if (!(vm.editingNode?.isBuiltin ?? false)) ...{
69 + 'main': [
70 ListItemTextField(
85 - keyValue: vm.nodePathUIKey,
86 - label: '/path',
87 - initialValue: vm.path,
88 - validator: NodePathValidator(),
71 + keyValue: vm.nodeLabelUIKey,
72 + label: 'Node label',
73 + initialValue: vm.label,
74 ),
90 - ListItemTextField(
91 - keyValue: vm.nodePortUIKey,
92 - label: S.current.node_port,
93 - initialValue: '',
94 - //keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
95 - validator: NodePortValidator(),
96 - ),
97 - if (vm.hasAuthCredentials) ...[
75 ListItemTextField(
99 - keyValue: vm.nodeUsernameUIKey,
100 - label: S.current.login,
101 - initialValue: vm.login,
76 + keyValue: vm.nodeAddressUIKey,
77 + label: S.current.node_address,
78 + initialValue: vm.address,
79 + validator: vm.walletType == WalletType.decred
80 + ? NodeAddressValidatorDecredBlankException()
81 + : NodeAddressValidator(),
82 ),
83 + if (vm.hasPathSupport)
84 + ListItemTextField(
85 + keyValue: vm.nodePathUIKey,
86 + label: '/path',
87 + initialValue: vm.path,
88 + validator: NodePathValidator(),
89 + ),
90 ListItemTextField(
104 - keyValue: vm.nodePasswordUIKey,
105 - label: S.current.password,
106 - initialValue: vm.password,
91 + keyValue: vm.nodePortUIKey,
92 + label: S.current.node_port,
93 + initialValue: '',
94 + //keyboardType: TextInputType.numberWithOptions(signed: false, decimal: false),
95 + validator: NodePortValidator(),
96 ),
108 - ]
109 - ],
110 - 'advanced': [
111 - ListItemCheckbox(
112 - keyValue: vm.useSSLUIKey,
113 - label: S.current.use_ssl,
114 - value: vm.useSSL,
115 - onChanged: (value) => vm.useSSL = value),
97 + if (vm.hasAuthCredentials) ...[
98 + ListItemTextField(
99 + keyValue: vm.nodeUsernameUIKey,
100 + label: S.current.login,
101 + initialValue: vm.login,
102 + ),
103 + ListItemTextField(
104 + keyValue: vm.nodePasswordUIKey,
105 + label: S.current.password,
106 + initialValue: vm.password,
107 + ),
108 + ]
109 + ],
110 + 'advanced': [
111 + ListItemCheckbox(
112 + keyValue: vm.useSSLUIKey,
113 + label: S.current.use_ssl,
114 + value: vm.useSSL,
115 + onChanged: (value) => vm.useSSL = value),
116 + ListItemCheckbox(
117 + keyValue: vm.nodeTrustedUIKey,
118 + label: S.current.trusted,
119 + value: vm.trusted,
120 + onChanged: (value) => vm.trusted = value,
121 + ),
122 + if (vm.usesEmbeddedProxy)
123 + ListItemCheckbox(
124 + keyValue: vm.nodeEmbeddedTorProxyUIKey,
125 + label: 'Embedded Tor SOCKS Proxy',
126 + value: vm.usesEmbeddedProxy,
127 + onChanged: (_) {},
128 + ),
129 + if (FeatureFlag.isAutomaticNodeSwitchingEnabled)
130 + ListItemCheckbox(
131 + keyValue: vm.autoSwitchingUIKey,
132 + label: S.current.enable_for_auto_switching,
133 + value: vm.isEnabledForAutoSwitching,
134 + onChanged: (value) => vm.isEnabledForAutoSwitching = value),
135 + ],
136 + },
137 + "proxy": [
138 ListItemCheckbox(
117 - keyValue: vm.nodeTrustedUIKey,
118 - label: S.current.trusted,
119 - value: vm.trusted,
120 - onChanged: (value) => vm.trusted = value,
139 + keyValue: vm.useSocksProxyUIKey,
140 + label: 'Use SOCKS Proxy',
141 + value: vm.useSocksProxy,
142 + onChanged: (value) {
143 + vm.socksProxyAddress = '';
144 + vm.useSocksProxy = value;
145 + },
146 ),
122 - if (vm.usesEmbeddedProxy)
123 - ListItemCheckbox(
124 - keyValue: vm.nodeEmbeddedTorProxyUIKey,
125 - label: 'Embedded Tor SOCKS Proxy',
126 - value: vm.usesEmbeddedProxy,
127 - onChanged: (_) {},
147 + if (vm.useSocksProxy)
148 + ListItemTextField(
149 + keyValue: vm.socksProxyAddressUIKey,
150 + label: 'host:port',
151 + initialValue: vm.socksProxyAddress,
152 + validator: SocksProxyNodeAddressValidator(),
153 ),
129 - if(FeatureFlag.isAutomaticNodeSwitchingEnabled)
130 - ListItemCheckbox(
131 - keyValue: vm.autoSwitchingUIKey,
132 - label: S.current.enable_for_auto_switching,
133 - value: vm.isEnabledForAutoSwitching,
134 - onChanged: (value) => vm.isEnabledForAutoSwitching = value),
135 - ],
154 + ]
155 },
137 -
138 - "proxy" : [
139 - ListItemCheckbox(
140 - keyValue: vm.useSocksProxyUIKey,
141 - label: 'Use SOCKS Proxy',
142 - value: vm.useSocksProxy,
143 - onChanged: (value) {
144 - vm.socksProxyAddress = '';
145 - vm.useSocksProxy = value;
146 - },
147 - ),
148 - if (vm.useSocksProxy)
149 - ListItemTextField(
150 - keyValue: vm.socksProxyAddressUIKey,
151 - label: 'host:port',
152 - initialValue: vm.socksProxyAddress,
153 - validator: SocksProxyNodeAddressValidator(),
154 - ),
155 - ]
156 - },
157 - controllers: _controllers,
158 - getCheckboxValue: vm.getCheckboxValue,
159 - updateCheckboxValue: vm.updateCheckboxValue,
160 - tapHandlers: tapHandlers
161 - ),
156 + controllers: _controllers,
157 + getCheckboxValue: vm.getCheckboxValue,
158 + updateCheckboxValue: vm.updateCheckboxValue,
159 + tapHandlers: tapHandlers),
160 ),
161 );
162 }
163
164 Map<String, VoidCallback> get tapHandlers => {
167 - 'node_regular_with_drill_in_row_key': () => _showToast('Regular with drill-in row tapped'),
168 - 'node_tall_row_key': () => _showToast('Tall row tapped'),
169 - 'node_regular_with_trailing_row_key': () => _showToast('Regular with trailing row tapped'),
170 - 'node_item_selector_row_key': () => _showToast('Item selector row tapped'),
171 - };
165 + 'node_regular_with_drill_in_row_key': () => _showToast('Regular with drill-in row tapped'),
166 + 'node_tall_row_key': () => _showToast('Tall row tapped'),
167 + 'node_regular_with_trailing_row_key': () => _showToast('Regular with trailing row tapped'),
168 + 'node_item_selector_row_key': () => _showToast('Item selector row tapped'),
169 + };
170
171 void _showToast(String msg) async {
172 try {
@@ -179,7 +177,6 @@ class NodeFormState extends State<NodeForm> {
177 } catch (_) {}
178 }
179
182 -
180 void _setupReactions() {
181 _bindController(() => vm.label, vm.nodeLabelUIKey);
182 _bindController(() => vm.address, vm.nodeAddressUIKey);
lib/src/screens/nodes/widgets/node_list_row.dart
+35 -18
@@ -8,7 +8,7 @@ class NodeListRow extends StatelessWidget {
8 NodeListRow(
9 {required this.node,
10 required this.onTap,
11 - required this.onEditComplete,
11 + required this.onEditComplete,
12 required this.isSelected,
13 required this.isPow,
14 this.speed,
@@ -42,20 +42,36 @@ class NodeListRow extends StatelessWidget {
42 mainAxisAlignment: MainAxisAlignment.spaceBetween,
43 children: <Widget>[
44 leading,
45 - Expanded(
46 - child: Column(crossAxisAlignment:CrossAxisAlignment.start,spacing:4,children: [
47 - Row(
48 - spacing: 4,
49 - mainAxisAlignment: MainAxisAlignment.start,
50 - children: [
51 - Text(hasLabel ? node.label! : uriText, style: TextStyle(fontSize: 12),),
52 - if(badgePath != null)
53 - CakeImageWidget(imageUrl: badgePath, colorFilter: ColorFilter.mode(Theme.of(context).colorScheme.primary,BlendMode.srcIn),)
54 - ],
55 - ),
56 - if(hasLabel) Text(uriText, style: TextStyle(fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),),
57 - ],),
58 - ),
45 + Expanded(
46 + child: Column(
47 + crossAxisAlignment: CrossAxisAlignment.start,
48 + spacing: 4,
49 + children: [
50 + Row(
51 + spacing: 4,
52 + mainAxisAlignment: MainAxisAlignment.start,
53 + children: [
54 + Text(
55 + hasLabel ? node.label! : uriText,
56 + style: TextStyle(fontSize: 12),
57 + ),
58 + if (badgePath != null)
59 + CakeImageWidget(
60 + imageUrl: badgePath,
61 + colorFilter: ColorFilter.mode(
62 + Theme.of(context).colorScheme.primary, BlendMode.srcIn),
63 + )
64 + ],
65 + ),
66 + if (hasLabel)
67 + Text(
68 + uriText,
69 + style: TextStyle(
70 + fontSize: 12, color: Theme.of(context).colorScheme.onSurfaceVariant),
71 + ),
72 + ],
73 + ),
74 + ),
75 trailing,
76 ],
77 ),
@@ -89,7 +105,8 @@ class NodeListRow extends StatelessWidget {
105 GestureDetector(
106 behavior: HitTestBehavior.opaque,
107 onTap: () async {
92 - final res = await Navigator.of(context).pushNamed(isPow ? Routes.newPowNode : Routes.newNode,
108 + final res = await Navigator.of(context).pushNamed(
109 + isPow ? Routes.newPowNode : Routes.newNode,
110 arguments: {'editingNode': node, 'isSelected': isSelected});
111 await onEditComplete(res);
112 },
@@ -107,8 +124,8 @@ class NodeListRow extends StatelessWidget {
124 }
125
126 String? get badgePath {
110 - if(node.isOfficial) return "assets/new-ui/official_node.svg";
111 - if(node.isBuiltin) return "assets/new-ui/default_node.svg";
127 + if (node.isOfficial) return "assets/new-ui/official_node.svg";
128 + if (node.isBuiltin) return "assets/new-ui/default_node.svg";
129 return null;
130 }
131 }
lib/src/screens/pin_code/pin_code.dart
+2 -6
@@ -2,12 +2,8 @@ import 'package:flutter/foundation.dart';
2 import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
3
4 class PinCode extends PinCodeWidget {
5 - PinCode(
6 - void Function(String pin, PinCodeState state) onFullPin,
7 - void Function(String pin) onChangedPin,
8 - int initialPinLength,
9 - bool hasLengthSwitcher,
10 - Key key)
5 + PinCode(void Function(String pin, PinCodeState state) onFullPin,
6 + void Function(String pin) onChangedPin, int initialPinLength, bool hasLengthSwitcher, Key key)
7 : super(
8 key: key,
9 onFullPin: onFullPin,
lib/src/screens/pin_code/pin_code_widget.dart
+4 -2
@@ -231,7 +231,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
231 child: TextButton(
232 onPressed: () => {_pop(), HapticFeedback.mediumImpact()},
233 style: TextButton.styleFrom(
234 - backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
234 + backgroundColor:
235 + Theme.of(context).colorScheme.surfaceContainer,
236 shape: CircleBorder(),
237 ),
238 child: deleteIconImage,
@@ -249,7 +250,8 @@ class PinCodeState<T extends PinCodeWidget> extends State<T> {
250 key: ValueKey('pin_code_button_${index}_key'),
251 onPressed: () => {_push(index), HapticFeedback.mediumImpact()},
252 style: TextButton.styleFrom(
252 - backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
253 + backgroundColor:
254 + Theme.of(context).colorScheme.surfaceContainer,
255 shape: CircleBorder(),
256 ),
257 child: Text('$index',
lib/src/screens/receive/widgets/anonpay_status_section.dart
+12 -12
@@ -28,9 +28,9 @@ class AnonInvoiceStatusSection extends StatelessWidget {
28 Text(
29 S.current.status,
30 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
31 - fontWeight: FontWeight.w500,
32 - color: Theme.of(context).colorScheme.onSurfaceVariant,
33 - ),
31 + fontWeight: FontWeight.w500,
32 + color: Theme.of(context).colorScheme.onSurfaceVariant,
33 + ),
34 ),
35 Container(
36 padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
@@ -50,9 +50,9 @@ class AnonInvoiceStatusSection extends StatelessWidget {
50 Text(
51 invoiceInfo.status,
52 style: Theme.of(context).textTheme.bodySmall?.copyWith(
53 - fontWeight: FontWeight.w600,
54 - color: Theme.of(context).colorScheme.onSecondaryContainer,
55 - ),
53 + fontWeight: FontWeight.w600,
54 + color: Theme.of(context).colorScheme.onSecondaryContainer,
55 + ),
56 ),
57 ],
58 ),
@@ -66,16 +66,16 @@ class AnonInvoiceStatusSection extends StatelessWidget {
66 Text(
67 'ID',
68 style: Theme.of(context).textTheme.bodyMedium?.copyWith(
69 - fontWeight: FontWeight.w500,
70 - color: Theme.of(context).colorScheme.onSurfaceVariant,
71 - ),
69 + fontWeight: FontWeight.w500,
70 + color: Theme.of(context).colorScheme.onSurfaceVariant,
71 + ),
72 ),
73 Text(
74 invoiceInfo.invoiceId,
75 style: Theme.of(context).textTheme.bodySmall?.copyWith(
76 - fontWeight: FontWeight.w600,
77 - color: Theme.of(context).colorScheme.onSurface,
78 - ),
76 + fontWeight: FontWeight.w600,
77 + color: Theme.of(context).colorScheme.onSurface,
78 + ),
79 ),
80 ],
81 ),
lib/src/screens/receive/widgets/copy_link_item.dart
+2 -2
@@ -20,8 +20,8 @@ class CopyLinkItem extends StatelessWidget {
20 Text(
21 title,
22 style: Theme.of(context).textTheme.bodyLarge?.copyWith(
23 - color: Theme.of(context).colorScheme.onSurface,
24 - ),
23 + color: Theme.of(context).colorScheme.onSurface,
24 + ),
25 ),
26 SizedBox(width: 50),
27 Row(
lib/src/screens/release_notes/release_notes_screen.dart
+9 -11
@@ -47,12 +47,11 @@ class ReleaseNotesScreen extends StatelessWidget {
47 alignment: Alignment.bottomCenter,
48 child: DefaultTextStyle(
49 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
50 - decoration: TextDecoration.none,
51 - fontSize: 24.0,
52 - fontWeight: FontWeight.bold,
53 -
54 - color: Theme.of(context).colorScheme.onSurface,
55 - ),
50 + decoration: TextDecoration.none,
51 + fontSize: 24.0,
52 + fontWeight: FontWeight.bold,
53 + color: Theme.of(context).colorScheme.onSurface,
54 + ),
55 child: Text(title),
56 ),
57 ),
@@ -115,11 +114,10 @@ class ReleaseNotesScreen extends StatelessWidget {
114 children: [
115 DefaultTextStyle(
116 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
118 - decoration: TextDecoration.none,
119 - fontSize: 16.0,
120 -
121 - color: Theme.of(context).colorScheme.onSurface,
122 - ),
117 + decoration: TextDecoration.none,
118 + fontSize: 16.0,
119 + color: Theme.of(context).colorScheme.onSurface,
120 + ),
121 child: Row(
122 crossAxisAlignment: CrossAxisAlignment.start,
123 children: [
lib/src/screens/rescan/rescan_page.dart
-1
@@ -25,7 +25,6 @@ class RescanPage extends StatefulWidget {
25 class _RescanPageState extends State<RescanPage> {
26 final TextEditingController _heightController = TextEditingController();
27
28 -
28 @override
29 Widget build(BuildContext context) {
30 Widget child;
lib/src/screens/restore/restore_from_backup_page.dart
+8 -8
@@ -207,14 +207,14 @@ class RestoreFromBackupPage extends BasePage {
207 }
208 } catch (e) {
209 await showPopUp<void>(
210 - context: context,
211 - builder: (_) {
212 - return AlertWithOneAction(
213 - alertTitle: S.current.error,
214 - alertContent: e.toString(),
215 - buttonText: S.of(context).ok,
216 - buttonAction: () => Navigator.of(context).pop());
217 - });
210 + context: context,
211 + builder: (_) {
212 + return AlertWithOneAction(
213 + alertTitle: S.current.error,
214 + alertContent: e.toString(),
215 + buttonText: S.of(context).ok,
216 + buttonAction: () => Navigator.of(context).pop());
217 + });
218 }
219 textEditingController.text = '';
220 }
lib/src/screens/restore/restore_options_page.dart
+5 -5
@@ -23,9 +23,9 @@ class RestoreOptionsPage extends BasePage {
23
24 @override
25 Widget body(BuildContext context) => _RestoreOptionsBody(
26 - isNewInstall: isNewInstall,
27 - themeType: currentTheme.type,
28 - );
26 + isNewInstall: isNewInstall,
27 + themeType: currentTheme.type,
28 + );
29 }
30
31 class _RestoreOptionsBody extends StatefulWidget {
@@ -157,7 +157,7 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
157
158 Future<void> _onScanQRCode(BuildContext context) async {
159 final isCameraPermissionGranted =
160 - await PermissionHandler.checkPermission(Permission.camera, context);
160 + await PermissionHandler.checkPermission(Permission.camera, context);
161
162 if (!isCameraPermissionGranted) return;
163 try {
@@ -180,4 +180,4 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> {
180 _showQRScanError(context, e.toString());
181 }
182 }
183 -}
\ No newline at end of file
183 +}
lib/src/screens/restore/wallet_restore_choose_derivation.dart
+4 -3
@@ -11,9 +11,10 @@ class WalletRestoreChooseDerivationPage extends BasePage {
11 @override
12 Widget middle(BuildContext context) => Text(
13 S.current.choose_derivation,
14 - style: Theme.of(context).textTheme.titleLarge?.copyWith(
15 - fontWeight: FontWeight.bold,
16 - color: Theme.of(context).colorScheme.primary),
14 + style: Theme.of(context)
15 + .textTheme
16 + .titleLarge
17 + ?.copyWith(fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.primary),
18 );
19
20 final WalletRestoreChooseDerivationViewModel walletRestoreChooseDerivationViewModel;
lib/src/screens/restore/wallet_restore_from_keys_form.dart
+18 -20
@@ -232,27 +232,25 @@ class WalletRestoreFromKeysFormState extends State<WalletRestoreFromKeysForm> {
232
233 bool nanoBased = widget.walletRestoreViewModel.type == WalletType.nano ||
234 widget.walletRestoreViewModel.type == WalletType.banano;
235 - return Column(
236 - children: [
237 - AddressTextField(
238 - addressKey: ValueKey('wallet_restore_from_key_private_key_textfield_key'),
239 - controller: privateKeyController,
240 - placeholder: nanoBased ? S.of(context).seed_hex_form : S.of(context).private_key,
241 - options: [AddressTextFieldOption.paste],
242 - onPushPasteButton: (_) {
243 - _pasteText();
244 - },
235 + return Column(children: [
236 + AddressTextField(
237 + addressKey: ValueKey('wallet_restore_from_key_private_key_textfield_key'),
238 + controller: privateKeyController,
239 + placeholder: nanoBased ? S.of(context).seed_hex_form : S.of(context).private_key,
240 + options: [AddressTextFieldOption.paste],
241 + onPushPasteButton: (_) {
242 + _pasteText();
243 + },
244 + ),
245 + if (widget.walletRestoreViewModel.hasBlockchainHeightSelector)
246 + BlockchainHeightWidget(
247 + key: blockchainHeightKey,
248 + hasDatePicker: widget.walletRestoreViewModel.type != WalletType.haven,
249 + onHeightChange: (_) => null,
250 + onHeightOrDateEntered: widget.onHeightOrDateEntered,
251 + walletType: widget.walletRestoreViewModel.type,
252 ),
246 - if (widget.walletRestoreViewModel.hasBlockchainHeightSelector)
247 - BlockchainHeightWidget(
248 - key: blockchainHeightKey,
249 - hasDatePicker: widget.walletRestoreViewModel.type != WalletType.haven,
250 - onHeightChange: (_) => null,
251 - onHeightOrDateEntered: widget.onHeightOrDateEntered,
252 - walletType: widget.walletRestoreViewModel.type,
253 - ),
254 - ]
255 - );
253 + ]);
254 }
255
256 return Column(
lib/src/screens/restore/wallet_restore_from_seed_form.dart
+1 -1
@@ -161,7 +161,7 @@ class WalletRestoreFromSeedFormState extends State<WalletRestoreFromSeedForm> {
161 onPressed: () async {
162 final rName = await generateName();
163 FocusManager.instance.primaryFocus?.unfocus();
164 -
164 +
165 setState(() {
166 nameTextEditingController.text = rName;
167 nameTextEditingController.selection = TextSelection.fromPosition(
lib/src/screens/restore/wallet_restore_page.dart
+2 -3
@@ -298,8 +298,7 @@ class WalletRestorePage extends BasePage {
298 "m/49'/0'/0'",
299 };
300
301 - final shouldSkipChooseDerivationScreen =
302 - derivationPathsWithHistory.isNotEmpty &&
301 + final shouldSkipChooseDerivationScreen = derivationPathsWithHistory.isNotEmpty &&
302 derivationPathsWithHistory.every(scanDerivationPaths.contains);
303
304 if (derivationsWithHistory > 1 && !shouldSkipChooseDerivationScreen) {
@@ -537,7 +536,7 @@ class _WalletRestorePageBodyState extends State<_WalletRestorePageBody>
536 },
537 onViewKeyEntered: (bool entered) {
538 if (widget.walletRestoreViewModel.onlyViewKeyRestore ||
540 - walletRestoreViewModel.type == WalletType.litecoin) {
539 + walletRestoreViewModel.type == WalletType.litecoin) {
540 walletRestoreViewModel.isButtonEnabled = entered;
541 }
542 },
lib/src/screens/root/root.dart
-2
@@ -118,7 +118,6 @@ class RootState extends State<Root> with WidgetsBindingObserver {
118 final uri = Uri.parse('cakewallet://quickaction/${widget.initialQuickAction}');
119 handleDeepLinking(uri);
120 }
121 -
121 } catch (e) {
122 printV(e);
123 }
@@ -136,7 +135,6 @@ class RootState extends State<Root> with WidgetsBindingObserver {
135
136 bool requireAuth = await widget.authService.requireAuth();
137
139 -
138 if (widget.authenticationStore.state == AuthenticationState.allowedCreate) {
139 requireAuth = false;
140 }
lib/src/screens/seed/seed_verification/seed_verification_success_view.dart
+9 -7
@@ -21,12 +21,12 @@ class SeedVerificationSuccessView extends StatelessWidget {
21 children: [
22 ConstrainedBox(
23 constraints: BoxConstraints(maxHeight: MediaQuery.of(context).size.height * 0.3),
24 - child: CakeImageWidget(
25 - height: 128,
26 - imageUrl: currentTheme.isDark
27 - ? 'assets/images/seed_verified_dark.png'
28 - : 'assets/images/seed_verified_light.png',
29 - ),
24 + child: CakeImageWidget(
25 + height: 128,
26 + imageUrl: currentTheme.isDark
27 + ? 'assets/images/seed_verified_dark.png'
28 + : 'assets/images/seed_verified_light.png',
29 + ),
30 ),
31 SizedBox(height: 40),
32 Text(
@@ -72,7 +72,9 @@ class SeedVerificationSuccessView extends StatelessWidget {
72 Navigator.of(context).popUntil((route) => route.isFirst);
73 }
74 },
75 - text: (walletType == WalletType.bitcoin) ? S.current.continue_text : S.current.open_wallet,
75 + text: (walletType == WalletType.bitcoin)
76 + ? S.current.continue_text
77 + : S.current.open_wallet,
78 color: Theme.of(context).colorScheme.primary,
79 textColor: Theme.of(context).colorScheme.onPrimary,
80 ),
lib/src/screens/seed/wallet_seed_page.dart
+10 -9
@@ -21,7 +21,8 @@ class WalletSeedPage extends BasePage {
21 WalletSeedPage(this.walletSeedViewModel, {required this.isNewWalletCreated});
22
23 @override
24 - String get title => '${walletTypeToString(walletSeedViewModel.walletType)} ${S.current.seed_title}';
24 + String get title =>
25 + '${walletTypeToString(walletSeedViewModel.walletType)} ${S.current.seed_title}';
26
27 final bool isNewWalletCreated;
28 final WalletSeedViewModel walletSeedViewModel;
@@ -144,14 +145,14 @@ class WalletSeedPage extends BasePage {
145 }
146
147 void _shareSeed(BuildContext context) async {
147 - switch(defaultTargetPlatform) {
148 + switch (defaultTargetPlatform) {
149 case TargetPlatform.android:
150 case TargetPlatform.iOS:
150 - ShareUtil.share(
151 - text: walletSeedViewModel.seed,
152 - context: context,
153 - );
154 - break;
151 + ShareUtil.share(
152 + text: walletSeedViewModel.seed,
153 + context: context,
154 + );
155 + break;
156 case TargetPlatform.macOS:
157 case TargetPlatform.windows:
158 case TargetPlatform.linux:
@@ -160,12 +161,12 @@ class WalletSeedPage extends BasePage {
161 fileName: "${walletSeedViewModel.name}-seed.txt",
162 lockParentWindow: true,
163 );
163 - if(path != null) {
164 + if (path != null) {
165 final file = File(path);
166 await file.writeAsString(walletSeedViewModel.seed);
167 }
168 default:
168 -break;
169 + break;
170 }
171 }
172 }
lib/src/screens/send/send_page.dart
+337 -328
@@ -67,7 +67,6 @@ class SendPage extends BasePage {
67
68 final currentPage = ValueNotifier<int>(0);
69
70 -
70 bool _effectsInstalled = false;
71 ContactRecord? newContactAddress;
72
@@ -176,323 +175,334 @@ class SendPage extends BasePage {
175 _setEffects(context);
176
177 return ValueListenableBuilder(
179 - valueListenable: currentPage,
180 - builder: (context, value, child) {
181 - return Observer(builder: (_) {
182 - List<Widget> sendCards = [];
183 - List<KeyboardActionsItem> keyboardActions = [];
184 - for (final output in sendViewModel.outputs) {
185 - final isCurrent = sendViewModel.outputs.indexOf(output) == value;
186 - sendCards.add(
187 - SendCard(
188 - currentTheme: currentTheme,
189 - key: output.key,
190 - output: output,
191 - sendViewModel: sendViewModel,
192 - paymentViewModel: paymentViewModel,
193 - walletSwitcherViewModel: walletSwitcherViewModel,
194 - initialPaymentRequest: initialPaymentRequest,
195 - cryptoAmountFocus: isCurrent ? _cryptoAmountFocus : null,
196 - fiatAmountFocus: isCurrent ? _fiatAmountFocus : null,
197 - ),
198 - );
199 - keyboardActions.add(
200 - KeyboardActionsItem(
201 - focusNode: _cryptoAmountFocus,
202 - toolbarButtons: [(_) => KeyboardDoneButton()],
203 - ),
204 - );
205 - keyboardActions.add(
206 - KeyboardActionsItem(
207 - focusNode: _fiatAmountFocus,
208 - toolbarButtons: [(_) => KeyboardDoneButton()],
209 - ),
210 - );
211 - }
212 - return Stack(
213 - children: [
214 - KeyboardActions(
215 - config: KeyboardActionsConfig(
216 - keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
217 - keyboardBarColor: Theme.of(context).colorScheme.surface,
218 - nextFocus: false,
219 - actions: keyboardActions,
178 + valueListenable: currentPage,
179 + builder: (context, value, child) {
180 + return Observer(builder: (_) {
181 + List<Widget> sendCards = [];
182 + List<KeyboardActionsItem> keyboardActions = [];
183 + for (final output in sendViewModel.outputs) {
184 + final isCurrent = sendViewModel.outputs.indexOf(output) == value;
185 + sendCards.add(
186 + SendCard(
187 + currentTheme: currentTheme,
188 + key: output.key,
189 + output: output,
190 + sendViewModel: sendViewModel,
191 + paymentViewModel: paymentViewModel,
192 + walletSwitcherViewModel: walletSwitcherViewModel,
193 + initialPaymentRequest: initialPaymentRequest,
194 + cryptoAmountFocus: isCurrent ? _cryptoAmountFocus : null,
195 + fiatAmountFocus: isCurrent ? _fiatAmountFocus : null,
196 ),
221 - child: Container(
222 - height: 0,
223 - color: Colors.transparent,
197 + );
198 + keyboardActions.add(
199 + KeyboardActionsItem(
200 + focusNode: _cryptoAmountFocus,
201 + toolbarButtons: [(_) => KeyboardDoneButton()],
202 ),
225 - ),
226 - GestureDetector(
227 - onLongPress: () => sendViewModel.balanceViewModel.isReversing =
228 - !sendViewModel.balanceViewModel.isReversing,
229 - onLongPressUp: () => sendViewModel.balanceViewModel.isReversing =
230 - !sendViewModel.balanceViewModel.isReversing,
231 - child: RepaintBoundary(
232 - child: Form(
233 - key: _formKey,
234 - child: ScrollableWithBottomSection(
235 - contentPadding: EdgeInsets.only(bottom: 24),
236 - content: FocusTraversalGroup(
237 - policy: OrderedTraversalPolicy(),
238 - child: Column(
239 - children: <Widget>[
240 - PageViewHeightAdaptable(
241 - controller: controller,
242 - children: sendCards,
243 - ),
244 - SizedBox(height: 10),
245 - Padding(
246 - padding: EdgeInsets.only(left: 24, right: 24, bottom: 10),
247 - child: Container(
248 - height: 10,
249 - child: Observer(
250 - builder: (_) {
251 - final count = sendViewModel.outputs.length;
252 -
253 - return count > 1
254 - ? Semantics(
255 - label: 'Page Indicator',
256 - hint: 'Swipe to change receiver',
257 - excludeSemantics: true,
258 - child: SmoothPageIndicator(
259 - controller: controller,
260 - count: count,
261 - effect: ScrollingDotsEffect(
262 - spacing: 6.0,
263 - radius: 6.0,
264 - dotWidth: 6.0,
265 - dotHeight: 6.0,
266 - dotColor: Theme.of(context)
267 - .colorScheme
268 - .primary
269 - .withAlpha(100),
270 - activeDotColor: Theme.of(context).colorScheme.primary,
203 + );
204 + keyboardActions.add(
205 + KeyboardActionsItem(
206 + focusNode: _fiatAmountFocus,
207 + toolbarButtons: [(_) => KeyboardDoneButton()],
208 + ),
209 + );
210 + }
211 + return Stack(
212 + children: [
213 + KeyboardActions(
214 + config: KeyboardActionsConfig(
215 + keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
216 + keyboardBarColor: Theme.of(context).colorScheme.surface,
217 + nextFocus: false,
218 + actions: keyboardActions,
219 + ),
220 + child: Container(
221 + height: 0,
222 + color: Colors.transparent,
223 + ),
224 + ),
225 + GestureDetector(
226 + onLongPress: () => sendViewModel.balanceViewModel.isReversing =
227 + !sendViewModel.balanceViewModel.isReversing,
228 + onLongPressUp: () => sendViewModel.balanceViewModel.isReversing =
229 + !sendViewModel.balanceViewModel.isReversing,
230 + child: RepaintBoundary(
231 + child: Form(
232 + key: _formKey,
233 + child: ScrollableWithBottomSection(
234 + contentPadding: EdgeInsets.only(bottom: 24),
235 + content: FocusTraversalGroup(
236 + policy: OrderedTraversalPolicy(),
237 + child: Column(
238 + children: <Widget>[
239 + PageViewHeightAdaptable(
240 + controller: controller,
241 + children: sendCards,
242 + ),
243 + SizedBox(height: 10),
244 + Padding(
245 + padding: EdgeInsets.only(left: 24, right: 24, bottom: 10),
246 + child: Container(
247 + height: 10,
248 + child: Observer(
249 + builder: (_) {
250 + final count = sendViewModel.outputs.length;
251 +
252 + return count > 1
253 + ? Semantics(
254 + label: 'Page Indicator',
255 + hint: 'Swipe to change receiver',
256 + excludeSemantics: true,
257 + child: SmoothPageIndicator(
258 + controller: controller,
259 + count: count,
260 + effect: ScrollingDotsEffect(
261 + spacing: 6.0,
262 + radius: 6.0,
263 + dotWidth: 6.0,
264 + dotHeight: 6.0,
265 + dotColor: Theme.of(context)
266 + .colorScheme
267 + .primary
268 + .withAlpha(100),
269 + activeDotColor:
270 + Theme.of(context).colorScheme.primary,
271 + ),
272 ),
272 - ),
273 - )
274 - : Offstage();
275 - },
273 + )
274 + : Offstage();
275 + },
276 + ),
277 ),
278 ),
278 - ),
279 - Container(
280 - height: 40,
281 - width: double.infinity,
282 - padding: EdgeInsets.only(left: 24),
283 - child: SingleChildScrollView(
284 - scrollDirection: Axis.horizontal,
285 - child: Observer(
286 - builder: (_) {
287 - final templates = sendViewModel.templates;
288 - final itemCount = templates.length;
289 -
290 - return Row(
291 - children: <Widget>[
292 - AddTemplateButton(
293 - key: ValueKey('send_page_add_template_button_key'),
294 - onTap: () =>
295 - Navigator.of(context).pushNamed(Routes.sendTemplate),
296 - currentTemplatesLength: templates.length,
297 - ),
298 - ListView.builder(
299 - scrollDirection: Axis.horizontal,
300 - shrinkWrap: true,
301 - physics: NeverScrollableScrollPhysics(),
302 - itemCount: itemCount,
303 - itemBuilder: (context, index) {
304 - final template = templates[index];
305 - return TemplateTile(
306 - key: UniqueKey(),
307 - to: template.name,
308 - hasMultipleRecipients:
309 - template.additionalRecipients != null &&
310 - template.additionalRecipients!.length > 1,
311 - amount: template.isCurrencySelected
312 - ? template.amount
313 - : template.amountFiat,
314 - from: template.isCurrencySelected
315 - ? template.cryptoCurrency
316 - : template.fiatCurrency,
317 - onTap: () async {
318 - sendViewModel.state = LoadingTemplateExecutingState();
319 - if (template.additionalRecipients?.isNotEmpty ??
320 - false) {
321 - sendViewModel.clearOutputs();
322 -
323 - for (int i = 0;
324 - i < template.additionalRecipients!.length;
325 - i++) {
326 - Output output;
327 - try {
328 - output = sendViewModel.outputs[i];
329 - } catch (e) {
330 - sendViewModel.addOutput();
331 - output = sendViewModel.outputs[i];
279 + Container(
280 + height: 40,
281 + width: double.infinity,
282 + padding: EdgeInsets.only(left: 24),
283 + child: SingleChildScrollView(
284 + scrollDirection: Axis.horizontal,
285 + child: Observer(
286 + builder: (_) {
287 + final templates = sendViewModel.templates;
288 + final itemCount = templates.length;
289 +
290 + return Row(
291 + children: <Widget>[
292 + AddTemplateButton(
293 + key: ValueKey('send_page_add_template_button_key'),
294 + onTap: () => Navigator.of(context)
295 + .pushNamed(Routes.sendTemplate),
296 + currentTemplatesLength: templates.length,
297 + ),
298 + ListView.builder(
299 + scrollDirection: Axis.horizontal,
300 + shrinkWrap: true,
301 + physics: NeverScrollableScrollPhysics(),
302 + itemCount: itemCount,
303 + itemBuilder: (context, index) {
304 + final template = templates[index];
305 + return TemplateTile(
306 + key: UniqueKey(),
307 + to: template.name,
308 + hasMultipleRecipients:
309 + template.additionalRecipients != null &&
310 + template.additionalRecipients!.length > 1,
311 + amount: template.isCurrencySelected
312 + ? template.amount
313 + : template.amountFiat,
314 + from: template.isCurrencySelected
315 + ? template.cryptoCurrency
316 + : template.fiatCurrency,
317 + onTap: () async {
318 + sendViewModel.state =
319 + LoadingTemplateExecutingState();
320 + if (template.additionalRecipients?.isNotEmpty ??
321 + false) {
322 + sendViewModel.clearOutputs();
323 +
324 + for (int i = 0;
325 + i < template.additionalRecipients!.length;
326 + i++) {
327 + Output output;
328 + try {
329 + output = sendViewModel.outputs[i];
330 + } catch (e) {
331 + sendViewModel.addOutput();
332 + output = sendViewModel.outputs[i];
333 + }
334 +
335 + await _setInputsFromTemplate(
336 + context,
337 + output: output,
338 + template:
339 + template.additionalRecipients![i],
340 + );
341 }
333 -
342 + } else {
343 + final output = _defineCurrentOutput();
344 await _setInputsFromTemplate(
345 context,
346 output: output,
337 - template: template.additionalRecipients![i],
347 + template: template,
348 );
349 }
340 - } else {
341 - final output = _defineCurrentOutput();
342 - await _setInputsFromTemplate(
343 - context,
344 - output: output,
345 - template: template,
350 + sendViewModel.state = InitialExecutionState();
351 + },
352 + onRemove: () {
353 + showPopUp<void>(
354 + context: context,
355 + builder: (dialogContext) {
356 + return AlertWithTwoActions(
357 + alertTitle: S.of(context).template,
358 + alertContent: S
359 + .of(context)
360 + .confirm_delete_template,
361 + rightButtonText: S.of(context).delete,
362 + leftButtonText: S.of(context).cancel,
363 + actionRightButton: () {
364 + Navigator.of(dialogContext).pop();
365 + sendViewModel.sendTemplateViewModel
366 + .removeTemplate(
367 + template: template);
368 + },
369 + actionLeftButton: () =>
370 + Navigator.of(dialogContext).pop());
371 + },
372 );
347 - }
348 - sendViewModel.state = InitialExecutionState();
349 - },
350 - onRemove: () {
351 - showPopUp<void>(
352 - context: context,
353 - builder: (dialogContext) {
354 - return AlertWithTwoActions(
355 - alertTitle: S.of(context).template,
356 - alertContent:
357 - S.of(context).confirm_delete_template,
358 - rightButtonText: S.of(context).delete,
359 - leftButtonText: S.of(context).cancel,
360 - actionRightButton: () {
361 - Navigator.of(dialogContext).pop();
362 - sendViewModel.sendTemplateViewModel
363 - .removeTemplate(template: template);
364 - },
365 - actionLeftButton: () =>
366 - Navigator.of(dialogContext).pop());
367 - },
368 - );
369 - },
370 - );
371 - },
372 - ),
373 - ],
374 - );
375 - },
373 + },
374 + );
375 + },
376 + ),
377 + ],
378 + );
379 + },
380 + ),
381 ),
382 ),
378 - ),
379 - ],
383 + ],
384 + ),
385 ),
381 - ),
382 - bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
383 - bottomSection: Column(
384 - children: [
385 - if (sendViewModel.sendTemplateViewModel.hasMultiRecipient)
386 - Padding(
387 - padding: EdgeInsets.only(bottom: 12),
388 - child: PrimaryButton(
389 - key: ValueKey('send_page_add_receiver_button_key'),
390 - onPressed: () {
391 - sendViewModel.addOutput();
392 - Future.delayed(const Duration(milliseconds: 250), () {
393 - controller.jumpToPage(sendViewModel.outputs.length - 1);
394 - });
395 - },
396 - text: S.of(context).add_receiver,
397 - color: Colors.transparent,
398 - textColor: Theme.of(context).colorScheme.onSurfaceVariant,
399 - isDottedBorder: true,
400 - borderColor: Theme.of(context).colorScheme.outline,
401 - )),
402 - Observer(
403 - builder: (_) {
404 - return LoadingPrimaryButton(
405 - key: ValueKey('send_page_send_button_key'),
406 - onPressed: () async {
407 - //Request dummy node to get the focus out of the text fields
408 - FocusScope.of(context).requestFocus(FocusNode());
409 -
410 - if (sendViewModel.state is IsExecutingState) return;
411 - if (_formKey.currentState != null &&
412 - !_formKey.currentState!.validate()) {
413 - if (sendViewModel.outputs.length > 1) {
414 - showErrorValidationAlert(context);
415 - }
416 -
417 - return;
418 - }
419 -
420 - final hasInvalidItems = sendViewModel.outputs.any((item) =>
421 - item.address.isEmpty ||
422 - (item.cryptoAmount.isEmpty && !item.sendAll));
423 -
424 - if (hasInvalidItems) {
425 - showErrorValidationAlert(context);
426 - return;
427 - }
428 -
429 - if (sendViewModel.wallet.isHardwareWallet) {
430 - if (!sendViewModel.hardwareWalletViewModel!.isConnected(sendViewModel.walletType)) {
431 - await Navigator.of(context).pushNamed(Routes.connectDevices,
432 - arguments: ConnectDevicePageParams(
433 - walletType: sendViewModel.walletType,
434 - hardwareWalletType:
435 - sendViewModel.wallet.walletInfo.hardwareWalletType!,
436 - onConnectDevice: (BuildContext context, _) {
437 - sendViewModel.hardwareWalletViewModel!
438 - .initWallet(sendViewModel.wallet);
439 - Navigator.of(context).pop();
440 - },
441 - ));
442 - } else {
443 - sendViewModel.hardwareWalletViewModel!
444 - .initWallet(sendViewModel.wallet);
445 - }
446 - }
447 -
448 - if (sendViewModel.wallet.type == WalletType.monero) {
449 - var amount = Money.zero(sendViewModel.wallet.currency);
450 - for (var item in sendViewModel.outputs) {
451 - amount += item.cryptoAmountMoney;
452 - }
453 - if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
454 - await Navigator.of(context).pushNamed(Routes.urqrAnimatedPage,
455 - arguments: monero!.exportOutputsUR(sendViewModel.wallet));
456 - await Future.delayed(
457 - Duration(seconds: 1)); // wait for monero to refresh the state
386 + bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
387 + bottomSection: Column(
388 + children: [
389 + if (sendViewModel.sendTemplateViewModel.hasMultiRecipient)
390 + Padding(
391 + padding: EdgeInsets.only(bottom: 12),
392 + child: PrimaryButton(
393 + key: ValueKey('send_page_add_receiver_button_key'),
394 + onPressed: () {
395 + sendViewModel.addOutput();
396 + Future.delayed(const Duration(milliseconds: 250), () {
397 + controller.jumpToPage(sendViewModel.outputs.length - 1);
398 + });
399 + },
400 + text: S.of(context).add_receiver,
401 + color: Colors.transparent,
402 + textColor: Theme.of(context).colorScheme.onSurfaceVariant,
403 + isDottedBorder: true,
404 + borderColor: Theme.of(context).colorScheme.outline,
405 + )),
406 + Observer(
407 + builder: (_) {
408 + return LoadingPrimaryButton(
409 + key: ValueKey('send_page_send_button_key'),
410 + onPressed: () async {
411 + //Request dummy node to get the focus out of the text fields
412 + FocusScope.of(context).requestFocus(FocusNode());
413 +
414 + if (sendViewModel.state is IsExecutingState) return;
415 + if (_formKey.currentState != null &&
416 + !_formKey.currentState!.validate()) {
417 + if (sendViewModel.outputs.length > 1) {
418 + showErrorValidationAlert(context);
419 + }
420 +
421 + return;
422 }
459 - if (monero!.needExportOutputs(sendViewModel.wallet, amount)) {
423 +
424 + final hasInvalidItems = sendViewModel.outputs.any((item) =>
425 + item.address.isEmpty ||
426 + (item.cryptoAmount.isEmpty && !item.sendAll));
427 +
428 + if (hasInvalidItems) {
429 + showErrorValidationAlert(context);
430 return;
431 }
462 - }
463 -
464 - final check = sendViewModel.shouldDisplayTotp();
465 - authService.authenticateAction(
466 - context,
467 - conditionToDetermineIfToUse2FA: check,
468 - onAuthSuccess: (value) async {
469 - if (value) {
470 - await sendViewModel.createTransaction();
432 +
433 + if (sendViewModel.wallet.isHardwareWallet) {
434 + if (!sendViewModel.hardwareWalletViewModel!
435 + .isConnected(sendViewModel.walletType)) {
436 + await Navigator.of(context)
437 + .pushNamed(Routes.connectDevices,
438 + arguments: ConnectDevicePageParams(
439 + walletType: sendViewModel.walletType,
440 + hardwareWalletType: sendViewModel
441 + .wallet.walletInfo.hardwareWalletType!,
442 + onConnectDevice: (BuildContext context, _) {
443 + sendViewModel.hardwareWalletViewModel!
444 + .initWallet(sendViewModel.wallet);
445 + Navigator.of(context).pop();
446 + },
447 + ));
448 + } else {
449 + sendViewModel.hardwareWalletViewModel!
450 + .initWallet(sendViewModel.wallet);
451 }
472 - },
473 - );
474 - },
475 - text: _sendButtonText(context),
476 - color: Theme.of(context).colorScheme.primary,
477 - textColor: Theme.of(context).colorScheme.onPrimary,
478 - isLoading: sendViewModel.state is IsExecutingState ||
479 - sendViewModel.state is TransactionCommitting ||
480 - sendViewModel.state is IsAwaitingDeviceResponseState ||
481 - sendViewModel.state is LoadingTemplateExecutingState,
482 - isDisabled: !sendViewModel.isReadyForSend || sendViewModel.state is ExecutedSuccessfullyState,
483 - );
484 - },
485 - )
486 - ],
487 - )),
452 + }
453 +
454 + if (sendViewModel.wallet.type == WalletType.monero) {
455 + var amount = Money.zero(sendViewModel.wallet.currency);
456 + for (var item in sendViewModel.outputs) {
457 + amount += item.cryptoAmountMoney;
458 + }
459 + if (monero!
460 + .needExportOutputs(sendViewModel.wallet, amount)) {
461 + await Navigator.of(context).pushNamed(
462 + Routes.urqrAnimatedPage,
463 + arguments:
464 + monero!.exportOutputsUR(sendViewModel.wallet));
465 + await Future.delayed(Duration(
466 + seconds: 1)); // wait for monero to refresh the state
467 + }
468 + if (monero!
469 + .needExportOutputs(sendViewModel.wallet, amount)) {
470 + return;
471 + }
472 + }
473 +
474 + final check = sendViewModel.shouldDisplayTotp();
475 + authService.authenticateAction(
476 + context,
477 + conditionToDetermineIfToUse2FA: check,
478 + onAuthSuccess: (value) async {
479 + if (value) {
480 + await sendViewModel.createTransaction();
481 + }
482 + },
483 + );
484 + },
485 + text: _sendButtonText(context),
486 + color: Theme.of(context).colorScheme.primary,
487 + textColor: Theme.of(context).colorScheme.onPrimary,
488 + isLoading: sendViewModel.state is IsExecutingState ||
489 + sendViewModel.state is TransactionCommitting ||
490 + sendViewModel.state is IsAwaitingDeviceResponseState ||
491 + sendViewModel.state is LoadingTemplateExecutingState,
492 + isDisabled: !sendViewModel.isReadyForSend ||
493 + sendViewModel.state is ExecutedSuccessfullyState,
494 + );
495 + },
496 + )
497 + ],
498 + )),
499 + ),
500 ),
501 ),
490 - ),
491 - ],
492 - );
502 + ],
503 + );
504 + });
505 });
494 - }
495 - );
506 }
507
508 BuildContext? dialogContext;
@@ -505,7 +515,7 @@ class SendPage extends BasePage {
515 bitcoin!.updateFeeRates(sendViewModel.wallet);
516 }
517
508 - controller.addListener((){
518 + controller.addListener(() {
519 if (!controller.hasClients) return;
520 currentPage.value = controller.page!.round();
521 });
@@ -572,37 +582,36 @@ class SendPage extends BasePage {
582 isScrollControlled: true,
583 builder: (BuildContext bottomSheetContext) {
584 return Observer(
575 - builder: (_) => ConfirmSendingBottomSheet(
576 - key: ValueKey('send_page_confirm_sending_bottom_sheet_key'),
577 - titleText: S.of(bottomSheetContext).confirm_transaction,
578 - accessibleNavigationModeSlideActionButtonText: S.of(bottomSheetContext).send,
579 - footerType: FooterType.slideActionButton,
580 - isSlideActionEnabled: sendViewModel.isReadyForSend,
581 - walletType: sendViewModel.walletType,
582 - titleIconPath: sendViewModel.selectedCryptoCurrency.iconPath,
583 - currency: sendViewModel.selectedCryptoCurrency,
584 - amount: S.of(bottomSheetContext).send_amount,
585 - amountValue: sendViewModel.amountParsingProxy.getDisplayCryptoAmount(
586 - sendViewModel.pendingTransaction!.amountFormatted,
587 - sendViewModel.selectedCryptoCurrency),
588 - fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
589 - fee: isEVMCompatibleChain(sendViewModel.walletType)
590 - ? S.of(bottomSheetContext).send_estimated_fee
591 - : S.of(bottomSheetContext).send_fee,
592 - feeValue: "${sendViewModel.amountParsingProxy.getDisplayCryptoAmount(
593 - sendViewModel.pendingTransaction!.feeFormattedValue,
594 - sendViewModel.selectedCryptoCurrency)} ${sendViewModel.amountParsingProxy
595 - .getCryptoSymbol(sendViewModel.wallet.currency)}",
596 - feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
597 - outputs: sendViewModel.outputs,
598 - onSlideActionComplete: () async {
599 - Navigator.of(bottomSheetContext).pop(true);
600 - sendViewModel.commitTransaction(context);
601 - },
602 - change: sendViewModel.pendingTransaction!.change,
603 - isOpenCryptoPay: sendViewModel.ocpRequest != null,
604 - amountParsingProxy: sendViewModel.amountParsingProxy,
605 - ),);
585 + builder: (_) => ConfirmSendingBottomSheet(
586 + key: ValueKey('send_page_confirm_sending_bottom_sheet_key'),
587 + titleText: S.of(bottomSheetContext).confirm_transaction,
588 + accessibleNavigationModeSlideActionButtonText: S.of(bottomSheetContext).send,
589 + footerType: FooterType.slideActionButton,
590 + isSlideActionEnabled: sendViewModel.isReadyForSend,
591 + walletType: sendViewModel.walletType,
592 + titleIconPath: sendViewModel.selectedCryptoCurrency.iconPath,
593 + currency: sendViewModel.selectedCryptoCurrency,
594 + amount: S.of(bottomSheetContext).send_amount,
595 + amountValue: sendViewModel.amountParsingProxy.getDisplayCryptoAmount(
596 + sendViewModel.pendingTransaction!.amountFormatted,
597 + sendViewModel.selectedCryptoCurrency),
598 + fiatAmountValue: sendViewModel.pendingTransactionFiatAmountFormatted,
599 + fee: isEVMCompatibleChain(sendViewModel.walletType)
600 + ? S.of(bottomSheetContext).send_estimated_fee
601 + : S.of(bottomSheetContext).send_fee,
602 + feeValue:
603 + "${sendViewModel.amountParsingProxy.getDisplayCryptoAmount(sendViewModel.pendingTransaction!.feeFormattedValue, sendViewModel.selectedCryptoCurrency)} ${sendViewModel.amountParsingProxy.getCryptoSymbol(sendViewModel.wallet.currency)}",
604 + feeFiatAmount: sendViewModel.pendingTransactionFeeFiatAmountFormatted,
605 + outputs: sendViewModel.outputs,
606 + onSlideActionComplete: () async {
607 + Navigator.of(bottomSheetContext).pop(true);
608 + sendViewModel.commitTransaction(context);
609 + },
610 + change: sendViewModel.pendingTransaction!.change,
611 + isOpenCryptoPay: sendViewModel.ocpRequest != null,
612 + amountParsingProxy: sendViewModel.amountParsingProxy,
613 + ),
614 + );
615 },
616 );
617
lib/src/screens/send/widgets/choose_yat_address_alert.dart
+5 -6
@@ -90,12 +90,11 @@ class ChooseYatAddressButtonsState extends State<ChooseYatAddressButtons> {
90 maxLines: 1,
91 overflow: TextOverflow.ellipsis,
92 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
93 - fontSize: 15,
94 - fontWeight: FontWeight.w600,
95 -
96 - color: Theme.of(context).colorScheme.onSurfaceVariant,
97 - decoration: TextDecoration.none,
98 - ),
93 + fontSize: 15,
94 + fontWeight: FontWeight.w600,
95 + color: Theme.of(context).colorScheme.onSurfaceVariant,
96 + decoration: TextDecoration.none,
97 + ),
98 ),
99 )
100 ],
lib/src/screens/send/widgets/send_card.dart
+9 -8
@@ -640,8 +640,7 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
640 onPushAddressBookButton: (context) async {
641 output.resetParsedAddress();
642 },
643 - onSelectedContact: (contact) {
644 - },
643 + onSelectedContact: (contact) {},
644 validator: validator,
645 selectedCurrency: sendViewModel.selectedCryptoCurrency,
646 );
@@ -671,8 +670,10 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
670 sendAllButtonKey: ValueKey('send_page_send_all_button_key'),
671 currencyAmountTextFieldWidgetKey:
672 ValueKey('send_page_crypto_currency_amount_textfield_widget_key'),
674 - selectedCurrency: output.useSatoshi ? "SATS" : sendViewModel.selectedCryptoCurrency.title,
675 - selectedCurrencyDecimals: output.useSatoshi ? 0 : sendViewModel.selectedCryptoCurrency.decimals,
673 + selectedCurrency:
674 + output.useSatoshi ? "SATS" : sendViewModel.selectedCryptoCurrency.title,
675 + selectedCurrencyDecimals:
676 + output.useSatoshi ? 0 : sendViewModel.selectedCryptoCurrency.decimals,
677 amountFocusNode: widget.cryptoAmountFocus,
678 amountController: cryptoAmountController,
679 isAmountEditable: true,
@@ -976,8 +977,8 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
977 output.setSendAll(await sendViewModel.sendingBalance);
978 }
979
979 - output.setCryptoAmount(sendViewModel.amountParsingProxy
980 - .getCanonicalCryptoAmount(cryptoAmountController.text, sendViewModel.selectedCryptoCurrency));
980 + output.setCryptoAmount(sendViewModel.amountParsingProxy.getCanonicalCryptoAmount(
981 + cryptoAmountController.text, sendViewModel.selectedCryptoCurrency));
982 });
983
984 reaction((_) => output.fiatAmount, (String amount) {
@@ -991,8 +992,8 @@ class SendCardState extends State<SendCard> with AutomaticKeepAliveClientMixin<S
992 output.sendAll = false;
993 }
994
994 - final cryptoAmount = sendViewModel.amountParsingProxy
995 - .getCanonicalCryptoAmount(cryptoAmountController.text, sendViewModel.selectedCryptoCurrency);
995 + final cryptoAmount = sendViewModel.amountParsingProxy.getCanonicalCryptoAmount(
996 + cryptoAmountController.text, sendViewModel.selectedCryptoCurrency);
997 if (amount != cryptoAmount) {
998 cryptoAmountController.text = sendViewModel.amountParsingProxy
999 .getDisplayCryptoAmount(amount, sendViewModel.selectedCryptoCurrency);
lib/src/screens/settings/attributes.dart
+1 -1
@@ -1 +1 @@
1 -enum Attributes {arrow, header, link, switcher, widget, rawWidget}
\ No newline at end of file
1 +enum Attributes { arrow, header, link, switcher, widget, rawWidget }
lib/src/screens/settings/connection_sync_page.dart
+153 -158
@@ -43,89 +43,87 @@ class ConnectionSyncPage extends BasePage {
43 mainAxisSize: MainAxisSize.min,
44 children: [
45 Observer(
46 - builder: (context) =>
47 - NewListSections(
48 - sections: {
49 - "": [
50 - if (FeatureFlag.isInAppTorEnabled)
51 - ListItemToggle(
52 - keyValue: "enable_builtin_tor",
53 - label: S.of(context).enable_builtin_tor,
54 - value: _connectionSyncViewModel.builtinTor,
55 - onChanged: (val) {
56 - _connectionSyncViewModel.setBuiltinTor(val, context);
57 - }),
58 - ListItemToggle(
59 - keyValue: "disable_automatic_exchange_status_updates",
60 - label: S.of(context).disable_automatic_exchange_status_updates,
61 - value: _connectionSyncViewModel.disableAutomaticExchangeStatusUpdates,
62 - onChanged: (val) {
63 - _connectionSyncViewModel.setDisableAutomaticExchangeStatusUpdates(val);
64 - }),
65 - if (_connectionSyncViewModel.canUseBlinkProtection)
66 - ListItemToggle(
67 - keyValue: "can_use_blink_protection",
68 - label: S.of(context).use_blink_protection,
69 - value: _connectionSyncViewModel.useBlinkProtection,
70 - onChanged: (val) {
71 - _connectionSyncViewModel.setUseBlinkProtection(val);
72 - }),
73 - if (_connectionSyncViewModel.canUseEtherscan)
74 - ListItemToggle(
75 - keyValue: "can_use_etherscan",
76 - label: S.of(context).etherscan_history,
77 - value: _connectionSyncViewModel.useEtherscan,
78 - onChanged: (val) {
79 - _connectionSyncViewModel.setUseEtherscan(val);
80 - }),
81 - if (_connectionSyncViewModel.canUsePolygonScan)
82 - ListItemToggle(
83 - keyValue: "can_use_polygonscan",
84 - label: S.of(context).polygonscan_history,
85 - value: _connectionSyncViewModel.usePolygonScan,
86 - onChanged: (val) {
87 - _connectionSyncViewModel.setUsePolygonScan(val);
88 - }),
89 - if (_connectionSyncViewModel.canUseBaseScan)
90 - ListItemToggle(
91 - keyValue: "can_use_basescan",
92 - label: S.of(context).basescan_history,
93 - value: _connectionSyncViewModel.canUseBaseScan,
94 - onChanged: (val) {
95 - _connectionSyncViewModel.setUseBaseScan(val);
96 - }),
97 - if (_connectionSyncViewModel.canUseArbiScan)
98 - ListItemToggle(
99 - keyValue: "can_use_arbiscan",
100 - label: S.of(context).arbiscan_history,
101 - value: _connectionSyncViewModel.useArbiScan,
102 - onChanged: (val) {
103 - _connectionSyncViewModel.setUseArbiScan(val);
104 - }),
105 - if (_connectionSyncViewModel.canUseBscScan)
106 - ListItemToggle(
107 - keyValue: "can_use_bscscan",
108 - label: S.of(context).bscscan_history,
109 - value: _connectionSyncViewModel.useBscScan,
110 - onChanged: (val) {
111 - _connectionSyncViewModel.setUseBscScan(val);
112 - }),
113 - if (_connectionSyncViewModel.canUseTronGrid)
114 - ListItemToggle(
115 - keyValue: "can_use_trongrid",
116 - label: S.of(context).trongrid_history,
117 - value: _connectionSyncViewModel.useTronGrid,
118 - onChanged: (val) {
119 - _connectionSyncViewModel.setUseTronGrid(val);
120 - }),
121 - if (_connectionSyncViewModel.canUseMempoolFeeAPI)
122 - ListItemToggle(
123 - keyValue: "enable_mempool_api",
124 - label: S.of(context).enable_mempool_api,
125 - value: _connectionSyncViewModel.useMempoolFeeAPI,
126 - onChanged: (bool isEnabled) async {
127 - if (!isEnabled) {
128 - final bool confirmation = await showPopUp<bool>(
46 + builder: (context) => NewListSections(sections: {
47 + "": [
48 + if (FeatureFlag.isInAppTorEnabled)
49 + ListItemToggle(
50 + keyValue: "enable_builtin_tor",
51 + label: S.of(context).enable_builtin_tor,
52 + value: _connectionSyncViewModel.builtinTor,
53 + onChanged: (val) {
54 + _connectionSyncViewModel.setBuiltinTor(val, context);
55 + }),
56 + ListItemToggle(
57 + keyValue: "disable_automatic_exchange_status_updates",
58 + label: S.of(context).disable_automatic_exchange_status_updates,
59 + value: _connectionSyncViewModel.disableAutomaticExchangeStatusUpdates,
60 + onChanged: (val) {
61 + _connectionSyncViewModel.setDisableAutomaticExchangeStatusUpdates(val);
62 + }),
63 + if (_connectionSyncViewModel.canUseBlinkProtection)
64 + ListItemToggle(
65 + keyValue: "can_use_blink_protection",
66 + label: S.of(context).use_blink_protection,
67 + value: _connectionSyncViewModel.useBlinkProtection,
68 + onChanged: (val) {
69 + _connectionSyncViewModel.setUseBlinkProtection(val);
70 + }),
71 + if (_connectionSyncViewModel.canUseEtherscan)
72 + ListItemToggle(
73 + keyValue: "can_use_etherscan",
74 + label: S.of(context).etherscan_history,
75 + value: _connectionSyncViewModel.useEtherscan,
76 + onChanged: (val) {
77 + _connectionSyncViewModel.setUseEtherscan(val);
78 + }),
79 + if (_connectionSyncViewModel.canUsePolygonScan)
80 + ListItemToggle(
81 + keyValue: "can_use_polygonscan",
82 + label: S.of(context).polygonscan_history,
83 + value: _connectionSyncViewModel.usePolygonScan,
84 + onChanged: (val) {
85 + _connectionSyncViewModel.setUsePolygonScan(val);
86 + }),
87 + if (_connectionSyncViewModel.canUseBaseScan)
88 + ListItemToggle(
89 + keyValue: "can_use_basescan",
90 + label: S.of(context).basescan_history,
91 + value: _connectionSyncViewModel.canUseBaseScan,
92 + onChanged: (val) {
93 + _connectionSyncViewModel.setUseBaseScan(val);
94 + }),
95 + if (_connectionSyncViewModel.canUseArbiScan)
96 + ListItemToggle(
97 + keyValue: "can_use_arbiscan",
98 + label: S.of(context).arbiscan_history,
99 + value: _connectionSyncViewModel.useArbiScan,
100 + onChanged: (val) {
101 + _connectionSyncViewModel.setUseArbiScan(val);
102 + }),
103 + if (_connectionSyncViewModel.canUseBscScan)
104 + ListItemToggle(
105 + keyValue: "can_use_bscscan",
106 + label: S.of(context).bscscan_history,
107 + value: _connectionSyncViewModel.useBscScan,
108 + onChanged: (val) {
109 + _connectionSyncViewModel.setUseBscScan(val);
110 + }),
111 + if (_connectionSyncViewModel.canUseTronGrid)
112 + ListItemToggle(
113 + keyValue: "can_use_trongrid",
114 + label: S.of(context).trongrid_history,
115 + value: _connectionSyncViewModel.useTronGrid,
116 + onChanged: (val) {
117 + _connectionSyncViewModel.setUseTronGrid(val);
118 + }),
119 + if (_connectionSyncViewModel.canUseMempoolFeeAPI)
120 + ListItemToggle(
121 + keyValue: "enable_mempool_api",
122 + label: S.of(context).enable_mempool_api,
123 + value: _connectionSyncViewModel.useMempoolFeeAPI,
124 + onChanged: (bool isEnabled) async {
125 + if (!isEnabled) {
126 + final bool confirmation = await showPopUp<bool>(
127 context: context,
128 builder: (BuildContext context) {
129 return AlertWithTwoActions(
@@ -133,91 +131,88 @@ class ConnectionSyncPage extends BasePage {
131 alertContent: S.of(context).disable_fee_api_warning,
132 rightButtonText: S.of(context).confirm,
133 leftButtonText: S.of(context).cancel,
136 - actionRightButton: () => Navigator.of(context).pop(true),
137 - actionLeftButton: () => Navigator.of(context).pop(false));
134 + actionRightButton: () =>
135 + Navigator.of(context).pop(true),
136 + actionLeftButton: () =>
137 + Navigator.of(context).pop(false));
138 }) ??
139 - false;
140 - if (confirmation) {
141 - _connectionSyncViewModel.setUseMempoolFeeAPI(isEnabled);
142 - }
143 - return;
144 - }
145 -
139 + false;
140 + if (confirmation) {
141 _connectionSyncViewModel.setUseMempoolFeeAPI(isEnabled);
147 - }),
148 - if (Platform.isAndroid && FeatureFlag.isBackgroundSyncEnabled)
149 - ListItemRegularRow(
150 - keyValue: "background_sync",
151 - label: S.of(context).background_sync,
152 - onTap: () => Navigator.of(context).pushNamed(Routes.backgroundSync)
153 - ),
154 - if (_connectionSyncViewModel.hasPowNodes)
155 - ListItemRegularRow(
156 - keyValue: "manage_pow_nodes",
157 - label: S.of(context).manage_pow_nodes,
158 - onTap: () => Navigator.of(context).pushNamed(Routes.managePowNodes),
159 - ),
160 - ListItemSelector(
161 - keyValue: "fiat_api",
162 - label: S.of(context).fiat_api,
163 - options: [_connectionSyncViewModel.fiatApiMode.title],
164 - onTap: () async {
165 - final items = FiatApiMode.all;
142 + }
143 + return;
144 + }
145 +
146 + _connectionSyncViewModel.setUseMempoolFeeAPI(isEnabled);
147 + }),
148 + if (Platform.isAndroid && FeatureFlag.isBackgroundSyncEnabled)
149 + ListItemRegularRow(
150 + keyValue: "background_sync",
151 + label: S.of(context).background_sync,
152 + onTap: () => Navigator.of(context).pushNamed(Routes.backgroundSync)),
153 + if (_connectionSyncViewModel.hasPowNodes)
154 + ListItemRegularRow(
155 + keyValue: "manage_pow_nodes",
156 + label: S.of(context).manage_pow_nodes,
157 + onTap: () => Navigator.of(context).pushNamed(Routes.managePowNodes),
158 + ),
159 + ListItemSelector(
160 + keyValue: "fiat_api",
161 + label: S.of(context).fiat_api,
162 + options: [_connectionSyncViewModel.fiatApiMode.title],
163 + onTap: () async {
164 + final items = FiatApiMode.all;
165
167 - final selectedAtIndex =
166 + final selectedAtIndex =
167 items.indexOf(_connectionSyncViewModel.fiatApiMode);
168
170 - await showPopUp<void>(
171 - context: context,
172 - builder: (_) => Picker(
173 - items: items,
174 - selectedAtIndex: selectedAtIndex,
175 - mainAxisAlignment: MainAxisAlignment.start,
176 - onItemSelected: (FiatApiMode fiatApiMode) {
177 - _connectionSyncViewModel.setFiatMode(fiatApiMode);
178 - },
179 - isSeparated: false,
180 - ),
181 - );
182 - }),
183 - ListItemSelector(
184 - keyValue: "swap",
185 - label: S.of(context).swap,
186 - options: [_connectionSyncViewModel.exchangeStatus.title],
187 - onTap: () async {
188 - final items = ExchangeApiMode.all;
169 + await showPopUp<void>(
170 + context: context,
171 + builder: (_) => Picker(
172 + items: items,
173 + selectedAtIndex: selectedAtIndex,
174 + mainAxisAlignment: MainAxisAlignment.start,
175 + onItemSelected: (FiatApiMode fiatApiMode) {
176 + _connectionSyncViewModel.setFiatMode(fiatApiMode);
177 + },
178 + isSeparated: false,
179 + ),
180 + );
181 + }),
182 + ListItemSelector(
183 + keyValue: "swap",
184 + label: S.of(context).swap,
185 + options: [_connectionSyncViewModel.exchangeStatus.title],
186 + onTap: () async {
187 + final items = ExchangeApiMode.all;
188
190 - final selectedAtIndex =
189 + final selectedAtIndex =
190 items.indexOf(_connectionSyncViewModel.exchangeStatus);
191
193 - await showPopUp<void>(
194 - context: context,
195 - builder: (_) => Picker(
196 - items: items,
197 - selectedAtIndex: selectedAtIndex,
198 - mainAxisAlignment: MainAxisAlignment.start,
199 - onItemSelected: (ExchangeApiMode mode) {
200 - _connectionSyncViewModel.setExchangeApiMode(mode);
201 - },
202 - isSeparated: false,
203 - ),
204 - );
205 - }),
206 - ListItemRegularRow(
207 - keyValue: "domain_lookups",
208 - label: S.of(context).domain_looks_up,
209 - onTap: () => Navigator.of(context).pushNamed(Routes.domainLookupsPage)
210 - ),
211 - if(_connectionSyncViewModel.hasRescan)
212 - ListItemRegularRow(
192 + await showPopUp<void>(
193 + context: context,
194 + builder: (_) => Picker(
195 + items: items,
196 + selectedAtIndex: selectedAtIndex,
197 + mainAxisAlignment: MainAxisAlignment.start,
198 + onItemSelected: (ExchangeApiMode mode) {
199 + _connectionSyncViewModel.setExchangeApiMode(mode);
200 + },
201 + isSeparated: false,
202 + ),
203 + );
204 + }),
205 + ListItemRegularRow(
206 + keyValue: "domain_lookups",
207 + label: S.of(context).domain_looks_up,
208 + onTap: () => Navigator.of(context).pushNamed(Routes.domainLookupsPage)),
209 + if (_connectionSyncViewModel.hasRescan)
210 + ListItemRegularRow(
211 keyValue: "rescan",
212 label: S.of(context).rescan,
215 - onTap: ()=>Navigator.of(context).pushNamed(Routes.rescan)
216 - )
217 - ],
218 - }
219 - )
220 - ),
213 + onTap: () => Navigator.of(context).pushNamed(Routes.rescan))
214 + ],
215 + })),
216 ],
217 ),
218 );
lib/src/screens/settings/desktop_settings/desktop_settings_page.dart
+5 -7
@@ -61,9 +61,9 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
61 }
62
63 if ((!widget.dashboardViewModel.isMoneroViewOnly &&
64 - item.name(context) == S.of(context).export_outputs) ||
65 - (!widget.dashboardViewModel.hasMweb &&
66 - item.name(context) == S.of(context).litecoin_mweb_settings)) {
64 + item.name(context) == S.of(context).export_outputs) ||
65 + (!widget.dashboardViewModel.hasMweb &&
66 + item.name(context) == S.of(context).litecoin_mweb_settings)) {
67 return Container();
68 }
69
@@ -103,11 +103,9 @@ class _DesktopSettingsPageState extends State<DesktopSettingsPage> {
103 key: _settingsNavigatorKey,
104 initialRoute: Routes.empty_no_route,
105 onGenerateRoute: (settings) => Router.createRoute(settings),
106 - onGenerateInitialRoutes:
107 - (NavigatorState navigator, String initialRouteName) {
106 + onGenerateInitialRoutes: (NavigatorState navigator, String initialRouteName) {
107 return [
109 - navigator
110 - .widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!
108 + navigator.widget.onGenerateRoute!(RouteSettings(name: initialRouteName))!
109 ];
110 },
111 ),
lib/src/screens/settings/display_settings_page.dart
+174 -176
@@ -27,7 +27,6 @@ import 'package:image_picker/image_picker.dart';
27 class DisplaySettingsPage extends StatelessWidget {
28 DisplaySettingsPage(this._displaySettingsViewModel);
29
30 -
30 final DisplaySettingsViewModel _displaySettingsViewModel;
31
32 @override
@@ -38,198 +37,197 @@ class DisplaySettingsPage extends StatelessWidget {
37 leadingIcon: Icon(Icons.arrow_back_ios_new),
38 onLeadingPressed: () => Navigator.of(context).pop(),
39 ),
41 - content: Column(
42 - spacing: 16,
43 - crossAxisAlignment: CrossAxisAlignment.start,
44 - children: [
45 - if (responsiveLayoutUtil.shouldRenderMobileUI &&
46 - DeviceInfo.instance.isMobile) ...[
47 - Padding(
48 - padding: const EdgeInsets.only(left: 14, top: 14),
49 - child: Text(
50 - S.of(context).appearance,
51 - style: Theme.of(context).textTheme.labelLarge?.copyWith(
40 + content: Column(
41 + spacing: 16,
42 + crossAxisAlignment: CrossAxisAlignment.start,
43 + children: [
44 + if (responsiveLayoutUtil.shouldRenderMobileUI && DeviceInfo.instance.isMobile) ...[
45 + Padding(
46 + padding: const EdgeInsets.only(left: 14, top: 14),
47 + child: Text(
48 + S.of(context).appearance,
49 + style: Theme.of(context).textTheme.labelLarge?.copyWith(
50 height: 0.2,
51 color: Theme.of(context).colorScheme.onSurfaceVariant,
52 ),
53 + ),
54 + ),
55 + Container(
56 + decoration: ShapeDecoration(
57 + color: Theme.of(context).colorScheme.surfaceContainerHigh,
58 + shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(18))),
59 + child: Column(
60 + children: [
61 + SettingsChoicesCell(
62 + ChoicesListItem<ThemeMode>(
63 + title: "",
64 + items: ThemeMode.values,
65 + selectedItem: _displaySettingsViewModel.themeMode,
66 + onItemSelected: (ThemeMode themeMode) =>
67 + _displaySettingsViewModel.setThemeMode(themeMode),
68 + displayItem: (ThemeMode themeMode) {
69 + return themeMode.name[0].toUpperCase() +
70 + themeMode.name.substring(1).toLowerCase();
71 + },
72 + ),
73 + useGenericColor: false,
74 + padding: EdgeInsets.all(14),
75 ),
56 - ),
57 - Container(
58 - decoration: ShapeDecoration(
59 - color: Theme.of(context).colorScheme.surfaceContainerHigh,
60 - shape: RoundedSuperellipseBorder(
61 - borderRadius: BorderRadius.circular(18))),
62 - child: Column(
63 - children: [
64 - SettingsChoicesCell(
65 - ChoicesListItem<ThemeMode>(
66 - title: "",
67 - items: ThemeMode.values,
68 - selectedItem: _displaySettingsViewModel.themeMode,
69 - onItemSelected: (ThemeMode themeMode) =>
70 - _displaySettingsViewModel.setThemeMode(themeMode),
71 - displayItem: (ThemeMode themeMode) {
72 - return themeMode.name[0].toUpperCase() +
73 - themeMode.name.substring(1).toLowerCase();
74 - },
76 + Container(
77 + decoration: ShapeDecoration(
78 + color: Theme.of(context).colorScheme.surfaceContainer,
79 + shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(18))),
80 + child: Column(
81 + children: [
82 + Semantics(
83 + label: S.of(context).color_theme,
84 + child: SettingsThemeChoicesCell(_displaySettingsViewModel),
85 ),
76 - useGenericColor: false,
77 - padding: EdgeInsets.all(14),
78 - ),
79 - Container(
80 - decoration: ShapeDecoration(
81 - color: Theme.of(context).colorScheme.surfaceContainer,
82 - shape: RoundedSuperellipseBorder(
83 - borderRadius: BorderRadius.circular(18))),
84 - child: Column(
85 - children: [
86 - Semantics(
87 - label: S.of(context).color_theme,
88 - child: SettingsThemeChoicesCell(_displaySettingsViewModel),
89 - ),
90 - ],
91 - ),
92 - ),
93 - ],
86 + ],
87 + ),
88 ),
95 - ),
96 - ],
97 - Observer(
98 - builder: (_) => NewListSections(
99 - sections: {
100 - "": [
101 - ListItemToggle(
102 - keyValue: "apps",
103 - label: S.of(context).apps,
104 - value: _displaySettingsViewModel.shouldShowMarketPlaceInDashboard,
105 - onChanged: (val) {
106 - _displaySettingsViewModel.setShouldShowMarketPlaceInDashbaord(val);
107 - }),
108 - ListItemToggle(
109 - keyValue: "display_settings_show_address_book_popup",
110 - label: S.of(context).show_address_book_popup,
111 - value: _displaySettingsViewModel.showAddressBookPopup,
112 - onChanged: (val) {
113 - _displaySettingsViewModel.setShowAddressBookPopup(val);
114 - }),
115 - ListItemToggle(
116 - keyValue: "display_settings_disable_buy_button",
117 - label: S.of(context).disable_buy,
118 - value: _displaySettingsViewModel.disableTradeOption,
119 - onChanged: (val) {
120 - _displaySettingsViewModel.setDisableTradeOption(val);
121 - }),
122 - if (_displaySettingsViewModel.showZcashCardSetting)
123 - ListItemToggle(
124 - keyValue: "display_settings_show_zcashcard",
125 - label: S.of(context).show_zcash_card,
126 - value: _displaySettingsViewModel.showZcashCard,
127 - onChanged: (val) {
128 - _displaySettingsViewModel.setShowZcashCard(val);
129 - }),
130 - ListItemSelector(
131 - keyValue: "display_settings_sync_status_display",
132 - label: S.of(context).sync_status_display_mode,
133 - options: [_displaySettingsViewModel.syncStatusDisplayMode.title],
134 - onTap: () async {
135 - final items = SyncStatusDisplayMode.values.toList();
89 + ],
90 + ),
91 + ),
92 + ],
93 + Observer(
94 + builder: (_) => NewListSections(
95 + sections: {
96 + "": [
97 + ListItemToggle(
98 + keyValue: "apps",
99 + label: S.of(context).apps,
100 + value: _displaySettingsViewModel.shouldShowMarketPlaceInDashboard,
101 + onChanged: (val) {
102 + _displaySettingsViewModel.setShouldShowMarketPlaceInDashbaord(val);
103 + }),
104 + ListItemToggle(
105 + keyValue: "display_settings_show_address_book_popup",
106 + label: S.of(context).show_address_book_popup,
107 + value: _displaySettingsViewModel.showAddressBookPopup,
108 + onChanged: (val) {
109 + _displaySettingsViewModel.setShowAddressBookPopup(val);
110 + }),
111 + ListItemToggle(
112 + keyValue: "display_settings_disable_buy_button",
113 + label: S.of(context).disable_buy,
114 + value: _displaySettingsViewModel.disableTradeOption,
115 + onChanged: (val) {
116 + _displaySettingsViewModel.setDisableTradeOption(val);
117 + }),
118 + if (_displaySettingsViewModel.showZcashCardSetting)
119 + ListItemToggle(
120 + keyValue: "display_settings_show_zcashcard",
121 + label: S.of(context).show_zcash_card,
122 + value: _displaySettingsViewModel.showZcashCard,
123 + onChanged: (val) {
124 + _displaySettingsViewModel.setShowZcashCard(val);
125 + }),
126 + ListItemSelector(
127 + keyValue: "display_settings_sync_status_display",
128 + label: S.of(context).sync_status_display_mode,
129 + options: [_displaySettingsViewModel.syncStatusDisplayMode.title],
130 + onTap: () async {
131 + final items = SyncStatusDisplayMode.values.toList();
132
137 - final selectedAtIndex =
133 + final selectedAtIndex =
134 items.indexOf(_displaySettingsViewModel.syncStatusDisplayMode);
135
140 - await showPopUp<void>(
141 - context: context,
142 - builder: (_) => Picker(
143 - items: items,
144 - selectedAtIndex: selectedAtIndex,
145 - mainAxisAlignment: MainAxisAlignment.start,
146 - onItemSelected: (SyncStatusDisplayMode mode) {
147 - _displaySettingsViewModel.setSyncStatusDisplayMode(mode);
148 - },
149 - displayItem: (SyncStatusDisplayMode mode) => mode.title,
150 - isSeparated: false,
151 - ),
152 - );
153 - }),
154 - if (_displaySettingsViewModel.showDisplayAmountsInSatoshiSetting)
155 - ListItemRegularRow(
156 - keyValue: "display_settings_bitcoin_amount_display",
157 - label: S.of(context).bitcoin_amount_display,
158 - trailingText: _displaySettingsViewModel.displayAmountsInSatoshi.title,
159 - onTap: () async {
160 - final items = BitcoinAmountDisplayMode.all;
136 + await showPopUp<void>(
137 + context: context,
138 + builder: (_) => Picker(
139 + items: items,
140 + selectedAtIndex: selectedAtIndex,
141 + mainAxisAlignment: MainAxisAlignment.start,
142 + onItemSelected: (SyncStatusDisplayMode mode) {
143 + _displaySettingsViewModel.setSyncStatusDisplayMode(mode);
144 + },
145 + displayItem: (SyncStatusDisplayMode mode) => mode.title,
146 + isSeparated: false,
147 + ),
148 + );
149 + }),
150 + if (_displaySettingsViewModel.showDisplayAmountsInSatoshiSetting)
151 + ListItemRegularRow(
152 + keyValue: "display_settings_bitcoin_amount_display",
153 + label: S.of(context).bitcoin_amount_display,
154 + trailingText: _displaySettingsViewModel.displayAmountsInSatoshi.title,
155 + onTap: () async {
156 + final items = BitcoinAmountDisplayMode.all;
157
162 - final selectedAtIndex =
158 + final selectedAtIndex =
159 items.indexOf(_displaySettingsViewModel.displayAmountsInSatoshi);
160
165 - await showPopUp<void>(
166 - context: context,
167 - builder: (_) => Picker(
168 - items: items,
169 - selectedAtIndex: selectedAtIndex,
170 - mainAxisAlignment: MainAxisAlignment.start,
171 - onItemSelected: _displaySettingsViewModel.setDisplayAmountsInSatoshi,
172 - displayItem: (BitcoinAmountDisplayMode mode) => mode.title,
173 - isSeparated: false,
174 - ),
175 - );
176 - }),
177 - if (!_displaySettingsViewModel.disabledFiatApiMode)
178 - ListItemSelector(
179 - keyValue: "display_settings_fiat_currency",
180 - label: S.of(context).settings_currency,
181 - options: [_displaySettingsViewModel.fiatCurrency.title],
182 - onTap: () => FiatCurrencyPickerSheet.show(
183 - context: context,
184 - selected: _displaySettingsViewModel.fiatCurrency,
185 - onSelected: _displaySettingsViewModel.setFiatCurrency,
186 - )),
187 - ListItemSelector(
188 - keyValue: "display_settings_language",
189 - label: S.of(context).settings_change_language,
190 - options: [LanguageService.list[_displaySettingsViewModel.languageCode] ?? ''],
191 - onTap: () async {
192 - final items = LanguageService.list.keys.toList();
161 + await showPopUp<void>(
162 + context: context,
163 + builder: (_) => Picker(
164 + items: items,
165 + selectedAtIndex: selectedAtIndex,
166 + mainAxisAlignment: MainAxisAlignment.start,
167 + onItemSelected: _displaySettingsViewModel.setDisplayAmountsInSatoshi,
168 + displayItem: (BitcoinAmountDisplayMode mode) => mode.title,
169 + isSeparated: false,
170 + ),
171 + );
172 + }),
173 + if (!_displaySettingsViewModel.disabledFiatApiMode)
174 + ListItemSelector(
175 + keyValue: "display_settings_fiat_currency",
176 + label: S.of(context).settings_currency,
177 + options: [_displaySettingsViewModel.fiatCurrency.title],
178 + onTap: () => FiatCurrencyPickerSheet.show(
179 + context: context,
180 + selected: _displaySettingsViewModel.fiatCurrency,
181 + onSelected: _displaySettingsViewModel.setFiatCurrency,
182 + )),
183 + ListItemSelector(
184 + keyValue: "display_settings_language",
185 + label: S.of(context).settings_change_language,
186 + options: [LanguageService.list[_displaySettingsViewModel.languageCode] ?? ''],
187 + onTap: () async {
188 + final items = LanguageService.list.keys.toList();
189
194 - final selectedAtIndex =
190 + final selectedAtIndex =
191 items.indexOf(_displaySettingsViewModel.languageCode);
192
197 - await showPopUp<void>(
198 - context: context,
199 - builder: (_) => Picker(
200 - displayItem: (dynamic code) {
201 - return LanguageService.list[code] ?? '';
202 - },
203 - items: items,
204 - selectedAtIndex: selectedAtIndex,
205 - mainAxisAlignment: MainAxisAlignment.start,
206 - onItemSelected: _displaySettingsViewModel.onLanguageSelected,
207 - images: LanguageService.list.keys
208 - .map((e) => Image.asset(
193 + await showPopUp<void>(
194 + context: context,
195 + builder: (_) => Picker(
196 + displayItem: (dynamic code) {
197 + return LanguageService.list[code] ?? '';
198 + },
199 + items: items,
200 + selectedAtIndex: selectedAtIndex,
201 + mainAxisAlignment: MainAxisAlignment.start,
202 + onItemSelected: _displaySettingsViewModel.onLanguageSelected,
203 + images: LanguageService.list.keys
204 + .map((e) => Image.asset(
205 "assets/images/flags/${LanguageService.localeCountryCode[e]}.png"))
210 - .toList(),
211 - hintText: S.of(context).search_language,
212 - matchingCriteria: (String code, String searchText) {
213 - return LanguageService.list[code]?.toLowerCase().contains(searchText) ?? false;
214 - },
215 - isSeparated: true,
216 -
217 - ),
218 - );
219 - }),
220 - ],
221 - },
222 - ),
223 - ),
224 - if (FeatureFlag.customBackgroundEnabled)
225 - StandardListRow(
226 - title: "Custom background",
227 - isSelected: false,
228 - onTap: (_) => _pickImage(context),
229 - ),
230 - ],
206 + .toList(),
207 + hintText: S.of(context).search_language,
208 + matchingCriteria: (String code, String searchText) {
209 + return LanguageService.list[code]
210 + ?.toLowerCase()
211 + .contains(searchText) ??
212 + false;
213 + },
214 + isSeparated: true,
215 + ),
216 + );
217 + }),
218 + ],
219 + },
220 + ),
221 ),
232 - );
222 + if (FeatureFlag.customBackgroundEnabled)
223 + StandardListRow(
224 + title: "Custom background",
225 + isSelected: false,
226 + onTap: (_) => _pickImage(context),
227 + ),
228 + ],
229 + ),
230 + );
231 }
232
233 // Function to pick an image from the gallery
lib/src/screens/settings/domain_lookups_page.dart
+7 -5
@@ -25,11 +25,13 @@ class DomainLookupsPage extends BasePage {
25 .map(
26 (source) => SettingsSwitcherCell(
27 title: source.label,
28 - leading: source.iconPath.isNotEmpty ? CakeImageWidget(
29 - imageUrl: source.iconPath,
30 - width: 24,
31 - height: 24,
32 - ) : SizedBox(width: 24, height: 24),
28 + leading: source.iconPath.isNotEmpty
29 + ? CakeImageWidget(
30 + imageUrl: source.iconPath,
31 + width: 24,
32 + height: 24,
33 + )
34 + : SizedBox(width: 24, height: 24),
35 value: _connectionsSyncViewModel.lookupValue(source),
36 onValueChange: (_, bool value) =>
37 _connectionsSyncViewModel.setLookupValue(source, value),
lib/src/screens/settings/items/item_headers.dart
+1 -1
@@ -15,4 +15,4 @@ class ItemHeaders {
15 static const termsAndConditions = 'Terms and conditions';
16 static const faq = 'FAQ';
17 static const version = 'Version';
18 -}
\ No newline at end of file
18 +}
lib/src/screens/settings/manage_nodes_page.dart
+10 -11
@@ -55,10 +55,10 @@ class _ManageNodesPageState extends State<ManageNodesPage> {
55 ModernButton(
56 size: 36,
57 icon: Icon(Icons.add),
58 - onPressed: ()async {
58 + onPressed: () async {
59 final res = await Navigator.of(context)
60 - .pushNamed(widget.isPow ? Routes.newPowNode : Routes.newNode);
61 - if(res != null && res is Node) {
60 + .pushNamed(widget.isPow ? Routes.newPowNode : Routes.newNode);
61 + if (res != null && res is Node) {
62 widget.nodeListViewModel.nodes.add(res);
63 }
64 })
@@ -75,12 +75,11 @@ class _ManageNodesPageState extends State<ManageNodesPage> {
75 // horizontal: 0,
76 node: widget.nodeListViewModel.currentNode,
77 speed: widget.nodeListViewModel.nodeSpeedFor(widget.nodeListViewModel.currentNode),
78 - onEditComplete: (res)async{
79 - if(res != null && res is Node) {
80 - widget.nodeListViewModel.nodes.removeWhere((item)=>item.id == res.id);
78 + onEditComplete: (res) async {
79 + if (res != null && res is Node) {
80 + widget.nodeListViewModel.nodes.removeWhere((item) => item.id == res.id);
81 widget.nodeListViewModel.nodes.add(res);
82 }
83 -
83 },
84 onTap: () {},
85 isSelected: true,
@@ -93,7 +92,7 @@ class _ManageNodesPageState extends State<ManageNodesPage> {
92 color: Theme.of(context).colorScheme.surfaceContainer,
93 borderRadius: BorderRadius.circular(18)),
94 child: ClipRRect(
96 - borderRadius: BorderRadius.circular(18),
95 + borderRadius: BorderRadius.circular(18),
96 child: Observer(
97 builder: (BuildContext context) {
98 int itemsCount = widget.nodeListViewModel.nonCurrentNodes.length;
@@ -119,11 +118,11 @@ class _ManageNodesPageState extends State<ManageNodesPage> {
118 isPow: widget.isPow,
119 speed: widget.nodeListViewModel.nodeSpeedFor(node),
120 onEditComplete: (res) async {
122 - if(res != null && res is Node) {
123 - widget.nodeListViewModel.nodes.removeWhere((item)=>item.id == res.id);
121 + if (res != null && res is Node) {
122 + widget.nodeListViewModel.nodes
123 + .removeWhere((item) => item.id == res.id);
124 widget.nodeListViewModel.nodes.add(res);
125 }
126 -
126 },
127 onTap: () async {
128 await showPopUp<void>(
lib/src/screens/settings/mweb_logs_page.dart
+6 -6
@@ -38,7 +38,8 @@ class MwebLogsPage extends BasePage {
38 padding: EdgeInsets.all(16.0),
39 child: Text(
40 snapshot.data!,
41 - style: Theme.of(context).textTheme.bodyMedium!.copyWith(fontFamily: 'Monospace'),
41 + style:
42 + Theme.of(context).textTheme.bodyMedium!.copyWith(fontFamily: 'Monospace'),
43 ),
44 ),
45 );
@@ -103,11 +104,10 @@ class MwebLogsPage extends BasePage {
104 }
105
106 Future<void> _saveFile() async {
106 - String? outputFile = await FilePicker.platform
107 - .saveFile(
108 - dialogTitle: 'Save Your File to desired location',
109 - fileName: "debug.log",
110 - lockParentWindow: true);
107 + String? outputFile = await FilePicker.platform.saveFile(
108 + dialogTitle: 'Save Your File to desired location',
109 + fileName: "debug.log",
110 + lockParentWindow: true);
111
112 if (outputFile == null) return;
113
lib/src/screens/settings/mweb_node_page.dart
+20 -21
@@ -7,6 +7,7 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
7 import 'package:cake_wallet/generated/i18n.dart';
8 import 'package:cake_wallet/view_model/settings/mweb_settings_view_model.dart';
9 import 'package:flutter/material.dart';
10 +
11 class MwebNodePage extends StatefulWidget {
12 const MwebNodePage(this.mwebSettingsViewModelBase, {super.key});
13
@@ -30,30 +31,28 @@ class _MwebNodePageState extends State<MwebNodePage> {
31 Widget build(BuildContext context) {
32 return SafeArea(
33 child: ModalPageWrapper(
33 - topBar: ModalTopBar(
34 + topBar: ModalTopBar(
35 title: S.current.litecoin_mweb_settings,
36 onLeadingPressed: Navigator.of(context).pop,
37 leadingIcon: Icon(Icons.arrow_back_ios_new)),
37 - content: Container(
38 - child: NewListSections(
39 - controllers: {
40 - widget.mwebSettingsViewModelBase.mwebNodeUri: _nodeUriController,
41 - },
42 - sections: {
43 - 'main': [
44 - ListItemTextField(
45 - keyValue: widget.mwebSettingsViewModelBase.mwebNodeUri,
46 - label: S.current.node_address,
47 - validator: NodePathValidator(),
48 - ),
49 - ]
50 - }),
51 - ),
52 - bottomContent: LoadingPrimaryButton(
53 - onPressed: () => save(context),
54 - text: S.of(context).save,
55 - color: Theme.of(context).colorScheme.primary,
56 - textColor: Theme.of(context).colorScheme.onPrimary,
38 + content: Container(
39 + child: NewListSections(controllers: {
40 + widget.mwebSettingsViewModelBase.mwebNodeUri: _nodeUriController,
41 + }, sections: {
42 + 'main': [
43 + ListItemTextField(
44 + keyValue: widget.mwebSettingsViewModelBase.mwebNodeUri,
45 + label: S.current.node_address,
46 + validator: NodePathValidator(),
47 + ),
48 + ]
49 + }),
50 + ),
51 + bottomContent: LoadingPrimaryButton(
52 + onPressed: () => save(context),
53 + text: S.of(context).save,
54 + color: Theme.of(context).colorScheme.primary,
55 + textColor: Theme.of(context).colorScheme.onPrimary,
56 ),
57 ),
58 );
lib/src/screens/settings/mweb_settings.dart
+1 -1
@@ -41,7 +41,7 @@ class MwebSettingsPage extends BasePage {
41 title: S.current.litecoin_mweb_scanning,
42 handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.rescan),
43 ),
44 - SettingsCellWithArrow(
44 + SettingsCellWithArrow(
45 title: S.current.litecoin_mweb_logs,
46 handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.mwebLogs),
47 ),
lib/src/screens/settings/other_settings_page.dart
+70 -67
@@ -149,7 +149,8 @@ class OtherSettingsPage extends BasePage {
149 Navigator.of(context).pushNamed(Routes.signPage);
150 }),
151 ],
152 - if (_otherSettingsViewModel.walletType == WalletType.bitcoin) "btc_logging": [
152 + if (_otherSettingsViewModel.walletType == WalletType.bitcoin)
153 + "btc_logging": [
154 ListItemRegularRow(
155 keyValue: "export_lightning_logs",
156 label: S.of(context).export_lightning_logs,
@@ -158,72 +159,74 @@ class OtherSettingsPage extends BasePage {
159 keyValue: "export_payjoin_logs",
160 label: S.of(context).export_payjoin_logs,
161 onTap: () => onExportPJLog(context)),
161 - ],
162 - "dev": FeatureFlag.hasDevOptions == false ? [] : [
163 - if (_otherSettingsViewModel.walletType == WalletType.monero)
164 - ListItemRegularRow(
165 - keyValue: "[dev] monero background sync",
166 - label: "[dev] monero background sync",
167 - onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroBackgroundSync)),
168 - if ([WalletType.monero, WalletType.wownero, WalletType.zano]
169 - .contains(_otherSettingsViewModel.walletType))
170 - ListItemRegularRow(
171 - keyValue: "[dev] xmr call profiler",
172 - label: "[dev] xmr call profiler",
173 - onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroCallProfiler)),
174 - if ([WalletType.monero].contains(_otherSettingsViewModel.walletType))
175 - ListItemRegularRow(
176 - keyValue: '[dev] xmr wallet cache debug',
177 - label: '[dev] xmr wallet cache debug',
178 - onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroWalletCacheDebug)),
179 - ListItemRegularRow(
180 - keyValue: '[dev] shared preferences',
181 - label: '[dev] shared preferences',
182 - onTap: () => Navigator.of(context).pushNamed(Routes.devSharedPreferences)),
183 - ListItemRegularRow(
184 - keyValue: '[dev] secure storage preferences',
185 - label: '[dev] secure storage preferences',
186 - onTap: () => Navigator.of(context).pushNamed(Routes.devSecurePreferences)),
187 - ListItemRegularRow(
188 - keyValue: '[dev] background sync logs',
189 - label: '[dev] background sync logs',
190 - onTap: () => Navigator.of(context).pushNamed(Routes.devBackgroundSyncLogs)),
191 - ListItemRegularRow(
192 - keyValue: '[dev] socket health logs',
193 - label: '[dev] socket health logs',
194 - onTap: () => Navigator.of(context).pushNamed(Routes.devSocketHealthLogs)),
195 - ListItemRegularRow(
196 - keyValue: '[dev] network requests logs',
197 - label: '[dev] network requests logs',
198 - onTap: () => Navigator.of(context).pushNamed(Routes.devNetworkRequests)),
199 - ListItemRegularRow(
200 - keyValue: '[dev] exchange provider logs',
201 - label: '[dev] exchange provider logs',
202 - onTap: () => Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs)),
203 - ListItemRegularRow(
204 - keyValue: '[dev] *QR tools',
205 - label: '[dev] *QR tools',
206 - onTap: () => Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs)),
207 - ListItemRegularRow(
208 - keyValue: '[dev] browse sqlite db',
209 - label: '[dev] browse sqlite db',
210 - onTap: () async {
211 - final data = await dumpDb();
212 - Navigator.of(context).push(
213 - MaterialPageRoute(
214 - builder: (context) => JsonExplorerPage(data: data, title: 'sqlite db'),
215 - ),
216 - );
217 - }),
218 - ListItemRegularRow(
219 - keyValue: '[dev] fake corrupt sqlite db',
220 - label: '[dev] fake corrupt sqlite db',
221 - onTap: () async {
222 - final dbDebugMarker = await sqliteDebugMarkerFile();
223 - dbDebugMarker.create();
224 - }
225 - ),
226 - ]
162 + ],
163 + "dev": FeatureFlag.hasDevOptions == false
164 + ? []
165 + : [
166 + if (_otherSettingsViewModel.walletType == WalletType.monero)
167 + ListItemRegularRow(
168 + keyValue: "[dev] monero background sync",
169 + label: "[dev] monero background sync",
170 + onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroBackgroundSync)),
171 + if ([WalletType.monero, WalletType.wownero, WalletType.zano]
172 + .contains(_otherSettingsViewModel.walletType))
173 + ListItemRegularRow(
174 + keyValue: "[dev] xmr call profiler",
175 + label: "[dev] xmr call profiler",
176 + onTap: () => Navigator.of(context).pushNamed(Routes.devMoneroCallProfiler)),
177 + if ([WalletType.monero].contains(_otherSettingsViewModel.walletType))
178 + ListItemRegularRow(
179 + keyValue: '[dev] xmr wallet cache debug',
180 + label: '[dev] xmr wallet cache debug',
181 + onTap: () =>
182 + Navigator.of(context).pushNamed(Routes.devMoneroWalletCacheDebug)),
183 + ListItemRegularRow(
184 + keyValue: '[dev] shared preferences',
185 + label: '[dev] shared preferences',
186 + onTap: () => Navigator.of(context).pushNamed(Routes.devSharedPreferences)),
187 + ListItemRegularRow(
188 + keyValue: '[dev] secure storage preferences',
189 + label: '[dev] secure storage preferences',
190 + onTap: () => Navigator.of(context).pushNamed(Routes.devSecurePreferences)),
191 + ListItemRegularRow(
192 + keyValue: '[dev] background sync logs',
193 + label: '[dev] background sync logs',
194 + onTap: () => Navigator.of(context).pushNamed(Routes.devBackgroundSyncLogs)),
195 + ListItemRegularRow(
196 + keyValue: '[dev] socket health logs',
197 + label: '[dev] socket health logs',
198 + onTap: () => Navigator.of(context).pushNamed(Routes.devSocketHealthLogs)),
199 + ListItemRegularRow(
200 + keyValue: '[dev] network requests logs',
201 + label: '[dev] network requests logs',
202 + onTap: () => Navigator.of(context).pushNamed(Routes.devNetworkRequests)),
203 + ListItemRegularRow(
204 + keyValue: '[dev] exchange provider logs',
205 + label: '[dev] exchange provider logs',
206 + onTap: () => Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs)),
207 + ListItemRegularRow(
208 + keyValue: '[dev] *QR tools',
209 + label: '[dev] *QR tools',
210 + onTap: () => Navigator.of(context).pushNamed(Routes.devExchangeProviderLogs)),
211 + ListItemRegularRow(
212 + keyValue: '[dev] browse sqlite db',
213 + label: '[dev] browse sqlite db',
214 + onTap: () async {
215 + final data = await dumpDb();
216 + Navigator.of(context).push(
217 + MaterialPageRoute(
218 + builder: (context) => JsonExplorerPage(data: data, title: 'sqlite db'),
219 + ),
220 + );
221 + }),
222 + ListItemRegularRow(
223 + keyValue: '[dev] fake corrupt sqlite db',
224 + label: '[dev] fake corrupt sqlite db',
225 + onTap: () async {
226 + final dbDebugMarker = await sqliteDebugMarkerFile();
227 + dbDebugMarker.create();
228 + }),
229 + ]
230 }),
231 );
232 }
lib/src/screens/settings/privacy_page.dart
+45 -47
@@ -38,44 +38,43 @@ class PrivacyPage extends BasePage {
38 return Column(
39 mainAxisSize: MainAxisSize.min,
40 children: [
41 - NewListSections(
42 - sections: {
43 - "1": [
44 - if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
45 - ListItemToggle(
46 - keyValue: "auto_generate_subaddresses",
47 - label: _privacySettingsViewModel.isMoneroWallet
48 - ? S.of(context).auto_generate_subaddresses
49 - : S.of(context).auto_generate_addresses,
50 - value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
51 - onChanged: (val) {
52 - _privacySettingsViewModel.setAutoGenerateSubaddresses(val);
53 - }),
41 + NewListSections(sections: {
42 + "1": [
43 + if (_privacySettingsViewModel.isAutoGenerateSubaddressesVisible)
44 ListItemToggle(
55 - keyValue: "save_recipient_address",
56 - label: S.of(context).settings_save_recipient_address,
57 - value: _privacySettingsViewModel.shouldSaveRecipientAddress,
45 + keyValue: "auto_generate_subaddresses",
46 + label: _privacySettingsViewModel.isMoneroWallet
47 + ? S.of(context).auto_generate_subaddresses
48 + : S.of(context).auto_generate_addresses,
49 + value: _privacySettingsViewModel.isAutoGenerateSubaddressesEnabled,
50 onChanged: (val) {
59 - _privacySettingsViewModel.setShouldSaveRecipientAddress(val);
51 + _privacySettingsViewModel.setAutoGenerateSubaddresses(val);
52 }),
61 - if (_privacySettingsViewModel.canUsePayjoin)
62 - ListItemToggle(
63 - keyValue: "use_payjoin",
64 - label: S.of(context).use_payjoin,
65 - value: _privacySettingsViewModel.usePayjoin,
66 - onChanged: (val) {
67 - _privacySettingsViewModel.setUsePayjoin(val);
68 - }),
69 - if (_privacySettingsViewModel.canUseLightning)
70 - ListItemToggle(
71 - keyValue: "enable_lightning",
72 - label: S.of(context).enable_lightning,
73 - value: _privacySettingsViewModel.useLightning,
74 - onChanged: (val) {
75 - _privacySettingsViewModel.setUseLightning(val);
76 - }),
77 - ],
78 - "": [
53 + ListItemToggle(
54 + keyValue: "save_recipient_address",
55 + label: S.of(context).settings_save_recipient_address,
56 + value: _privacySettingsViewModel.shouldSaveRecipientAddress,
57 + onChanged: (val) {
58 + _privacySettingsViewModel.setShouldSaveRecipientAddress(val);
59 + }),
60 + if (_privacySettingsViewModel.canUsePayjoin)
61 + ListItemToggle(
62 + keyValue: "use_payjoin",
63 + label: S.of(context).use_payjoin,
64 + value: _privacySettingsViewModel.usePayjoin,
65 + onChanged: (val) {
66 + _privacySettingsViewModel.setUsePayjoin(val);
67 + }),
68 + if (_privacySettingsViewModel.canUseLightning)
69 + ListItemToggle(
70 + keyValue: "enable_lightning",
71 + label: S.of(context).enable_lightning,
72 + value: _privacySettingsViewModel.useLightning,
73 + onChanged: (val) {
74 + _privacySettingsViewModel.setUseLightning(val);
75 + }),
76 + ],
77 + "": [
78 if (_privacySettingsViewModel.isBitcoin)
79 ListItemRegularRow(
80 iconPath: "assets/new-ui/settings_row_icons/silent-payments.svg",
@@ -83,23 +82,22 @@ class PrivacyPage extends BasePage {
82 label: S.of(context).silent_payments,
83 onTap: () =>
84 Navigator.of(context).pushNamed(Routes.silentPaymentsSettings)),
86 - if (_privacySettingsViewModel.hasMWEB)
87 - ListItemRegularRow(
88 - iconPath: "assets/new-ui/settings_row_icons/mweb.svg",
89 - keyValue: "mweb",
90 - label: "MWEB",
91 - onTap: () =>
92 - Navigator.of(context).pushNamed(Routes.mwebSettings)),
93 - if (_privacySettingsViewModel.hasCoinControl)
85 + if (_privacySettingsViewModel.hasMWEB)
86 + ListItemRegularRow(
87 + iconPath: "assets/new-ui/settings_row_icons/mweb.svg",
88 + keyValue: "mweb",
89 + label: "MWEB",
90 + onTap: () => Navigator.of(context).pushNamed(Routes.mwebSettings)),
91 + if (_privacySettingsViewModel.hasCoinControl)
92 ListItemRegularRow(
93 iconPath: "assets/new-ui/settings_row_icons/coin-control.svg",
94 keyValue: "coin_control",
95 label: "Coin Control",
98 - onTap: () =>
99 - Navigator.of(context).pushNamed(Routes.unspentCoinsList, arguments: CoinControlPageArgs(canEdit: false, coinTypeToSpendFrom: null))),
96 + onTap: () => Navigator.of(context).pushNamed(Routes.unspentCoinsList,
97 + arguments:
98 + CoinControlPageArgs(canEdit: false, coinTypeToSpendFrom: null))),
99 ],
101 - }
102 - ),
100 + }),
101 ],
102 );
103 }),
lib/src/screens/settings/security_backup_page.dart
+10 -11
@@ -73,8 +73,8 @@ class SecurityBackupPage extends BasePage {
73 isAuthenticatedSuccessfully);
74 }
75 } else {
76 - _securitySettingsViewModel.setAllowBiometricalAuthentication(
77 - isAuthenticatedSuccessfully);
76 + _securitySettingsViewModel
77 + .setAllowBiometricalAuthentication(isAuthenticatedSuccessfully);
78 }
79 },
80 conditionToDetermineIfToUse2FA: _securitySettingsViewModel
@@ -85,13 +85,13 @@ class SecurityBackupPage extends BasePage {
85 }
86 }),
87 if (DeviceInfo.instance.isMobile)
88 - ListItemToggle(
89 - keyValue: "display_settings_prevent_screen_capture",
90 - label: S.of(context).prevent_screenshots,
91 - value: _securitySettingsViewModel.isAppSecure,
92 - onChanged: (val) {
93 - _securitySettingsViewModel.setIsAppSecure(val);
94 - }),
88 + ListItemToggle(
89 + keyValue: "display_settings_prevent_screen_capture",
90 + label: S.of(context).prevent_screenshots,
91 + value: _securitySettingsViewModel.isAppSecure,
92 + onChanged: (val) {
93 + _securitySettingsViewModel.setIsAppSecure(val);
94 + }),
95 if (FeatureFlag.duressPinEnabled)
96 ListItemToggle(
97 keyValue: "security_backup_page_duress_pin_button_key",
@@ -114,8 +114,7 @@ class SecurityBackupPage extends BasePage {
114 if (confirmation) {
115 Navigator.of(context).pushNamed(
116 Routes.setupDuressPin,
117 - arguments:
118 - (PinCodeState<PinCodeWidget> pinCtx, String _) async {
117 + arguments: (PinCodeState<PinCodeWidget> pinCtx, String _) async {
118 pinCtx.close();
119 _securitySettingsViewModel.setEnableDuressPin(true);
120 },
lib/src/screens/settings/silent_payments_logs_page.dart
+4 -5
@@ -105,11 +105,10 @@ class SilentPaymentsLogPage extends BasePage {
105 }
106
107 Future<void> _saveFile() async {
108 - String? outputFile = await FilePicker.platform
109 - .saveFile(
110 - dialogTitle: 'Save Your File to desired location',
111 - fileName: "debug.log",
112 - lockParentWindow: true);
108 + String? outputFile = await FilePicker.platform.saveFile(
109 + dialogTitle: 'Save Your File to desired location',
110 + fileName: "debug.log",
111 + lockParentWindow: true);
112
113 if (outputFile == null) return;
114
lib/src/screens/settings/silent_payments_settings.dart
+15 -10
@@ -19,7 +19,11 @@ class SilentPaymentsSettingsPage extends StatelessWidget {
19 color: Theme.of(context).colorScheme.surface,
20 child: Column(
21 children: [
22 - ModalTopBar(title: S.current.silent_payments_settings,leadingIcon: Icon(Icons.arrow_back_ios_new),onLeadingPressed: Navigator.of(context).pop,),
22 + ModalTopBar(
23 + title: S.current.silent_payments_settings,
24 + leadingIcon: Icon(Icons.arrow_back_ios_new),
25 + onLeadingPressed: Navigator.of(context).pop,
26 + ),
27 Expanded(
28 child: SingleChildScrollView(
29 child: Observer(builder: (_) {
@@ -27,14 +31,14 @@ class SilentPaymentsSettingsPage extends StatelessWidget {
31 padding: EdgeInsets.only(top: 10),
32 child: Column(
33 children: [
30 - if(!FeatureFlag.hasNewUi)
31 - SettingsSwitcherCell(
32 - title: S.current.silent_payments_display_card,
33 - value: _silentPaymentsSettingsViewModel.silentPaymentsCardDisplay,
34 - onValueChange: (_, bool value) {
35 - _silentPaymentsSettingsViewModel.setSilentPaymentsCardDisplay(value);
36 - },
37 - ),
34 + if (!FeatureFlag.hasNewUi)
35 + SettingsSwitcherCell(
36 + title: S.current.silent_payments_display_card,
37 + value: _silentPaymentsSettingsViewModel.silentPaymentsCardDisplay,
38 + onValueChange: (_, bool value) {
39 + _silentPaymentsSettingsViewModel.setSilentPaymentsCardDisplay(value);
40 + },
41 + ),
42 SettingsSwitcherCell(
43 title: S.current.silent_payments_always_scan,
44 value: _silentPaymentsSettingsViewModel.silentPaymentsAlwaysScan,
@@ -44,7 +48,8 @@ class SilentPaymentsSettingsPage extends StatelessWidget {
48 ),
49 SettingsCellWithArrow(
50 title: S.current.silent_payments_scanning,
47 - handler: (BuildContext context) => Navigator.of(context).pushNamed(Routes.rescan),
51 + handler: (BuildContext context) =>
52 + Navigator.of(context).pushNamed(Routes.rescan),
53 ),
54 SettingsCellWithArrow(
55 title: S.current.silent_payments_logs,
lib/src/screens/settings/widgets/settings_choices_cell.dart
+3 -4
@@ -44,9 +44,8 @@ class SettingsChoicesCell extends StatelessWidget {
44 color: Theme.of(context).colorScheme.surfaceContainerHighest,
45 width: 1.5,
46 ),
47 - color: useGenericColor
48 - ? Theme.of(context).colorScheme.surfaceContainerHighest
49 - : null,
47 + color:
48 + useGenericColor ? Theme.of(context).colorScheme.surfaceContainerHighest : null,
49 ),
50 child: LayoutBuilder(
51 builder: (context, constraints) {
@@ -106,4 +105,4 @@ class SettingsChoicesCell extends StatelessWidget {
105 ),
106 );
107 }
109 -}
\ No newline at end of file
108 +}
lib/src/screens/settings/widgets/settings_picker_row.dart
+1 -1
@@ -6,4 +6,4 @@ class SettingsPickerRaw extends StatelessWidget {
6 // TODO: implement build
7 throw UnimplementedError();
8 }
9 -}
\ No newline at end of file
9 +}
lib/src/screens/settings/widgets/settings_theme_choice.dart
+29 -23
@@ -58,11 +58,13 @@ class SettingsThemeChoicesCell extends StatelessWidget {
58 curve: Curves.easeInOut,
59 margin: EdgeInsets.only(right: 24),
60 decoration: ShapeDecoration(
61 - shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(cellRadius),
62 - side: BorderSide(
63 - color: isSelected ? Theme.of(context).colorScheme.primary : Colors.transparent,
64 - strokeAlign: BorderSide.strokeAlignOutside)
65 - )),
61 + shape: RoundedSuperellipseBorder(
62 + borderRadius: BorderRadius.circular(cellRadius),
63 + side: BorderSide(
64 + color: isSelected
65 + ? Theme.of(context).colorScheme.primary
66 + : Colors.transparent,
67 + strokeAlign: BorderSide.strokeAlignOutside))),
68 child: ClipRRect(
69 borderRadius: BorderRadius.circular(cellRadius),
70 child: CakeImageWidget(
@@ -97,8 +99,8 @@ class SettingsThemeChoicesCell extends StatelessWidget {
99 children: [
100 Padding(
101 padding: EdgeInsets.only(top: 14),
100 - child: Container(height: 1, color: Theme.of(context).colorScheme.outlineVariant)
101 - ),
102 + child: Container(
103 + height: 1, color: Theme.of(context).colorScheme.outlineVariant)),
104 SizedBox(height: cellHeight),
105 Row(
106 mainAxisAlignment: MainAxisAlignment.spaceBetween,
@@ -123,10 +125,14 @@ class SettingsThemeChoicesCell extends StatelessWidget {
125 duration: Duration(milliseconds: 350),
126 opacity: isSelected ? 1 : 0,
127 child: Container(
126 - width:28,height:28,decoration: BoxDecoration(borderRadius: BorderRadius.circular(99999999),border: Border.all(color:Theme.of(context)
127 - .colorScheme
128 - .onSurface))
129 - ),
128 + width: 28,
129 + height: 28,
130 + decoration: BoxDecoration(
131 + borderRadius: BorderRadius.circular(99999999),
132 + border: Border.all(
133 + color: Theme.of(context)
134 + .colorScheme
135 + .onSurface))),
136 ),
137 AnimatedScale(
138 duration: Duration(milliseconds: 350),
@@ -153,19 +159,19 @@ class SettingsThemeChoicesCell extends StatelessWidget {
159 if (_displaySettingsViewModel.currentTheme is BlackTheme)
160 Padding(
161 padding: EdgeInsets.only(top: 12, bottom: 4),
156 - child: Container(height: 1, color: Theme.of(context).colorScheme.outlineVariant)
157 - ),
162 + child:
163 + Container(height: 1, color: Theme.of(context).colorScheme.outlineVariant)),
164 if (_displaySettingsViewModel.currentTheme is BlackTheme)
159 - SettingsSwitcherCell(
160 - height: 40,
161 - title: S.current.oled_mode,
162 - value: _displaySettingsViewModel.isBlackThemeOledEnabled,
163 - onValueChange: (_, bool value) {
164 - _displaySettingsViewModel.setBlackThemeOled(value);
165 - },
166 - padding: EdgeInsets.zero,
167 - switchBackgroundColor: currentTheme.colorScheme.secondaryContainer,
168 - ),
165 + SettingsSwitcherCell(
166 + height: 40,
167 + title: S.current.oled_mode,
168 + value: _displaySettingsViewModel.isBlackThemeOledEnabled,
169 + onValueChange: (_, bool value) {
170 + _displaySettingsViewModel.setBlackThemeOled(value);
171 + },
172 + padding: EdgeInsets.zero,
173 + switchBackgroundColor: currentTheme.colorScheme.secondaryContainer,
174 + ),
175 ],
176 ),
177 );
lib/src/screens/settings/widgets/wallet_connect_button.dart
+2 -2
@@ -26,8 +26,8 @@ class WalletConnectTile extends StatelessWidget {
26 child: Text(
27 S.current.walletConnect,
28 style: Theme.of(context).textTheme.bodyLarge?.copyWith(
29 - color: Theme.of(context).colorScheme.onSurface,
30 - ),
29 + color: Theme.of(context).colorScheme.onSurface,
30 + ),
31 ),
32 ),
33 Image.asset(
lib/src/screens/setup_2fa/setup_2fa_enter_code_page.dart
+6 -6
@@ -115,7 +115,6 @@ class TOTPEnterCode extends StatefulWidget {
115 required this.isClosable,
116 });
117
118 -
118 final Setup2FAViewModel setup2FAViewModel;
119 final bool isForSetup;
120 final bool isClosable;
@@ -154,7 +153,6 @@ class _TOTPEnterCodeState extends State<TOTPEnterCode> {
153 ),
154 child: Column(
155 children: [
157 -
156 BaseTextFormField(
157 textAlign: TextAlign.left,
158 hintText: S.current.totp_code,
@@ -180,15 +178,17 @@ class _TOTPEnterCodeState extends State<TOTPEnterCode> {
178 return PrimaryButton(
179 isDisabled: widget.setup2FAViewModel.enteredOTPCode.length != 8,
180 onPressed: () async {
183 - final result =
184 - await widget.setup2FAViewModel.totp2FAAuth(totpController.text, widget.isForSetup);
185 - final bannedState = widget.setup2FAViewModel.state is AuthenticationBanned;
181 + final result = await widget.setup2FAViewModel
182 + .totp2FAAuth(totpController.text, widget.isForSetup);
183 + final bannedState =
184 + widget.setup2FAViewModel.state is AuthenticationBanned;
185
186 await showPopUp<void>(
187 context: context,
188 builder: (BuildContext context) {
189 return PopUpCancellableAlertDialog(
191 - contentText: _textDisplayedInPopupOnResult(result, bannedState, context),
190 + contentText:
191 + _textDisplayedInPopupOnResult(result, bannedState, context),
192 actionButtonText: S.of(context).ok,
193 buttonAction: () {
194 result ? widget.setup2FAViewModel.success() : null;
lib/src/screens/setup_2fa/widgets/popup_cancellable_alert.dart
+5 -6
@@ -25,12 +25,11 @@ class PopUpCancellableAlertDialog extends StatelessWidget {
25 contentText,
26 textAlign: TextAlign.center,
27 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
28 - fontSize: 16,
29 - fontWeight: FontWeight.normal,
30 -
31 - color: Theme.of(context).colorScheme.onSurface,
32 - decoration: TextDecoration.none,
33 - ),
28 + fontSize: 16,
29 + fontWeight: FontWeight.normal,
30 + color: Theme.of(context).colorScheme.onSurface,
31 + decoration: TextDecoration.none,
32 + ),
33 );
34 }
35
lib/src/screens/setup_pin_code/setup_pin_code.dart
+5 -8
@@ -8,7 +8,7 @@ import 'package:cake_wallet/view_model/setup_pin_code_view_model.dart';
8 import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
9
10 class SetupPinCodePage extends BasePage {
11 - SetupPinCodePage(this.pinCodeViewModel,{this.onSuccessfulPinSetup, this.isDuressPin = false})
11 + SetupPinCodePage(this.pinCodeViewModel, {this.onSuccessfulPinSetup, this.isDuressPin = false})
12 : pinCodeStateKey = GlobalKey<PinCodeState>();
13
14 final SetupPinCodeViewModel pinCodeViewModel;
@@ -24,8 +24,7 @@ class SetupPinCodePage extends BasePage {
24 key: pinCodeStateKey,
25 hasLengthSwitcher: true,
26 onFullPin: (String pin, PinCodeState<PinCodeWidget> state) async {
27 - if (pinCodeViewModel.isOriginalPinCodeFull &&
28 - !pinCodeViewModel.isRepeatedPinCodeFull) {
27 + if (pinCodeViewModel.isOriginalPinCodeFull && !pinCodeViewModel.isRepeatedPinCodeFull) {
28 state.title = S.current.enter_your_pin_again;
29 state.clear();
30 return;
@@ -64,7 +63,7 @@ class SetupPinCodePage extends BasePage {
63 if (pinCodeStateKey.currentState != null) {
64 onSuccessfulPinSetup?.call(pinCodeStateKey.currentState!, pin);
65 }
67 -
66 +
67 state.reset();
68 },
69 alertBarrierDismissible: false,
@@ -76,8 +75,7 @@ class SetupPinCodePage extends BasePage {
75 builder: (BuildContext context) {
76 return AlertWithOneAction(
77 alertTitle: isDuressPin ? S.current.durres_PIN : S.current.setup_pin,
79 - alertContent:
80 - '${S.current.setup_pin_is_failed} ${e.toString()}',
78 + alertContent: '${S.current.setup_pin_is_failed} ${e.toString()}',
79 buttonText: S.of(context).ok,
80 buttonAction: () => Navigator.of(context).pop(),
81 alertBarrierDismissible: false,
@@ -108,7 +106,6 @@ class SetupPinCodePage extends BasePage {
106 pinCodeViewModel.reset();
107 }
108 },
111 - onChangedPinLength: (int length) =>
112 - pinCodeViewModel.pinCodeLength = length,
109 + onChangedPinLength: (int length) => pinCodeViewModel.pinCodeLength = length,
110 initialPinLength: pinCodeViewModel.pinCodeLength);
111 }
lib/src/screens/splash/splash_page.dart
+2 -4
@@ -3,8 +3,6 @@ import 'package:flutter/material.dart';
3 class SplashPage extends StatelessWidget {
4 @override
5 Widget build(BuildContext context) {
6 - return Scaffold(
7 - body: Container()
8 - );
6 + return Scaffold(body: Container());
7 }
10 -}
\ No newline at end of file
8 +}
lib/src/screens/start_tor/start_tor_page.dart
+2 -2
@@ -34,7 +34,7 @@ class StartTorPage extends BasePage {
34 CircularProgressIndicator(),
35 SizedBox(height: 20),
36 _buildWaitingText(context),
37 - ],
37 + ],
38 if (startTorViewModel.showOptions) ...[
39 _buildOptionsButtons(context),
40 ],
@@ -93,4 +93,4 @@ class StartTorPage extends BasePage {
93 ],
94 );
95 }
96 -}
\ No newline at end of file
96 +}
lib/src/screens/support_chat/support_chat_page.dart
+11 -13
@@ -11,15 +11,14 @@ class SupportChatPage extends StatelessWidget {
11 final SupportViewModel supportViewModel;
12 final SecureStorage secureStorage;
13
14 -
14 @override
15 Widget build(BuildContext context) => Container(
17 - color: Theme.of(context).colorScheme.surface,
18 - child: SafeArea(
19 - child: Padding(
20 - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
21 - child: Column(
22 - children: [
16 + color: Theme.of(context).colorScheme.surface,
17 + child: SafeArea(
18 + child: Padding(
19 + padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
20 + child: Column(
21 + children: [
22 ModalTopBar(
23 title: S.current.settings_support,
24 leadingIcon: Icon(Icons.arrow_back_ios_new),
@@ -42,12 +41,11 @@ class SupportChatPage extends StatelessWidget {
41 return Container();
42 },
43 ),
45 - ],
44 + ],
45 + ),
46 + ),
47 ),
47 - ),
48 - ),
49 - );
48 + );
49
51 - Future<String> getCookie() async =>
52 - await secureStorage.read(key: COOKIE_KEY) ?? "";
50 + Future<String> getCookie() async => await secureStorage.read(key: COOKIE_KEY) ?? "";
51 }
lib/src/screens/support_chat/widgets/chatwoot_widget.dart
+3 -4
@@ -41,11 +41,10 @@ class ChatwootWidgetState extends State<ChatwootWidget> {
41 controller.addWebMessageListener(
42 WebMessageListener(
43 jsObjectName: 'ReactNativeWebView',
44 - onPostMessage: (WebMessage? message, WebUri? sourceOrigin,
45 - bool isMainFrame, PlatformJavaScriptReplyProxy replyProxy) {
44 + onPostMessage: (WebMessage? message, WebUri? sourceOrigin, bool isMainFrame,
45 + PlatformJavaScriptReplyProxy replyProxy) {
46 final shortenedMessage = message?.data.toString().substring(16);
47 - if (shortenedMessage != null &&
48 - _isJsonString(shortenedMessage)) {
47 + if (shortenedMessage != null && _isJsonString(shortenedMessage)) {
48 final parsedMessage = jsonDecode(shortenedMessage);
49 final eventType = parsedMessage["event"];
50 if (eventType == 'loaded') {
lib/src/screens/trade_details/track_trade_list_item.dart
+1 -4
@@ -1,10 +1,7 @@
1 import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
2
3 class TrackTradeListItem extends StandartListItem {
4 - TrackTradeListItem({
5 - required String title,
6 - required String value,
7 - required this.onTap})
4 + TrackTradeListItem({required String title, required String value, required this.onTap})
5 : super(title: title, value: value);
6 final Function() onTap;
7 }
lib/src/screens/trade_details/trade_details_list_card.dart
+5 -7
@@ -19,13 +19,11 @@ class TradeDetailsListCardItem extends StandartListItem {
19 required CryptoCurrency to,
20 required void Function(BuildContext) onTap,
21 String? extraId}) {
22 -
23 -
24 - final extraIdTitle = from == CryptoCurrency.xrp
25 - ? S.current.destination_tag
26 - : from == CryptoCurrency.xlm
27 - ? S.current.memo
28 - : S.current.extra_id;
22 + final extraIdTitle = from == CryptoCurrency.xrp
23 + ? S.current.destination_tag
24 + : from == CryptoCurrency.xlm
25 + ? S.current.memo
26 + : S.current.extra_id;
27
28 return TradeDetailsListCardItem(
29 id: '${S.current.trade_details_id} ${formatAsText(id)}',
lib/src/screens/trade_details/trade_details_page.dart
+4 -4
@@ -74,10 +74,10 @@ class TradeDetailsPageBodyState extends State<TradeDetailsPageBody> {
74 child: Text(
75 '${item.value}',
76 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
77 - fontSize: 16,
78 - fontWeight: FontWeight.w500,
79 - color: Theme.of(context).colorScheme.onSurface,
80 - ),
77 + fontSize: 16,
78 + fontWeight: FontWeight.w500,
79 + color: Theme.of(context).colorScheme.onSurface,
80 + ),
81 ),
82 ),
83 image: GestureDetector(
lib/src/screens/trade_details/trade_details_status_item.dart
+1 -2
@@ -1,8 +1,7 @@
1 import 'package:cake_wallet/src/screens/transaction_details/standart_list_item.dart';
2
3 class DetailsListStatusItem extends StandartListItem {
4 - DetailsListStatusItem(
5 - {required String title, required String value, this.status})
4 + DetailsListStatusItem({required String title, required String value, this.status})
5 : super(title: title, value: value);
6
7 final String? status; // waiting, action required, created, fetching, finished, success
lib/src/screens/transaction_details/address_list_item.dart
+1 -1
@@ -2,4 +2,4 @@ import 'package:cake_wallet/src/screens/transaction_details/transaction_details_
2
3 class AddressListItem extends TransactionDetailsListItem {
4 AddressListItem({required super.title, required super.value, super.key});
5 -}
\ No newline at end of file
5 +}
lib/src/screens/transaction_details/confirmations_list_item.dart
+3 -3
@@ -6,7 +6,7 @@ class ConfirmationsListItem extends TransactionDetailsListItem {
6
7 ConfirmationsListItem({required super.title, required super.value, super.key}) {
8 final parts = value.split("/");
9 - current = int.tryParse(parts.first)??0;
10 - needed = int.tryParse(parts.last)??0;
9 + current = int.tryParse(parts.first) ?? 0;
10 + needed = int.tryParse(parts.last) ?? 0;
11 }
12 -}
\ No newline at end of file
12 +}
lib/src/screens/transaction_details/rbf_details_page.dart
+2 -1
@@ -105,7 +105,8 @@ class RBFDetailsPage extends BasePage {
105 text: S.of(context).send,
106 isLoading:
107 transactionDetailsViewModel.sendViewModel.state is IsExecutingState,
108 - isDisabled: transactionDetailsViewModel.sendViewModel.state is ExecutedSuccessfullyState,
108 + isDisabled: transactionDetailsViewModel.sendViewModel.state
109 + is ExecutedSuccessfullyState,
110 color: Theme.of(context).colorScheme.primary,
111 textColor: Theme.of(context).colorScheme.onPrimary,
112 ))),
lib/src/screens/transaction_details/textfield_list_item.dart
+1 -1
@@ -14,4 +14,4 @@ class TextFieldListItem extends TransactionDetailsListItem {
14 );
15
16 final Function(String value) onSubmitted;
17 -}
\ No newline at end of file
17 +}
lib/src/screens/transaction_details/transaction_details_page.dart
+11 -21
@@ -103,8 +103,10 @@ class TransactionDetailsPage extends BasePage {
103 child: SelectButton(
104 text: S.of(context).bump_fee,
105 onTap: () async {
106 - Navigator.of(context).pushNamed(Routes.bumpFeePage,
107 - arguments: [transactionDetailsViewModel.transactionInfo, transactionDetailsViewModel.rawTransaction]);
106 + Navigator.of(context).pushNamed(Routes.bumpFeePage, arguments: [
107 + transactionDetailsViewModel.transactionInfo,
108 + transactionDetailsViewModel.rawTransaction
109 + ]);
110 },
111 ),
112 );
@@ -123,25 +125,17 @@ class TransactionDetailsPage extends BasePage {
125 required WalletType walletType,
126 }) {
127 final textStyle = Theme.of(context).textTheme.bodyMedium!.copyWith(
126 - fontSize: 16,
127 - fontWeight: FontWeight.w500,
128 - color: Theme.of(context).colorScheme.onSurface,
129 - );
128 + fontSize: 16,
129 + fontWeight: FontWeight.w500,
130 + color: Theme.of(context).colorScheme.onSurface,
131 + );
132 final List<Widget> children = [];
133 final bool hasDoubleNewline = value.contains('\n\n');
134
135 if (hasDoubleNewline) {
134 - final blocks = value
135 - .split('\n\n')
136 - .map((b) => b.trim())
137 - .where((b) => b.isNotEmpty)
138 - .toList();
136 + final blocks = value.split('\n\n').map((b) => b.trim()).where((b) => b.isNotEmpty).toList();
137 for (final block in blocks) {
140 - final lines = block
141 - .split('\n')
142 - .map((l) => l.trim())
143 - .where((l) => l.isNotEmpty)
144 - .toList();
138 + final lines = block.split('\n').map((l) => l.trim()).where((l) => l.isNotEmpty).toList();
139 if (lines.length > 1) {
140 children.add(Text(lines.first, style: textStyle));
141 for (int i = 1; i < lines.length; i++) {
@@ -165,11 +159,7 @@ class TransactionDetailsPage extends BasePage {
159 children.add(SizedBox(height: 8));
160 }
161 } else {
168 - final lines = value
169 - .split('\n')
170 - .map((l) => l.trim())
171 - .where((l) => l.isNotEmpty)
172 - .toList();
162 + final lines = value.split('\n').map((l) => l.trim()).where((l) => l.isNotEmpty).toList();
163 bool firstLineIsContactName = (lines.length > 1 && lines.first.length < 20);
164 int startIndex = 0;
165 if (firstLineIsContactName) {
lib/src/screens/transaction_details/transaction_expandable_list_item.dart
+1 -1
@@ -7,6 +7,6 @@ class StandardExpandableListItem<T> extends TransactionDetailsListItem {
7 required this.expandableItems,
8 Key? key,
9 }) : super(title: title, value: '', key: key);
10 -
10 +
11 final List<T> expandableItems;
12 }
lib/src/screens/unspent_coins/unspent_coins_list_page.dart
+40 -42
@@ -121,14 +121,14 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
121 canPop: false,
122 onPopInvokedWithResult: (bool didPop, Object? result) async {
123 if (didPop) return;
124 - if(mounted)
125 - await widget.handleOnPopInvoked(context);
124 + if (mounted) await widget.handleOnPopInvoked(context);
125 },
126 child: FutureBuilder<void>(
127 future: _initialization,
128 builder: (context, snapshot) {
129 if (snapshot.connectionState == ConnectionState.waiting) {
131 - return Center(child: CircularProgressIndicator(
130 + return Center(
131 + child: CircularProgressIndicator(
132 color: Theme.of(context).colorScheme.primary,
133 ));
134 }
@@ -153,10 +153,10 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
153 Text(
154 S.current.all_coins,
155 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
156 - fontSize: 16,
157 - fontWeight: FontWeight.bold,
158 - color: Theme.of(context).colorScheme.onSurface,
159 - ),
156 + fontSize: 16,
157 + fontWeight: FontWeight.bold,
158 + color: Theme.of(context).colorScheme.onSurface,
159 + ),
160 ),
161 ],
162 ),
@@ -165,46 +165,44 @@ class UnspentCoinsListFormState extends State<UnspentCoinsListForm> {
165 child: unspentCoinsListViewModel.items.isEmpty
166 ? Center(
167 child: Text(
168 - 'No unspent coins available',
169 - textAlign: TextAlign.center,
170 - style: Theme.of(context).textTheme.bodyMedium!.copyWith(
171 - color: Theme.of(context).colorScheme.onSurfaceVariant,
172 - ),
173 - )
174 - )
168 + 'No unspent coins available',
169 + textAlign: TextAlign.center,
170 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(
171 + color: Theme.of(context).colorScheme.onSurfaceVariant,
172 + ),
173 + ))
174 : ListView.separated(
175 itemCount: unspentCoinsListViewModel.items.length,
176 separatorBuilder: (_, __) => SizedBox(height: 15),
177 itemBuilder: (_, int index) {
178 final item = unspentCoinsListViewModel.items[index];
180 - return Observer(
181 - builder: (_) {
182 - final fiatAmount = unspentCoinsListViewModel.fiatAmounts[item.amount] ?? '';
183 - return GestureDetector(
184 - onTap: () => Navigator.of(context).pushNamed(
185 - Routes.unspentCoinsDetails,
186 - arguments: [item, unspentCoinsListViewModel],
187 - ),
188 - child: UnspentCoinsListItem(
189 - note: item.note,
190 - amount: item.amount,
191 - fiatAmount: fiatAmount,
192 - address: item.address,
193 - isSending: item.isSending,
194 - isFrozen: item.isFrozen,
195 - isChange: item.isChange,
196 - isSilentPayment: item.isSilentPayment,
197 - onCheckBoxTap: item.isFrozen
198 - ? null
199 - : () async {
200 - item.isSending = !item.isSending;
201 - await unspentCoinsListViewModel
202 - .saveUnspentCoinInfo(item);
203 - },
204 - ),
205 - );
206 - }
207 - );
179 + return Observer(builder: (_) {
180 + final fiatAmount =
181 + unspentCoinsListViewModel.fiatAmounts[item.amount] ?? '';
182 + return GestureDetector(
183 + onTap: () => Navigator.of(context).pushNamed(
184 + Routes.unspentCoinsDetails,
185 + arguments: [item, unspentCoinsListViewModel],
186 + ),
187 + child: UnspentCoinsListItem(
188 + note: item.note,
189 + amount: item.amount,
190 + fiatAmount: fiatAmount,
191 + address: item.address,
192 + isSending: item.isSending,
193 + isFrozen: item.isFrozen,
194 + isChange: item.isChange,
195 + isSilentPayment: item.isSilentPayment,
196 + onCheckBoxTap: item.isFrozen
197 + ? null
198 + : () async {
199 + item.isSending = !item.isSending;
200 + await unspentCoinsListViewModel
201 + .saveUnspentCoinInfo(item);
202 + },
203 + ),
204 + );
205 + });
206 },
207 ),
208 ),
lib/src/screens/unspent_coins/widgets/unspent_coins_list_item.dart
+24 -24
@@ -73,19 +73,19 @@ class UnspentCoinsListItem extends StatelessWidget {
73 AutoSizeText(
74 note,
75 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
76 - color: amountColor,
77 - fontSize: 15,
78 - fontWeight: FontWeight.w600,
79 - ),
76 + color: amountColor,
77 + fontSize: 15,
78 + fontWeight: FontWeight.w600,
79 + ),
80 maxLines: 1,
81 ),
82 AutoSizeText(
83 amount,
84 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
85 - color: amountColor,
86 - fontSize: 15,
87 - fontWeight: FontWeight.w600,
88 - ),
85 + color: amountColor,
86 + fontSize: 15,
87 + fontWeight: FontWeight.w600,
88 + ),
89 maxLines: 1,
90 )
91 ],
@@ -111,21 +111,21 @@ class UnspentCoinsListItem extends StatelessWidget {
111 ],
112 ),
113 if (fiatAmount.isNotEmpty)
114 - Row(
115 - mainAxisAlignment: MainAxisAlignment.spaceBetween,
116 - crossAxisAlignment: CrossAxisAlignment.start,
117 - children: [
118 - AutoSizeText(
119 - fiatAmount,
120 - style: Theme.of(context).textTheme.bodyMedium!.copyWith(
121 - color: amountColor,
122 - fontSize: 1,
123 - fontWeight: FontWeight.w600,
114 + Row(
115 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
116 + crossAxisAlignment: CrossAxisAlignment.start,
117 + children: [
118 + AutoSizeText(
119 + fiatAmount,
120 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(
121 + color: amountColor,
122 + fontSize: 1,
123 + fontWeight: FontWeight.w600,
124 + ),
125 + maxLines: 1,
126 ),
125 - maxLines: 1,
126 - ),
127 - ],
128 - ),
127 + ],
128 + ),
129 Expanded(
130 child: Row(
131 crossAxisAlignment: CrossAxisAlignment.center,
@@ -134,8 +134,8 @@ class UnspentCoinsListItem extends StatelessWidget {
134 AutoSizeText(
135 '${address.substring(0, 5)}...${address.substring(address.length - 5)}', // ToDo: Maybe use address label
136 style: Theme.of(context).textTheme.bodySmall!.copyWith(
137 - color: addressColor,
138 - ),
137 + color: addressColor,
138 + ),
139 maxLines: 1,
140 ),
141 Row(
lib/src/screens/ur/animated_ur_page.dart
+4 -8
@@ -64,8 +64,7 @@ class AnimatedURPage extends BasePage {
64 hardwareWalletType: animatedURmodel.wallet.hardwareWalletType,
65 ),
66 ),
67 - if (["ur:xmr-txunsigned", "ur:xmr-output", "ur:psbt", BBQR.header]
68 - .contains(urQrType)) ...{
67 + if (["ur:xmr-txunsigned", "ur:xmr-output", "ur:psbt", BBQR.header].contains(urQrType)) ...{
68 Padding(
69 padding: const EdgeInsets.all(16.0),
70 child: SizedBox(
@@ -89,8 +88,7 @@ class AnimatedURPage extends BasePage {
88 case "ur:xmr-txunsigned": // ur:xmr-txsigned
89 final ur = await presentQRScanner(context, showManualInput: false);
90 if (ur == null) return;
92 - final result =
93 - await monero!.commitTransactionUR(animatedURmodel.wallet, ur);
91 + final result = await monero!.commitTransactionUR(animatedURmodel.wallet, ur);
92 if (result) {
93 Navigator.of(context).pop(true);
94 }
@@ -98,8 +96,7 @@ class AnimatedURPage extends BasePage {
96 case "ur:xmr-output": // xmr-keyimage
97 final ur = await presentQRScanner(context, showManualInput: false);
98 if (ur == null) return;
101 - final result =
102 - await monero!.importKeyImagesUR(animatedURmodel.wallet, ur);
99 + final result = await monero!.importKeyImagesUR(animatedURmodel.wallet, ur);
100 if (result) {
101 Navigator.of(context).pop(true);
102 }
@@ -107,8 +104,7 @@ class AnimatedURPage extends BasePage {
104 case "ur:psbt": // psbt
105 final ur = await presentQRScanner(context, showManualInput: false);
106 if (ur == null) return;
110 - await bitcoin!
111 - .commitPsbtUR(animatedURmodel.wallet, ur.trim().split("\n"));
107 + await bitcoin!.commitPsbtUR(animatedURmodel.wallet, ur.trim().split("\n"));
108 Navigator.of(context).pop(true);
109 default:
110 throw UnimplementedError("unable to handle UR: ${urQrType}");
lib/src/screens/ur/widgets/qr_format_info_bottom_sheet.dart
+1 -4
@@ -24,10 +24,7 @@ class QRFormatInfoBottomSheet extends StatelessWidget {
24 width: 40,
25 height: 4,
26 decoration: BoxDecoration(
27 - color: Theme.of(context)
28 - .colorScheme
29 - .onSurface
30 - .withOpacity(0.3),
27 + color: Theme.of(context).colorScheme.onSurface.withOpacity(0.3),
28 borderRadius: BorderRadius.circular(2),
29 ),
30 ),
lib/src/screens/ur/widgets/qr_selection_dialog.dart
+2 -7
@@ -90,9 +90,7 @@ class QRFormatSelectionDialog extends BaseAlertDialog {
90 fontSize: 14,
91 fontWeight: FontWeight.w600,
92 color: isSelected
93 - ? Theme.of(context)
94 - .colorScheme
95 - .onPrimaryContainer
93 + ? Theme.of(context).colorScheme.onPrimaryContainer
94 : Theme.of(context).colorScheme.onSurface,
95 ),
96 ),
@@ -105,10 +103,7 @@ class QRFormatSelectionDialog extends BaseAlertDialog {
103 .colorScheme
104 .onPrimaryContainer
105 .withOpacity(0.6)
108 - : Theme.of(context)
109 - .colorScheme
110 - .onSurface
111 - .withOpacity(0.6),
106 + : Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
107 ),
108 ),
109 ],
lib/src/screens/ur/widgets/urqr.dart
+5 -9
@@ -53,19 +53,17 @@ class _URQRState extends State<URQR> {
53
54 String get nextLabel => widget.urqr.keys.toList()[(selectedInt + 1) % widget.urqr.length];
55 void next() => setState(() {
56 - final keys = widget.urqr.keys.toList();
56 + final keys = widget.urqr.keys.toList();
57
58 - selectedInt++;
59 - selected = keys[(selectedInt) % keys.length];
60 - });
58 + selectedInt++;
59 + selected = keys[(selectedInt) % keys.length];
60 + });
61
62 late String selected = (widget.urqr.isEmpty) ? "unknown" : widget.urqr.keys.first;
63
64 -
64 List<String> get frames => widget.urqr[selected]?.split("\n") ?? [];
65 void _nextFrame() => setState(() => frame++);
66
68 -
67 @override
68 Widget build(BuildContext context) {
69 return Column(
@@ -85,9 +83,7 @@ class _URQRState extends State<URQR> {
83 ),
84 ),
85 if (widget.urqr.values.length > 1)
88 - widget.walletType == WalletType.monero
89 - ? _legacySwitch(context)
90 - : _newSwitch(context),
86 + widget.walletType == WalletType.monero ? _legacySwitch(context) : _newSwitch(context),
87 if (FeatureFlag.hasDevOptions) ...{
88 TextButton(
89 onPressed: () {
lib/src/screens/wallet_connect/services/chain_service/eth/evm_supported_methods.dart
+1 -1
@@ -28,4 +28,4 @@ enum EVMSupportedMethods {
28 return 'eth_sendTransaction';
29 }
30 }
31 -}
\ No newline at end of file
31 +}
lib/src/screens/wallet_connect/services/walletkit_service.dart
+19 -20
@@ -133,9 +133,9 @@ abstract class WalletKitServiceBase with Store {
133 if (!isInitialized) {
134 try {
135 await _walletKit.init().timeout(
136 - const Duration(seconds: 8),
137 - onTimeout: () => throw TimeoutException('walletKit init timed out'),
138 - );
136 + const Duration(seconds: 8),
137 + onTimeout: () => throw TimeoutException('walletKit init timed out'),
138 + );
139 debugPrint('Initialized');
140 isInitialized = true;
141 } catch (e) {
@@ -202,14 +202,16 @@ abstract class WalletKitServiceBase with Store {
202 namespaces: session.namespaces,
203 );
204 if (events.contains('accountsChanged')) {
205 - await _walletKit.emitSessionEvent(
206 - topic: session.topic,
207 - chainId: chainID,
208 - event: SessionEventParams(
209 - name: 'accountsChanged',
210 - data: [chain.publicKey],
211 - ),
212 - ).timeout(const Duration(seconds: 3));
205 + await _walletKit
206 + .emitSessionEvent(
207 + topic: session.topic,
208 + chainId: chainID,
209 + event: SessionEventParams(
210 + name: 'accountsChanged',
211 + data: [chain.publicKey],
212 + ),
213 + )
214 + .timeout(const Duration(seconds: 3));
215 }
216 } on ReownSignError catch (e) {
217 if (e.code == 6) {
@@ -433,12 +435,10 @@ abstract class WalletKitServiceBase with Store {
435 }
436
437 final requesterMetadata = args.requester.metadata;
436 - final requesterIcon = requesterMetadata.icons.isNotEmpty
437 - ? requesterMetadata.icons.first
438 - : null;
438 + final requesterIcon =
439 + requesterMetadata.icons.isNotEmpty ? requesterMetadata.icons.first : null;
440 final chainKeysForAuth = walletKeyService.getKeysForChain(appStore.wallet!);
440 - final addressForAuth =
441 - chainKeysForAuth.isNotEmpty ? chainKeysForAuth.first.publicKey : '';
441 + final addressForAuth = chainKeysForAuth.isNotEmpty ? chainKeysForAuth.first.publicKey : '';
442 final combinedMessageBody =
443 formattedMessages.map((m) => m.values.first as String).join('\n\n');
444
@@ -521,8 +521,7 @@ abstract class WalletKitServiceBase with Store {
521
522 @action
523 Future<void> deletePairing({required String topic}) async {
524 - final topicSessions =
525 - sessions.where((element) => element.pairingTopic == topic).toList();
524 + final topicSessions = sessions.where((element) => element.pairingTopic == topic).toList();
525
526 await _walletKit.core.pairing.disconnect(topic: topic);
527 for (var session in topicSessions) {
@@ -557,7 +556,7 @@ abstract class WalletKitServiceBase with Store {
556 reason: Errors.getSdkError(Errors.USER_DISCONNECTED).toSignError(),
557 );
558 } catch (e) {
560 - printV('disconnectSession: $e');
559 + printV('disconnectSession: $e');
560 }
561
562 sessions.clear();
@@ -622,7 +621,7 @@ abstract class WalletKitServiceBase with Store {
621
622 @action
623 List<SessionData> getSessionsForPairingInfo(PairingInfo pairing) {
625 - return sessions.where((element) => element.pairingTopic == pairing.topic).toList();
624 + return sessions.where((element) => element.pairingTopic == pairing.topic).toList();
625 }
626
627 String getKeyForStoringTopicsForWallet() {
lib/src/screens/wallet_connect/utils/method_utils.dart
+4 -9
@@ -13,7 +13,7 @@ import 'package:reown_walletkit/reown_walletkit.dart';
13 class MethodsUtils {
14 static final walletKit = getIt.get<WalletKitService>().walletKit;
15 static final bottomSheetService = getIt.get<BottomSheetService>();
16 -
16 +
17 static const _transactionMethods = {
18 'eth_sendTransaction',
19 'eth_signTransaction',
@@ -34,18 +34,13 @@ class MethodsUtils {
34 }) async {
35 final appStore = getIt.get<AppStore>();
36 final pending = walletKit.pendingRequests.getAll();
37 - final session = pending.isNotEmpty
38 - ? walletKit.sessions.get(pending.last.topic)
39 - : null;
37 + final session = pending.isNotEmpty ? walletKit.sessions.get(pending.last.topic) : null;
38 final dAppMetadata = session?.peer.metadata;
39
40 final isTransaction = method != null && _transactionMethods.contains(method);
41 final resolvedTitle = title ??
44 - (isTransaction
45 - ? S.current.wc_approve_request_title
46 - : S.current.wc_signing_request_title);
47 - final swipeLabel =
48 - isTransaction ? S.current.wc_swipe_to_approve : S.current.wc_swipe_to_sign;
42 + (isTransaction ? S.current.wc_approve_request_title : S.current.wc_signing_request_title);
43 + final swipeLabel = isTransaction ? S.current.wc_swipe_to_approve : S.current.wc_swipe_to_sign;
44
45 final extraRows = <WCMessageRow>[];
46 if (method != null && method.isNotEmpty) {
lib/src/screens/wallet_connect/utils/wc_permissions_mapper.dart
+2 -1
@@ -39,7 +39,8 @@ class WCPermissionsMapper {
39 }
40
41 final permissions = <WCPermission>[
42 - WCPermission(iconUrl: "assets/new-ui/global_view.svg", label: S.current.wc_permission_view_balance),
42 + WCPermission(
43 + iconUrl: "assets/new-ui/global_view.svg", label: S.current.wc_permission_view_balance),
44 ];
45
46 final wantsTransactionApproval = methods.any(_transactionMethods.contains);
lib/src/screens/wallet_connect/wc_connections_listing_view.dart
+1 -1
@@ -227,4 +227,4 @@ class WalletConnectConnectionsView extends StatelessWidget {
227 ),
228 );
229 }
230 -}
\ No newline at end of file
230 +}
lib/src/screens/wallet_connect/widgets/enter_wallet_connect_uri_widget.dart
+2 -2
@@ -78,12 +78,12 @@ class EnterWalletConnectURIWidget extends BaseAlertDialog {
78 width: 36,
79 height: 36,
80 padding: EdgeInsets.only(top: 0),
81 - child: Semantics(
81 + child: Semantics(
82 label: S.of(context).paste,
83 child: InkWell(
84 onTap: () => _pasteWalletConnectURI(),
85 child: Container(
86 - padding: EdgeInsets.all(8),
86 + padding: EdgeInsets.all(8),
87 decoration: BoxDecoration(
88 borderRadius: BorderRadius.all(Radius.circular(6)),
89 ),
lib/src/screens/wallet_connect/widgets/wc_hero_card.dart
-1
@@ -1,4 +1,3 @@
1 -
1 import 'package:cake_wallet/generated/i18n.dart';
2 import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
3 import 'package:flutter/material.dart';
lib/src/screens/wallet_keys/wallet_keys_page.dart
+1 -1
@@ -184,7 +184,7 @@ class _WalletKeysPageBodyState extends State<WalletKeysPageBody>
184 Widget _buildSeedTab(BuildContext context, bool isLegacySeed) {
185 return Column(
186 children: [
187 - if (isLegacySeedOnly || isLegacySeed ||widget.walletKeysViewModel.shouldShowHeightBox) ...[
187 + if (isLegacySeedOnly || isLegacySeed || widget.walletKeysViewModel.shouldShowHeightBox) ...[
188 _buildHeightBox(),
189 const SizedBox(height: 20),
190 ],
lib/src/screens/wallet_list/wallet_list_page.dart
+42 -44
@@ -143,7 +143,7 @@ class WalletListBodyState extends State<WalletListBody> {
143 @override
144 Widget build(BuildContext context) {
145 return GradientBackground(
146 - scaffold: Container(
146 + scaffold: Container(
147 height: double.infinity,
148 padding: EdgeInsets.only(top: 16),
149 child: Stack(
@@ -339,45 +339,45 @@ class WalletListBodyState extends State<WalletListBody> {
339 Stack(
340 alignment: Alignment.bottomCenter,
341 children: [
342 - !FeatureFlag.hasNewUi
343 - ? IgnorePointer(
344 - child: Container(
345 - alignment: Alignment.bottomCenter,
346 - height: 185,
347 - decoration: BoxDecoration(
348 - gradient: LinearGradient(
349 - begin: Alignment.topCenter,
350 - end: Alignment.bottomCenter,
351 - colors: <Color>[
352 - Theme.of(context).colorScheme.surface.withAlpha(10),
353 - Theme.of(context).colorScheme.surface,
354 - Theme.of(context).colorScheme.surface,
355 - Theme.of(context).colorScheme.surface
356 - ],
357 - ),
358 - ),
359 - ),
360 - )
361 - : IgnorePointer(
362 - child: Container(
363 - height: 275,
364 - decoration: BoxDecoration(
365 - gradient: LinearGradient(
366 - begin: Alignment.topCenter,
367 - end: Alignment.bottomCenter,
368 - colors: <Color>[
369 - Theme.of(context).colorScheme.surfaceDim.withAlpha(10),
370 - Theme.of(context).colorScheme.surfaceDim.withAlpha(150),
371 - Theme.of(context).colorScheme.surfaceDim.withAlpha(255),
372 - Theme.of(context).colorScheme.surfaceDim.withAlpha(255),
373 - Theme.of(context).colorScheme.surfaceDim.withAlpha(255),
374 - Theme.of(context).colorScheme.surfaceDim.withAlpha(255),
375 - Theme.of(context).colorScheme.surfaceDim.withAlpha(255)
376 - ],
342 + !FeatureFlag.hasNewUi
343 + ? IgnorePointer(
344 + child: Container(
345 + alignment: Alignment.bottomCenter,
346 + height: 185,
347 + decoration: BoxDecoration(
348 + gradient: LinearGradient(
349 + begin: Alignment.topCenter,
350 + end: Alignment.bottomCenter,
351 + colors: <Color>[
352 + Theme.of(context).colorScheme.surface.withAlpha(10),
353 + Theme.of(context).colorScheme.surface,
354 + Theme.of(context).colorScheme.surface,
355 + Theme.of(context).colorScheme.surface
356 + ],
357 + ),
358 + ),
359 + ),
360 + )
361 + : IgnorePointer(
362 + child: Container(
363 + height: 275,
364 + decoration: BoxDecoration(
365 + gradient: LinearGradient(
366 + begin: Alignment.topCenter,
367 + end: Alignment.bottomCenter,
368 + colors: <Color>[
369 + Theme.of(context).colorScheme.surfaceDim.withAlpha(10),
370 + Theme.of(context).colorScheme.surfaceDim.withAlpha(150),
371 + Theme.of(context).colorScheme.surfaceDim.withAlpha(255),
372 + Theme.of(context).colorScheme.surfaceDim.withAlpha(255),
373 + Theme.of(context).colorScheme.surfaceDim.withAlpha(255),
374 + Theme.of(context).colorScheme.surfaceDim.withAlpha(255),
375 + Theme.of(context).colorScheme.surfaceDim.withAlpha(255)
376 + ],
377 + ),
378 + ),
379 + ),
380 ),
378 - ),
379 - ),
380 - ),
381 Container(
382 height: 240,
383 width: MediaQuery.of(context).size.width,
@@ -464,8 +464,7 @@ class WalletListBodyState extends State<WalletListBody> {
464 color: Theme.of(context).colorScheme.primary,
465 textColor: Theme.of(context).colorScheme.onPrimary,
466 ),
467 - if(FeatureFlag.hasNewUi)
468 - SizedBox(height:52.0)
467 + if (FeatureFlag.hasNewUi) SizedBox(height: 52.0)
468 ],
469 ),
470 ),
@@ -578,9 +577,8 @@ class WalletListBodyState extends State<WalletListBody> {
577 if (_progressBar != null) {
578 _progressBar!.dismiss();
579 }
581 - _progressBar = createBar<void>(text, context, duration: null)
582 - ..show(context);
583 - }catch(e){}
580 + _progressBar = createBar<void>(text, context, duration: null)..show(context);
581 + } catch (e) {}
582 }
583
584 Future<void> hideProgressText() async {
lib/src/screens/wallet_unlock/wallet_unlock_arguments.dart
+1 -4
@@ -5,10 +5,7 @@ typedef AuthPasswordHandler = Future<void> Function(String);
5
6 class WalletUnlockArguments {
7 WalletUnlockArguments(
8 - {required this.callback,
9 - this.walletName,
10 - this.walletType,
11 - this.authPasswordHandler});
8 + {required this.callback, this.walletName, this.walletType, this.authPasswordHandler});
9
10 final OnAuthenticationFinished callback;
11 final AuthPasswordHandler? authPasswordHandler;
lib/src/screens/welcome/create_pin_welcome_page.dart
+2 -1
@@ -228,7 +228,8 @@ class CreatePinWelcomePage extends BasePage {
228 child: PrimaryButton(
229 key: ValueKey('create_pin_welcome_page_create_a_pin_button_key'),
230 onPressed: () => Navigator.pushNamed(context, Routes.welcomeWallet),
231 - text: isWalletPasswordDirectInput ? S.current.set_up_a_wallet : S.current.set_a_pin,
231 + text:
232 + isWalletPasswordDirectInput ? S.current.set_up_a_wallet : S.current.set_a_pin,
233 color: Theme.of(context).colorScheme.primary,
234 textColor: Theme.of(context).colorScheme.onPrimary,
235 ),
lib/src/screens/welcome/welcome_page.dart
+6 -4
@@ -22,17 +22,19 @@ class WelcomePage extends BasePage {
22
23 @override
24 Widget Function(BuildContext, Widget) get rootWrapper =>
25 - (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
25 + (BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
26
27 @override
28 bool get resizeToAvoidBottomInset => false;
29
30 @override
31 Widget trailing(BuildContext context) {
32 - final Uri _url =
33 - Uri.parse('https://docs.cakewallet.com/get-started/setup/');
32 + final Uri _url = Uri.parse('https://docs.cakewallet.com/get-started/setup/');
33 return IconButton(
35 - icon: Icon(Icons.info_outline, size: 26,),
34 + icon: Icon(
35 + Icons.info_outline,
36 + size: 26,
37 + ),
38 onPressed: () async {
39 await launchUrl(_url);
40 },
lib/src/screens/yat/widgets/first_introduction.dart
+37 -58
@@ -25,65 +25,44 @@ class FirstIntroduction extends StatelessWidget {
25 color: Theme.of(context).colorScheme.surfaceContainer,
26 child: ScrollableWithBottomSection(
27 contentPadding: EdgeInsets.only(top: 40, bottom: 40),
28 - content: Column(
29 - children: [
30 - Container(
31 - height: 45,
32 - padding: EdgeInsets.only(left: 24, right: 24),
33 - child: YatBar(onClose: () => Navigator.of(context).pop())
34 - ),
35 - animation,
36 - Container(
37 - padding: EdgeInsets.only(left: 30, right: 30),
38 - child: Column(
39 - children: [
40 - Text(
41 - S.of(context).yat_alert_title,
42 - textAlign: TextAlign.center,
43 - style: Theme.of(context).textTheme.bodyMedium!.copyWith(
44 - fontSize: 24,
45 - fontWeight: FontWeight.bold,
46 -
28 + content: Column(children: [
29 + Container(
30 + height: 45,
31 + padding: EdgeInsets.only(left: 24, right: 24),
32 + child: YatBar(onClose: () => Navigator.of(context).pop())),
33 + animation,
34 + Container(
35 + padding: EdgeInsets.only(left: 30, right: 30),
36 + child: Column(children: [
37 + Text(S.of(context).yat_alert_title,
38 + textAlign: TextAlign.center,
39 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(
40 + fontSize: 24,
41 + fontWeight: FontWeight.bold,
42 + color: Theme.of(context).colorScheme.onSurface,
43 + decoration: TextDecoration.none,
44 + )),
45 + Padding(
46 + padding: EdgeInsets.only(top: 20),
47 + child: Text(S.of(context).yat_alert_content,
48 + textAlign: TextAlign.center,
49 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(
50 + fontSize: 16,
51 + fontWeight: FontWeight.normal,
52 color: Theme.of(context).colorScheme.onSurface,
53 decoration: TextDecoration.none,
49 - )
50 - ),
51 - Padding(
52 - padding: EdgeInsets.only(top: 20),
53 - child: Text(
54 - S.of(context).yat_alert_content,
55 - textAlign: TextAlign.center,
56 - style: Theme.of(context).textTheme.bodyMedium!.copyWith(
57 - fontSize: 16,
58 - fontWeight: FontWeight.normal,
59 -
60 - color: Theme.of(context).colorScheme.onSurface,
61 - decoration: TextDecoration.none,
62 - )
63 - )
64 - )
65 - ]
66 - )
67 - )
68 - ]
69 - ),
54 + )))
55 + ]))
56 + ]),
57 bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24),
71 - bottomSection: Column(
72 - crossAxisAlignment: CrossAxisAlignment.center,
73 - children: [
74 - PrimaryButton(
75 - text: S.of(context).restore_next,
76 - textColor: Theme.of(context).colorScheme.onPrimary,
77 - color: Theme.of(context).colorScheme.primary,
78 - onPressed: onNext
79 - ),
80 - Padding(
81 - padding: EdgeInsets.only(top: 24),
82 - child: YatPageIndicator(filled: 0)
83 - )
84 - ]
85 - ),
86 - )
87 - );
58 + bottomSection: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
59 + PrimaryButton(
60 + text: S.of(context).restore_next,
61 + textColor: Theme.of(context).colorScheme.onPrimary,
62 + color: Theme.of(context).colorScheme.primary,
63 + onPressed: onNext),
64 + Padding(padding: EdgeInsets.only(top: 24), child: YatPageIndicator(filled: 0))
65 + ]),
66 + ));
67 }
89 -}
\ No newline at end of file
68 +}
lib/src/screens/yat/widgets/second_introduction.dart
+23 -41
@@ -29,60 +29,42 @@ class SecondIntroduction extends StatelessWidget {
29 Container(
30 height: 45,
31 padding: EdgeInsets.only(left: 24, right: 24),
32 - child: YatBar(onClose: onClose)
33 - ),
32 + child: YatBar(onClose: onClose)),
33 animation,
34 Padding(
35 padding: EdgeInsets.only(top: 40, left: 30, right: 30),
37 - child: Column(
38 - children: [
39 - Text(
40 - S.of(context).second_intro_title,
41 - textAlign: TextAlign.center,
42 - style: Theme.of(context).textTheme.bodyMedium!.copyWith(
36 + child: Column(children: [
37 + Text(S.of(context).second_intro_title,
38 + textAlign: TextAlign.center,
39 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(
40 fontSize: 24,
41 fontWeight: FontWeight.bold,
45 -
42 color: Theme.of(context).colorScheme.onSurface,
43 decoration: TextDecoration.none,
48 - )
49 - ),
50 - Padding(
51 - padding: EdgeInsets.only(top: 20),
52 - child: Text(
53 - S.of(context).second_intro_content,
54 - textAlign: TextAlign.center,
55 - style: Theme.of(context).textTheme.bodyMedium!.copyWith(
44 + )),
45 + Padding(
46 + padding: EdgeInsets.only(top: 20),
47 + child: Text(S.of(context).second_intro_content,
48 + textAlign: TextAlign.center,
49 + style: Theme.of(context).textTheme.bodyMedium!.copyWith(
50 fontSize: 16,
51 fontWeight: FontWeight.normal,
58 -
52 color: Theme.of(context).colorScheme.onSurface,
53 decoration: TextDecoration.none,
61 - )
62 - )
63 - )
64 - ]
65 - ),
54 + )))
55 + ]),
56 ),
57 ],
58 ),
59 bottomSectionPadding: EdgeInsets.fromLTRB(24, 0, 24, 24),
70 - bottomSection: Column(
71 - crossAxisAlignment: CrossAxisAlignment.center,
72 - children: [
73 - PrimaryButton(
74 - text: S.of(context).restore_next,
75 - textColor: Theme.of(context).colorScheme.onPrimary,
76 - color: Theme.of(context).colorScheme.primary,
77 - onPressed: onNext
78 - ),
79 - Padding(
80 - padding: EdgeInsets.only(top: 24),
81 - child: YatPageIndicator(filled: 1)
82 - )
83 - ]
84 - ),
85 - )
86 - );
60 + bottomSection: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
61 + PrimaryButton(
62 + text: S.of(context).restore_next,
63 + textColor: Theme.of(context).colorScheme.onPrimary,
64 + color: Theme.of(context).colorScheme.primary,
65 + onPressed: onNext),
66 + Padding(padding: EdgeInsets.only(top: 24), child: YatPageIndicator(filled: 1))
67 + ]),
68 + ));
69 }
88 -}
\ No newline at end of file
70 +}
lib/src/screens/yat/widgets/third_introduction.dart
+10 -12
@@ -39,23 +39,21 @@ class ThirdIntroduction extends StatelessWidget {
39 Text(S.of(context).third_intro_title,
40 textAlign: TextAlign.center,
41 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
42 - fontSize: 24,
43 - fontWeight: FontWeight.bold,
44 -
45 - color: Theme.of(context).colorScheme.onSurface,
46 - decoration: TextDecoration.none,
47 - )),
42 + fontSize: 24,
43 + fontWeight: FontWeight.bold,
44 + color: Theme.of(context).colorScheme.onSurface,
45 + decoration: TextDecoration.none,
46 + )),
47 Padding(
48 padding: EdgeInsets.only(top: 20),
49 child: Text(S.of(context).third_intro_content,
50 textAlign: TextAlign.center,
51 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
53 - fontSize: 16,
54 - fontWeight: FontWeight.normal,
55 -
56 - color: Theme.of(context).colorScheme.onSurface,
57 - decoration: TextDecoration.none,
58 - )))
52 + fontSize: 16,
53 + fontWeight: FontWeight.normal,
54 + color: Theme.of(context).colorScheme.onSurface,
55 + decoration: TextDecoration.none,
56 + )))
57 ])),
58 ],
59 ),
lib/src/screens/yat/widgets/yat_bar.dart
+5 -15
@@ -9,19 +9,9 @@ class YatBar extends StatelessWidget {
9
10 @override
11 Widget build(BuildContext context) {
12 - return Stack(
13 - alignment: Alignment.bottomCenter,
14 - children: [
15 - Positioned(
16 - top: 0,
17 - right: 0,
18 - child: YatCloseButton(onClose: onClose)
19 - ),
20 - Positioned(
21 - top: 16,
22 - child: image
23 - )
24 - ]
25 - );
12 + return Stack(alignment: Alignment.bottomCenter, children: [
13 + Positioned(top: 0, right: 0, child: YatCloseButton(onClose: onClose)),
14 + Positioned(top: 16, child: image)
15 + ]);
16 }
27 -}
\ No newline at end of file
17 +}
lib/src/screens/yat/widgets/yat_page_indicator.dart
+3 -7
@@ -22,11 +22,7 @@ class YatPageIndicator extends StatelessWidget {
22 shape: BoxShape.circle,
23 color: isFilled
24 ? Theme.of(context).colorScheme.primary
25 - : Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.1)
26 - )
27 - );
28 - })
29 - )
30 - );
25 + : Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.1)));
26 + })));
27 }
32 -}
\ No newline at end of file
28 +}
lib/src/widgets/adaptable_page_view.dart
+1 -2
@@ -156,7 +156,6 @@ class _RenderSizingContainer extends RenderProxyBox {
156 final double t = (page - floorPage).clamp(0.0, 1.0);
157 final double height = lerpDouble(a.height, b.height, t) ?? a.height;
158
159 -
159 child.layout(
160 constraints.copyWith(minHeight: height, maxHeight: height),
161 parentUsesSize: true,
@@ -214,4 +213,4 @@ class _RenderSizeAware extends RenderProxyBox {
213 ),
214 );
215 }
217 -}
\ No newline at end of file
216 +}
lib/src/widgets/alert_with_picker_option.dart
-1
@@ -48,7 +48,6 @@ class AlertWithPickerOption extends BaseAlertDialog {
48 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
49 fontSize: 10,
50 fontWeight: FontWeight.w500,
51 -
51 color: Theme.of(context).colorScheme.onSurface,
52 decoration: TextDecoration.none,
53 ),
lib/src/widgets/base_alert_dialog.dart
+45 -52
@@ -5,36 +5,30 @@ import 'package:cake_wallet/src/widgets/cake_image_widget.dart';
5 import 'package:cake_wallet/src/widgets/section_divider.dart';
6 import 'package:flutter/material.dart';
7
8 -
8 class AlertButtonStyle {
9 final Color backgroundColor;
10 final Color textColor;
11 final FontWeight fontWeight;
12
14 - const AlertButtonStyle({
15 - required this.backgroundColor,
16 - required this.textColor,
17 - this.fontWeight = FontWeight.w400
18 - });
13 + const AlertButtonStyle(
14 + {required this.backgroundColor, required this.textColor, this.fontWeight = FontWeight.w400});
15
16 factory AlertButtonStyle.primary(BuildContext context) => AlertButtonStyle(
21 - backgroundColor: Theme.of(context).colorScheme.primary,
22 - textColor: Theme.of(context).colorScheme.onPrimary,
23 - );
17 + backgroundColor: Theme.of(context).colorScheme.primary,
18 + textColor: Theme.of(context).colorScheme.onPrimary,
19 + );
20
21 factory AlertButtonStyle.secondary(BuildContext context) => AlertButtonStyle(
26 - backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
27 - textColor: Theme.of(context).colorScheme.primary,
28 - );
22 + backgroundColor: Theme.of(context).colorScheme.surfaceContainer,
23 + textColor: Theme.of(context).colorScheme.primary,
24 + );
25
26 factory AlertButtonStyle.error(BuildContext context) => AlertButtonStyle(
31 - backgroundColor: Theme.of(context).colorScheme.errorContainer,
32 - textColor: Theme.of(context).colorScheme.error,
33 - fontWeight: FontWeight.w500
34 - );
27 + backgroundColor: Theme.of(context).colorScheme.errorContainer,
28 + textColor: Theme.of(context).colorScheme.error,
29 + fontWeight: FontWeight.w500);
30 }
31
37 -
32 class BaseAlertDialog extends StatelessWidget {
33 String? get headerText => '';
34
@@ -67,7 +61,7 @@ class BaseAlertDialog extends StatelessWidget {
61 Key? rightActionButtonKey;
62
63 Key? dialogKey;
70 -
64 +
65 AlertButtonStyle? get leftAlertButtonStyle => null;
66
67 AlertButtonStyle? get rightAlertButtonStyle => null;
@@ -129,29 +123,30 @@ class BaseAlertDialog extends StatelessWidget {
123 return Row(
124 mainAxisAlignment: MainAxisAlignment.center,
125 mainAxisSize: MainAxisSize.max,
132 - spacing:8,
126 + spacing: 8,
127 children: <Widget>[
134 - if(showLeftButton)
135 - Expanded(
136 - child: GestureDetector(
137 - key: leftActionButtonKey,
138 - onTap: actionLeft,
139 - child: Container(
140 - decoration: BoxDecoration(
141 - borderRadius: BorderRadius.circular(999999),
142 - color: leftButtonStyle.backgroundColor
143 - ),
144 - child: Padding(
145 - padding: EdgeInsets.symmetric(vertical: 16, horizontal: 8),
146 - child: AutoSizeText(
147 - maxLines:1,
148 - leftActionButtonText,
149 - textAlign: TextAlign.center,
150 - style: TextStyle(fontSize: 16, color: leftButtonStyle.textColor, fontWeight: leftButtonStyle.fontWeight)
128 + if (showLeftButton)
129 + Expanded(
130 + child: GestureDetector(
131 + key: leftActionButtonKey,
132 + onTap: actionLeft,
133 + child: Container(
134 + decoration: BoxDecoration(
135 + borderRadius: BorderRadius.circular(999999),
136 + color: leftButtonStyle.backgroundColor),
137 + child: Padding(
138 + padding: EdgeInsets.symmetric(vertical: 16, horizontal: 8),
139 + child: AutoSizeText(
140 + maxLines: 1,
141 + leftActionButtonText,
142 + textAlign: TextAlign.center,
143 + style: TextStyle(
144 + fontSize: 16,
145 + color: leftButtonStyle.textColor,
146 + fontWeight: leftButtonStyle.fontWeight)),
147 ),
152 - ),
153 - )),
154 - ),
148 + )),
149 + ),
150 Expanded(
151 child: GestureDetector(
152 key: rightActionButtonKey,
@@ -159,16 +154,17 @@ class BaseAlertDialog extends StatelessWidget {
154 child: Container(
155 decoration: BoxDecoration(
156 borderRadius: BorderRadius.circular(999999),
162 - color: rightButtonStyle.backgroundColor
163 - ),
157 + color: rightButtonStyle.backgroundColor),
158 child: Padding(
159 padding: EdgeInsets.symmetric(vertical: 16, horizontal: 8),
160 child: AutoSizeText(
167 - maxLines: 1,
168 - rightActionButtonText,
169 - textAlign: TextAlign.center,
170 - style: TextStyle(fontSize: 16, color: rightButtonStyle.textColor, fontWeight: rightButtonStyle.fontWeight)
171 - ),
161 + maxLines: 1,
162 + rightActionButtonText,
163 + textAlign: TextAlign.center,
164 + style: TextStyle(
165 + fontSize: 16,
166 + color: rightButtonStyle.textColor,
167 + fontWeight: rightButtonStyle.fontWeight)),
168 ),
169 )),
170 ),
@@ -185,7 +181,7 @@ class BaseAlertDialog extends StatelessWidget {
181 radius: 50,
182 backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest,
183 child: ClipOval(
188 - child: CakeImageWidget (imageUrl: imageUrl, width: 100, height: 100, fit: BoxFit.cover),
184 + child: CakeImageWidget(imageUrl: imageUrl, width: 100, height: 100, fit: BoxFit.cover),
185 ),
186 ),
187 );
@@ -201,8 +197,7 @@ class BaseAlertDialog extends StatelessWidget {
197 child: BackdropFilter(
198 filter: ImageFilter.blur(sigmaX: 3.0, sigmaY: 3.0),
199 child: Container(
204 - decoration:
205 - BoxDecoration(color: Theme.of(context).colorScheme.onSurface.withAlpha(25)),
200 + decoration: BoxDecoration(color: Theme.of(context).colorScheme.onSurface.withAlpha(25)),
201 child: Center(
202 child: Padding(
203 padding: const EdgeInsets.all(16.0),
@@ -229,9 +224,7 @@ class BaseAlertDialog extends StatelessWidget {
224 crossAxisAlignment: CrossAxisAlignment.center,
225 children: <Widget>[
226 if (headerText?.isNotEmpty ?? false) headerTitle(context),
232 - titleText != null
233 - ? title(context)
234 - : SizedBox(height: 16),
227 + titleText != null ? title(context) : SizedBox(height: 16),
228 isDividerExists
229 ? Padding(
230 padding: EdgeInsets.only(top: 16, bottom: 8),
lib/src/widgets/base_text_form_field.dart
+2 -1
@@ -47,7 +47,8 @@ class BaseTextFormField extends StatelessWidget {
47 this.suffixIconConstraints,
48 super.key,
49 this.suffixText,
50 - this.borderRadius = const BorderRadius.all(Radius.circular(18)), this.onEditingComplete,
50 + this.borderRadius = const BorderRadius.all(Radius.circular(18)),
51 + this.onEditingComplete,
52 });
53
54 final TextEditingController? controller;
lib/src/widgets/blockchain_height_widget.dart
+1 -1
@@ -195,7 +195,7 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
195 height = decred!.heightByDate(date);
196 } else if (widget.walletType == WalletType.monero) {
197 height = monero!.getHeightByDate(date: date);
198 - } else if (widget.walletType == WalletType.wownero){
198 + } else if (widget.walletType == WalletType.wownero) {
199 height = wownero!.getHeightByDate(date: date);
200 } else if (widget.walletType == WalletType.zcash) {
201 height = await zcash!.getHeightByDate(date);
lib/src/widgets/bottom_sheet/cake_pay_transaction_sent_bottom_sheet.dart
+6 -15
@@ -49,8 +49,7 @@ class CakePayTransactionSentBottomSheet extends StatelessWidget {
49 color: Theme.of(ctx).colorScheme.onSurfaceVariant,
50 );
51
52 - Widget _buildHeader(BuildContext ctx) =>
53 - Column(
52 + Widget _buildHeader(BuildContext ctx) => Column(
53 children: [
54 const SizedBox(height: 12),
55 Container(
@@ -81,8 +80,7 @@ class CakePayTransactionSentBottomSheet extends StatelessWidget {
80 ],
81 );
82
84 - Widget _buildBody(BuildContext context) =>
85 - Padding(
83 + Widget _buildBody(BuildContext context) => Padding(
84 padding: const EdgeInsets.symmetric(horizontal: 8),
85 child: Column(
86 children: [
@@ -123,7 +121,6 @@ class CakePayTransactionSentBottomSheet extends StatelessWidget {
121 copyButtonOnPressed: () async =>
122 await Clipboard.setData(ClipboardData(text: paymentIdValue)),
123 ),
126 -
124 Padding(
125 padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
126 child: Column(
@@ -157,10 +154,7 @@ class CakePayTransactionSentBottomSheet extends StatelessWidget {
154 return ClipRRect(
155 borderRadius: const BorderRadius.vertical(top: Radius.circular(30)),
156 child: Material(
160 - color: Theme
161 - .of(context)
162 - .colorScheme
163 - .surface,
157 + color: Theme.of(context).colorScheme.surface,
158 child: ConstrainedBox(
159 constraints: BoxConstraints(maxHeight: maxHeight),
160 child: SingleChildScrollView(
@@ -210,17 +204,14 @@ class _StandardTile extends StatelessWidget {
204 padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
205 decoration: BoxDecoration(
206 borderRadius: BorderRadius.circular(10),
213 - color: Theme
214 - .of(context)
215 - .colorScheme
216 - .surfaceContainerLowest
217 - .withAlpha(80)),
207 + color: Theme.of(context).colorScheme.surfaceContainerLowest.withAlpha(80)),
208 child: Row(
209 mainAxisAlignment: MainAxisAlignment.spaceBetween,
210 children: [
211 Expanded(
212 child: Row(
223 - mainAxisAlignment: copyButton ? MainAxisAlignment.spaceBetween : MainAxisAlignment.start,
213 + mainAxisAlignment:
214 + copyButton ? MainAxisAlignment.spaceBetween : MainAxisAlignment.start,
215 children: [
216 if (imagePath != null)
217 Padding(
lib/src/widgets/bottom_sheet/confirm_sending_bottom_sheet_widget.dart
+2 -1
@@ -168,7 +168,8 @@ class ConfirmSendingBottomSheet extends BaseBottomSheet {
168 final batchContactTitle =
169 '${index + 1}/${outputs.length} - ${contactName.isEmpty ? 'Address' : contactName}';
170 final _address = item.isParsedAddress ? item.extractedAddress : item.address;
171 - final _amount = '${item.cryptoAmount.sanitized()} ${amountParsingProxy?.getCryptoSymbol(currency) ?? currency.title}';
171 + final _amount =
172 + '${item.cryptoAmount.sanitized()} ${amountParsingProxy?.getCryptoSymbol(currency) ?? currency.title}';
173 return isBatchSending || (contactName.isNotEmpty && !isCakePayName)
174 ? ExpansionAddressTile(
175 contactType: isOpenCryptoPay ? 'Open CryptoPay' : S.of(context).contact,
lib/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart
+3 -1
@@ -100,7 +100,9 @@ class InfoBottomSheet extends BaseBottomSheet {
100 )
101 else
102 Container(),
103 - SizedBox(height: 24,),
103 + SizedBox(
104 + height: 24,
105 + ),
106 if (content != null)
107 Expanded(
108 flex: 2,
lib/src/widgets/bottom_sheet/info_steps_bottom_sheet_widget.dart
+11 -11
@@ -34,7 +34,7 @@ class InfoStepsBottomSheet extends BaseBottomSheet {
34 ),
35 child: SingleChildScrollView(
36 child: Column(
37 - children: [
37 + children: [
38 Padding(
39 padding: const EdgeInsets.symmetric(horizontal: 28.0),
40 child: Column(
@@ -96,18 +96,18 @@ class InfoStepsBottomSheet extends BaseBottomSheet {
96 ))
97 .toList(),
98 ),
99 - ),
100 - Padding(
101 - padding: const EdgeInsets.all(16),
102 - child: PrimaryButton(
103 - text: S.of(context).close,
104 - color: context.currentTheme.colorScheme.primary,
99 + ),
100 + Padding(
101 + padding: const EdgeInsets.all(16),
102 + child: PrimaryButton(
103 + text: S.of(context).close,
104 + color: context.currentTheme.colorScheme.primary,
105 textColor: context.currentTheme.colorScheme.onPrimary,
106 onPressed: () => Navigator.of(context).pop(),
107 - ),
108 - )
109 - ],
110 - ),
107 + ),
108 + )
109 + ],
110 + ),
111 ),
112 ),
113 );
lib/src/widgets/bottom_sheet/payment_confirmation_bottom_sheet.dart
+1 -2
@@ -139,8 +139,7 @@ class _PaymentConfirmationContent extends StatelessWidget {
139 clipBehavior: Clip.none,
140 children: [
141 Image.asset(
142 - paymentFlowResult.addressDetectionResult?.detectedCurrency?.iconPath ??
143 - '',
142 + paymentFlowResult.addressDetectionResult?.detectedCurrency?.iconPath ?? '',
143 width: 70,
144 height: 70,
145 errorBuilder: (context, error, stackTrace) => Icon(
lib/src/widgets/bottom_sheet/swap_confirmation_bottom_sheet.dart
+2 -1
@@ -288,7 +288,8 @@ class SwapConfirmationContentState extends State<SwapConfirmationContent> {
288 SwapConfirmationTextfield(
289 key: ValueKey('swap_confirmation_bottomsheet_address_textfield_key'),
290 isAddress: true,
291 - walletType: cryptoCurrencyOrTokenToWalletType(widget.exchangeViewModel.receiveCurrency),
291 + walletType:
292 + cryptoCurrencyOrTokenToWalletType(widget.exchangeViewModel.receiveCurrency),
293 hintText: 'Destination Address',
294 focusNode: _addressFocus,
295 controller: _addressController,
lib/src/widgets/bottom_sheet/swap_details_bottom_sheet.dart
+5 -6
@@ -112,7 +112,7 @@ class _SwapDetailsBottomSheetState extends State<SwapDetailsBottomSheet> {
112 buttonAction: () {
113 _showingFailureDialog = false;
114 Navigator.of(popupContext).pop();
115 - if(mounted) {
115 + if (mounted) {
116 Navigator.of(context, rootNavigator: true).pop();
117 }
118 },
@@ -318,15 +318,13 @@ class _SwapDetailsContent extends StatelessWidget {
318 children: [
319 _SwapDetailsTile(
320 label: 'You Send',
321 - value:
322 - '${trade.amount} ${trade.from?.title ?? ''}',
321 + value: '${trade.amount} ${trade.from?.title ?? ''}',
322 valueFiatFormatted: exchangeTradeViewModel.sendAmountFiatFormatted,
323 ),
324 const SizedBox(height: 8),
325 _SwapDetailsTile(
326 label: 'You Get',
328 - value:
329 - '${trade.receiveAmount ?? '0'} ${trade.to?.title ?? ''}',
327 + value: '${trade.receiveAmount ?? '0'} ${trade.to?.title ?? ''}',
328 valueFiatFormatted: exchangeTradeViewModel
329 .getReceiveAmountFiatFormatted(trade.receiveAmount ?? '0.0'),
330 ),
@@ -351,7 +349,8 @@ class _SwapDetailsContent extends StatelessWidget {
349 const SizedBox(height: 4),
350 AddressFormatter.buildSegmentedAddress(
351 address: trade.payoutAddress ?? '',
354 - walletType: trade.to != null ? cryptoCurrencyOrTokenToWalletType(trade.to!) : null,
352 + walletType:
353 + trade.to != null ? cryptoCurrencyOrTokenToWalletType(trade.to!) : null,
354 evenTextStyle: Theme.of(context)
355 .textTheme
356 .bodyMedium!
lib/src/widgets/bottom_sheet/token_selection_bottom_sheet.dart
+8 -5
@@ -78,7 +78,8 @@ class _TokenSelectionContentState extends State<_TokenSelectionContent> {
78 void initState() {
79 super.initState();
80 final baseNetwork = widget.fixedNetwork ?? WalletType.ethereum;
81 - selectedNetwork = _resolveGenericETHDetectionResultToSpecificChain(baseNetwork, widget.paymentRequest.scheme.isNotEmpty);
81 + selectedNetwork = _resolveGenericETHDetectionResultToSpecificChain(
82 + baseNetwork, widget.paymentRequest.scheme.isNotEmpty);
83 _autoSelectToken();
84 }
85
@@ -101,9 +102,10 @@ class _TokenSelectionContentState extends State<_TokenSelectionContent> {
102 return null;
103 }
104
104 - WalletType _resolveGenericETHDetectionResultToSpecificChain(WalletType network, bool hasURIScheme) {
105 - if(hasURIScheme || network != WalletType.ethereum) return network;
106 -
105 + WalletType _resolveGenericETHDetectionResultToSpecificChain(
106 + WalletType network, bool hasURIScheme) {
107 + if (hasURIScheme || network != WalletType.ethereum) return network;
108 +
109 final current = widget.paymentViewModel.currentWalletType;
110 if (isEVMCompatibleChain(current)) return current;
111 return network;
@@ -113,7 +115,8 @@ class _TokenSelectionContentState extends State<_TokenSelectionContent> {
115 final initialNetwork = selectedNetwork;
116 if (initialNetwork == null || !mounted) return;
117
116 - final network = _resolveGenericETHDetectionResultToSpecificChain(initialNetwork, widget.paymentRequest.scheme.isNotEmpty);
118 + final network = _resolveGenericETHDetectionResultToSpecificChain(
119 + initialNetwork, widget.paymentRequest.scheme.isNotEmpty);
120
121 setState(() {
122 selectedNetwork = network;
lib/src/widgets/check_box_picker.dart
+5 -6
@@ -40,12 +40,11 @@ class CheckBoxPickerState extends State<CheckBoxPicker> {
40 widget.title,
41 textAlign: TextAlign.center,
42 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
43 - fontSize: 18,
44 -
45 - fontWeight: FontWeight.bold,
46 - decoration: TextDecoration.none,
47 - color: Theme.of(context).colorScheme.onSurface,
48 - ),
43 + fontSize: 18,
44 + fontWeight: FontWeight.bold,
45 + decoration: TextDecoration.none,
46 + color: Theme.of(context).colorScheme.onSurface,
47 + ),
48 ),
49 ),
50 Padding(
lib/src/widgets/checkbox_widget.dart
+1
@@ -1,4 +1,5 @@
1 import 'package:flutter/material.dart';
2 +
3 class CheckboxWidget extends StatefulWidget {
4 CheckboxWidget({required this.value, required this.caption, required this.onChanged});
5
lib/src/widgets/evm_switcher.dart
+1 -2
@@ -83,8 +83,7 @@ class _EvmSwitcherState extends State<EvmSwitcher> {
83 .toList(growable: false);
84 }
85
86 - bool _hiddenSetsEqual(Set<int> a, Set<int> b) =>
87 - a.length == b.length && a.containsAll(b);
86 + bool _hiddenSetsEqual(Set<int> a, Set<int> b) => a.length == b.length && a.containsAll(b);
87
88 int get _selectedIndex {
89 if (widget.currentChain == null) return -1;
lib/src/widgets/haven_wallet_removal_popup.dart
+9 -11
@@ -36,12 +36,11 @@ class HavenWalletRemovalPopup extends StatelessWidget {
36 alignment: Alignment.bottomCenter,
37 child: DefaultTextStyle(
38 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
39 - decoration: TextDecoration.none,
40 - fontSize: 24.0,
41 - fontWeight: FontWeight.bold,
42 -
43 - color: Theme.of(context).colorScheme.onSurfaceVariant,
44 - ),
39 + decoration: TextDecoration.none,
40 + fontSize: 24.0,
41 + fontWeight: FontWeight.bold,
42 + color: Theme.of(context).colorScheme.onSurfaceVariant,
43 + ),
44 child: Text("Emergency Notice"),
45 ),
46 ),
@@ -61,11 +60,10 @@ class HavenWalletRemovalPopup extends StatelessWidget {
60 child: Text(
61 "It looks like you have Haven wallets in your list. Haven is getting removed in next release of Cake Wallet, and you currently have Haven in the following wallets:\n\n[${affectedWalletNames.join(", ")}]\n\nPlease move your funds to other wallet, as you will lose access to your Haven funds in next update.\n\nFor assistance, please use the in-app support or email support@cakewallet.com",
62 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
64 - decoration: TextDecoration.none,
65 - fontSize: 16.0,
66 -
67 - color: Theme.of(context).colorScheme.onSurfaceVariant,
68 - ),
63 + decoration: TextDecoration.none,
64 + fontSize: 16.0,
65 + color: Theme.of(context).colorScheme.onSurfaceVariant,
66 + ),
67 ),
68 )
69 ],
lib/src/widgets/index.dart
+1
@@ -0,0 +1 @@
1 +
lib/src/widgets/new_list_row/list_Item_style_wrapper.dart
+21 -19
@@ -45,26 +45,28 @@ class ListItemStyleWrapper extends StatelessWidget {
45 bottom: Radius.circular(isLastInSection ? 18 : 0),
46 );
47
48 - return ClipRSuperellipse(
49 - borderRadius: radius,
50 - child: Column(
51 - children: [
52 - Container(
53 - height: height,
54 - decoration: ShapeDecoration(
55 - shape: RoundedSuperellipseBorder(
56 - borderRadius: radius,
57 - ),
58 - color: backgroundColor ?? theme.colorScheme.surfaceContainer,
48 + return ClipRSuperellipse(
49 + borderRadius: radius,
50 + child: Column(
51 + children: [
52 + Container(
53 + height: height,
54 + decoration: ShapeDecoration(
55 + shape: RoundedSuperellipseBorder(
56 + borderRadius: radius,
57 ),
60 - child: Material(
61 - color: Colors.transparent,
62 - child: InkWell(
63 - onTap: onTap,
64 - child: Padding(
65 - padding: EdgeInsets.symmetric(horizontal: 12, vertical: height == null ? 11 : 0),
66 - child: builder(context, textStyle, labelStyle))))),
67 - if(iconPath != null && isLastInSection == false) Container(
58 + color: backgroundColor ?? theme.colorScheme.surfaceContainer,
59 + ),
60 + child: Material(
61 + color: Colors.transparent,
62 + child: InkWell(
63 + onTap: onTap,
64 + child: Padding(
65 + padding: EdgeInsets.symmetric(
66 + horizontal: 12, vertical: height == null ? 11 : 0),
67 + child: builder(context, textStyle, labelStyle))))),
68 + if (iconPath != null && isLastInSection == false)
69 + Container(
70 color: theme.colorScheme.surfaceContainer,
71 child: Padding(
72 padding: const EdgeInsets.only(left: 50, right: 13),
lib/src/widgets/new_list_row/list_item_checkbox_widget.dart
+34 -30
@@ -14,7 +14,10 @@ class ListItemCheckboxWidget extends StatefulWidget {
14 this.subtitleColor,
15 this.onTap,
16 this.isFirstInSection = false,
17 - this.isLastInSection = false, this.subtitle, this.iconPath, this.showArrow = false,
17 + this.isLastInSection = false,
18 + this.subtitle,
19 + this.iconPath,
20 + this.showArrow = false,
21 });
22
23 final String keyValue;
@@ -34,15 +37,14 @@ class ListItemCheckboxWidget extends StatefulWidget {
37 }
38
39 class _ListItemCheckboxWidgetState extends State<ListItemCheckboxWidget> {
37 -
38 -
40 @override
41 Widget build(BuildContext context) {
42 return ListItemStyleWrapper(
43 iconPath: widget.iconPath,
43 - onTap: widget.onTap ?? () {
44 - widget.onChanged(!widget.value);
45 - },
44 + onTap: widget.onTap ??
45 + () {
46 + widget.onChanged(!widget.value);
47 + },
48 isFirstInSection: widget.isFirstInSection,
49 height: widget.subtitle != null ? 64 : 50,
50 isLastInSection: widget.isLastInSection,
@@ -56,7 +58,7 @@ class _ListItemCheckboxWidgetState extends State<ListItemCheckboxWidget> {
58 children: [
59 if (widget.iconPath != null)
60 widget.iconPath!.toLowerCase().endsWith("svg")
59 - ? CakeImageWidget(imageUrl:widget.iconPath!, height: 26, width: 26)
61 + ? CakeImageWidget(imageUrl: widget.iconPath!, height: 26, width: 26)
62 : Image.asset(
63 widget.iconPath!,
64 width: 26,
@@ -64,29 +66,31 @@ class _ListItemCheckboxWidgetState extends State<ListItemCheckboxWidget> {
66 ),
67 Expanded(
68 child: Column(
67 - mainAxisSize: MainAxisSize.max,
68 - crossAxisAlignment: CrossAxisAlignment.start,
69 - mainAxisAlignment: MainAxisAlignment.center,
70 - children: [
71 - Row(
72 - children: [
73 - Flexible(child: Text(widget.label)),
74 - if (widget.showArrow)
75 - Icon(
76 - Icons.chevron_right,
77 - size: 18,
78 - color: Theme.of(context).colorScheme.onSurfaceVariant,
79 - )
80 - ],
81 - ),
82 - if (widget.subtitle != null)
83 - Text(
84 - widget.subtitle!,
85 - style: TextStyle(
86 - fontSize: 12, color: widget.subtitleColor ?? Theme.of(context).colorScheme.onSurfaceVariant),
87 - )
88 - ],
89 - ),
69 + mainAxisSize: MainAxisSize.max,
70 + crossAxisAlignment: CrossAxisAlignment.start,
71 + mainAxisAlignment: MainAxisAlignment.center,
72 + children: [
73 + Row(
74 + children: [
75 + Flexible(child: Text(widget.label)),
76 + if (widget.showArrow)
77 + Icon(
78 + Icons.chevron_right,
79 + size: 18,
80 + color: Theme.of(context).colorScheme.onSurfaceVariant,
81 + )
82 + ],
83 + ),
84 + if (widget.subtitle != null)
85 + Text(
86 + widget.subtitle!,
87 + style: TextStyle(
88 + fontSize: 12,
89 + color: widget.subtitleColor ??
90 + Theme.of(context).colorScheme.onSurfaceVariant),
91 + )
92 + ],
93 + ),
94 ),
95 ],
96 ),
lib/src/widgets/new_list_row/list_item_regular_row_widget.dart
+1 -1
@@ -85,7 +85,7 @@ class ListItemRegularRowWidget extends StatelessWidget {
85
86 final imageWidget = badgeIconPath != null
87 ? Stack(
88 - clipBehavior: Clip.none,
88 + clipBehavior: Clip.none,
89 children: [
90 leadingIcon!,
91 Positioned(
lib/src/widgets/new_list_row/list_item_selector_widget.dart
+7 -6
@@ -12,7 +12,8 @@ class ListItemSelectorWidget extends StatelessWidget {
12 required this.selectedIndex,
13 required this.onChanged,
14 this.isFirstInSection = false,
15 - this.isLastInSection = false, this.onTap,
15 + this.isLastInSection = false,
16 + this.onTap,
17 });
18
19 final String keyValue;
@@ -45,16 +46,16 @@ class ListItemSelectorWidget extends StatelessWidget {
46 options[selectedIndex],
47 style: labelStyle,
48 ),
48 - CakeImageWidget(imageUrl:
49 - "assets/new-ui/chooser.svg",
49 + CakeImageWidget(
50 + imageUrl: "assets/new-ui/chooser.svg",
51 colorFilter:
51 - ColorFilter.mode(theme.colorScheme.onSurfaceVariant, BlendMode.srcIn),
52 + ColorFilter.mode(theme.colorScheme.onSurfaceVariant, BlendMode.srcIn),
53 ),
54 ],
55 ),
56 ),
57 ],
57 - );
58 + );
59 });
60 }
60 -}
\ No newline at end of file
61 +}
lib/src/widgets/new_list_row/list_item_text_field_widget.dart
+2 -3
@@ -26,8 +26,7 @@ class ListItemTextFieldWidget extends StatefulWidget {
26 final bool isLastInSection;
27
28 @override
29 - State<ListItemTextFieldWidget> createState() =>
30 - _ListItemTextFieldWidgetState();
29 + State<ListItemTextFieldWidget> createState() => _ListItemTextFieldWidgetState();
30 }
31
32 class _ListItemTextFieldWidgetState extends State<ListItemTextFieldWidget> {
@@ -36,7 +35,7 @@ class _ListItemTextFieldWidgetState extends State<ListItemTextFieldWidget> {
35 return ListItemStyleWrapper(
36 isFirstInSection: widget.isFirstInSection,
37 isLastInSection: widget.isLastInSection,
39 - height:50,
38 + height: 50,
39 builder: (context, textStyle, labelStyle) {
40 return Row(
41 children: [
lib/src/widgets/new_list_row/list_item_toggle_widget.dart
+1 -2
@@ -27,7 +27,6 @@ class ListItemToggleWidget extends StatefulWidget {
27 }
28
29 class _ListItemToggleWidgetState extends State<ListItemToggleWidget> {
30 -
30 @override
31 void initState() {
32 super.initState();
@@ -52,7 +51,7 @@ class _ListItemToggleWidgetState extends State<ListItemToggleWidget> {
51 Flexible(
52 child: Text(widget.label, style: textStyle, softWrap: true),
53 ),
55 - if(widget.leadingEndWidget != null) widget.leadingEndWidget!
54 + if (widget.leadingEndWidget != null) widget.leadingEndWidget!
55 ],
56 ),
57 ),
lib/src/widgets/new_list_row/new_list_section.dart
+8 -9
@@ -14,15 +14,14 @@ import 'package:cake_wallet/src/widgets/new_list_row/list_item_toggle_widget.dar
14 import 'package:flutter/material.dart';
15
16 class NewListSections extends StatelessWidget {
17 - const NewListSections({
18 - super.key,
19 - required this.sections,
20 - this.controllers = const {},
21 - this.tapHandlers = const {},
22 - this.getCheckboxValue,
23 - this.updateCheckboxValue,
24 - this.showHeader = false
25 - });
17 + const NewListSections(
18 + {super.key,
19 + required this.sections,
20 + this.controllers = const {},
21 + this.tapHandlers = const {},
22 + this.getCheckboxValue,
23 + this.updateCheckboxValue,
24 + this.showHeader = false});
25
26 final Map<String, List<ListItem>> sections;
27 final Map<String, TextEditingController> controllers;
lib/src/widgets/number_text_fild_widget.dart
+5 -5
@@ -56,7 +56,7 @@ class _NumberTextFieldState extends State<NumberTextField> {
56
57 @override
58 Widget build(BuildContext context) => TextField(
59 - style: Theme.of(context).textTheme.titleMedium!,
59 + style: Theme.of(context).textTheme.titleMedium!,
60 enableInteractiveSelection: false,
61 textAlign: TextAlign.center,
62 textAlignVertical: TextAlignVertical.bottom,
@@ -78,16 +78,16 @@ class _NumberTextFieldState extends State<NumberTextField> {
78 type: MaterialType.transparency,
79 child: InkWell(
80 child: Container(
81 - width: widget.arrowsWidth,
81 + width: widget.arrowsWidth,
82 alignment: Alignment.bottomCenter,
83 - child: Icon(Icons.keyboard_arrow_left_outlined ,size: widget.arrowsWidth)),
83 + child: Icon(Icons.keyboard_arrow_left_outlined, size: widget.arrowsWidth)),
84 onTap: _canGoDown ? () => _update(false) : null)),
85 suffixIcon: Material(
86 type: MaterialType.transparency,
87 child: InkWell(
88 child: Container(
89 - width: widget.arrowsWidth,
90 - alignment: Alignment.bottomCenter,
89 + width: widget.arrowsWidth,
90 + alignment: Alignment.bottomCenter,
91 child: Icon(Icons.keyboard_arrow_right_outlined, size: widget.arrowsWidth)),
92 onTap: _canGoUp ? () => _update(true) : null))),
93 maxLines: 1,
lib/src/widgets/picker.dart
+2 -1
@@ -345,7 +345,8 @@ class _PickerState<Item> extends State<Picker<Item>> {
345 Flexible(
346 child: Text(
347 key: ValueKey('picker_items_index_${itemName}_text_key'),
348 - widget.displayItem?.call(item) ?? (item == CryptoCurrency.btcln ? "BTC (LN)" : item.toString()),
348 + widget.displayItem?.call(item) ??
349 + (item == CryptoCurrency.btcln ? "BTC (LN)" : item.toString()),
350 softWrap: true,
351 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
352 fontWeight: FontWeight.w600,
lib/src/widgets/picker_inner_wrapper_widget.dart
+4 -6
@@ -3,8 +3,7 @@ import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
3 import 'package:cake_wallet/utils/responsive_layout_util.dart';
4
5 class PickerInnerWrapperWidget extends StatelessWidget {
6 - PickerInnerWrapperWidget(
7 - {required this.children, this.title, this.itemsHeight});
6 + PickerInnerWrapperWidget({required this.children, this.title, this.itemsHeight});
7
8 final List<Widget> children;
9 final String? title;
@@ -48,10 +47,9 @@ class PickerInnerWrapperWidget extends StatelessWidget {
47 color: Theme.of(context).colorScheme.surfaceContainerHighest,
48 child: ConstrainedBox(
49 constraints: BoxConstraints(
51 - maxHeight:
52 - itemsHeight != null && itemsHeight! <= containerHeight
53 - ? itemsHeight!
54 - : containerHeight,
50 + maxHeight: itemsHeight != null && itemsHeight! <= containerHeight
51 + ? itemsHeight!
52 + : containerHeight,
53 maxWidth: ResponsiveLayoutUtilBase.kPopupWidth,
54 ),
55 child: Column(
lib/src/widgets/provider_optoin_tile.dart
+2 -2
@@ -105,8 +105,8 @@ class ProviderOptionTile extends StatelessWidget {
105 children: [
106 Row(
107 children: [
108 - ImageUtil.getImageFromPath(imagePath:imagePath,
109 - height: imageHeight, width: imageWidth),
108 + ImageUtil.getImageFromPath(
109 + imagePath: imagePath, height: imageHeight, width: imageWidth),
110 SizedBox(width: 8),
111 Expanded(
112 child: Container(
lib/src/widgets/rounded_checkbox.dart
+14 -14
@@ -9,19 +9,19 @@ class RoundedCheckbox extends StatelessWidget {
9
10 @override
11 Widget build(BuildContext context) {
12 - return value
13 - ? Container(
14 - height: 20.0,
15 - width: 20.0,
16 - decoration: BoxDecoration(
17 - borderRadius: BorderRadius.all(Radius.circular(50.0)),
18 - color: Theme.of(context).colorScheme.primary,
19 - ),
20 - child: Icon(
21 - Icons.check,
22 - color: Theme.of(context).colorScheme.surface,
23 - size: 14.0,
24 - ))
25 - : Offstage();
12 + return value
13 + ? Container(
14 + height: 20.0,
15 + width: 20.0,
16 + decoration: BoxDecoration(
17 + borderRadius: BorderRadius.all(Radius.circular(50.0)),
18 + color: Theme.of(context).colorScheme.primary,
19 + ),
20 + child: Icon(
21 + Icons.check,
22 + color: Theme.of(context).colorScheme.surface,
23 + size: 14.0,
24 + ))
25 + : Offstage();
26 }
27 }
lib/src/widgets/rounded_icon_button.dart
+1 -1
@@ -27,7 +27,7 @@ class RoundedIconButton extends StatelessWidget {
27 onPressed: onPressed,
28 fillColor: fillColor ?? colorScheme.surfaceContainerHighest,
29 elevation: 0,
30 - constraints: BoxConstraints.tightFor(width: width ?? 30, height: height ?? 30),
30 + constraints: BoxConstraints.tightFor(width: width ?? 30, height: height ?? 30),
31 padding: EdgeInsets.zero,
32 materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
33 shape: shape ?? const CircleBorder(),
lib/src/widgets/scrollable_with_bottom_section.dart
+1 -1
@@ -52,4 +52,4 @@ class ScrollableWithBottomSectionState extends State<ScrollableWithBottomSection
52 ],
53 );
54 }
55 -}
\ No newline at end of file
55 +}
lib/src/widgets/seed_widget.dart
+7 -6
@@ -105,11 +105,11 @@ class SeedWidgetState extends State<SeedWidget> {
105 cursorColor: Theme.of(context).colorScheme.primary,
106 backgroundCursorColor: Theme.of(context).colorScheme.primary,
107 validStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
108 - color: Theme.of(context).colorScheme.onSurfaceVariant,
109 - backgroundColor: Colors.transparent,
110 - fontWeight: FontWeight.normal,
111 - fontSize: 16,
112 - ),
108 + color: Theme.of(context).colorScheme.onSurfaceVariant,
109 + backgroundColor: Colors.transparent,
110 + fontWeight: FontWeight.normal,
111 + fontSize: 16,
112 + ),
113 invalidStyle: Theme.of(context).textTheme.bodyMedium!.copyWith(
114 color: Theme.of(context).colorScheme.errorContainer,
115 backgroundColor: Colors.transparent,
@@ -157,7 +157,8 @@ class SeedWidgetState extends State<SeedWidget> {
157 padding: EdgeInsets.all(6),
158 decoration: ShapeDecoration(
159 color: Theme.of(context).colorScheme.surface,
160 - shape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(18)),
160 + shape: RoundedSuperellipseBorder(
161 + borderRadius: BorderRadius.circular(18)),
162 ),
163 child: Image.asset(
164 'assets/images/paste_ios.png',
lib/src/widgets/seedphrase_grid_widget.dart
+2 -6
@@ -9,8 +9,6 @@ class SeedPhraseGridWidget extends StatelessWidget {
9
10 final List<String> list;
11
12 -
13 -
12 @override
13 Widget build(BuildContext context) {
14 int minTiles = 1;
@@ -23,7 +21,6 @@ class SeedPhraseGridWidget extends StatelessWidget {
21 int crossAxisCount =
22 ((screenWidth + spacing - (2 * padding)) / (desiredTileWidth + spacing)).floor();
23
26 -
24 if (crossAxisCount > maxTiles) crossAxisCount = maxTiles;
25 if (crossAxisCount < minTiles) crossAxisCount = minTiles;
26
@@ -44,9 +41,8 @@ class SeedPhraseGridWidget extends StatelessWidget {
41 padding: const EdgeInsets.symmetric(horizontal: 8),
42 alignment: Alignment.center,
43 decoration: BoxDecoration(
47 - borderRadius: BorderRadius.circular(8),
48 - color: Theme.of(context).colorScheme.surfaceContainerHigh
49 - ),
44 + borderRadius: BorderRadius.circular(8),
45 + color: Theme.of(context).colorScheme.surfaceContainerHigh),
46 child: Row(
47 crossAxisAlignment: CrossAxisAlignment.center,
48 children: [
lib/src/widgets/simple_checkbox.dart
+3 -3
@@ -26,9 +26,9 @@ class _SimpleCheckboxState extends State<SimpleCheckbox> {
26 checkColor: Theme.of(context).textTheme.titleLarge!.color,
27 activeColor: Colors.transparent,
28 materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
29 - side: WidgetStateBorderSide.resolveWith((states) => BorderSide(
30 - color: Theme.of(context).textTheme.titleLarge!.color!, width: 1.0)),
29 + side: WidgetStateBorderSide.resolveWith((states) =>
30 + BorderSide(color: Theme.of(context).textTheme.titleLarge!.color!, width: 1.0)),
31 ),
32 );
33 }
34 -}
\ No newline at end of file
34 +}
lib/src/widgets/standard_checkbox.dart
+5 -6
@@ -66,12 +66,11 @@ class StandardCheckbox extends StatelessWidget {
66 caption,
67 softWrap: true,
68 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
69 - fontSize: 16.0,
70 -
71 - fontWeight: FontWeight.normal,
72 - color: captionColor ?? Theme.of(context).colorScheme.onSurface,
73 - decoration: TextDecoration.none,
74 - ),
69 + fontSize: 16.0,
70 + fontWeight: FontWeight.normal,
71 + color: captionColor ?? Theme.of(context).colorScheme.onSurface,
72 + decoration: TextDecoration.none,
73 + ),
74 ),
75 ),
76 )
lib/src/widgets/standard_list.dart
+9 -10
@@ -50,7 +50,6 @@ class StandardListRow extends StatelessWidget {
50 Widget? buildLeading(BuildContext context) => null;
51
52 Widget buildCenter(BuildContext context, {required bool hasLeftOffset}) {
53 -
53 return Expanded(
54 child: Row(
55 mainAxisAlignment: MainAxisAlignment.start,
@@ -84,17 +83,17 @@ class StandardListRow extends StatelessWidget {
83 ),
84 ),
85 )
87 - else
88 - Align(
89 - alignment: Alignment.centerLeft,
90 - child: Text(
91 - title,
92 - style: Theme.of(context).textTheme.bodyMedium?.copyWith(
93 - color: titleColor(context),
94 - fontWeight: isSelected ? FontWeight.w800 : FontWeight.w400,
86 + else
87 + Align(
88 + alignment: Alignment.centerLeft,
89 + child: Text(
90 + title,
91 + style: Theme.of(context).textTheme.bodyMedium?.copyWith(
92 + color: titleColor(context),
93 + fontWeight: isSelected ? FontWeight.w800 : FontWeight.w400,
94 + ),
95 ),
96 ),
97 - ),
97 ],
98 ),
99 )
lib/src/widgets/standard_list_status_row.dart
+3 -3
@@ -47,9 +47,9 @@ class StandardListStatusRow extends StatelessWidget {
47 Text(
48 value,
49 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
50 - fontSize: 16,
51 - fontWeight: FontWeight.w500,
52 - ),
50 + fontSize: 16,
51 + fontWeight: FontWeight.w500,
52 + ),
53 )
54 ],
55 ),
lib/src/widgets/standard_slide_button_widget.dart
+3 -1
@@ -113,7 +113,9 @@ class StandardSlideButtonState extends State<StandardSlideButton> {
113 child: Icon(
114 key: ValueKey('standard_slide_button_widget_slider_icon_key'),
115 Icons.arrow_forward,
116 - color: widget.isDisabled ? Theme.of(context).colorScheme.onSurface.withOpacity(0.2) : Theme.of(context).colorScheme.onSurface,
116 + color: widget.isDisabled
117 + ? Theme.of(context).colorScheme.onSurface.withOpacity(0.2)
118 + : Theme.of(context).colorScheme.onSurface,
119 ),
120 ),
121 ),
lib/src/widgets/validable_annotated_editable_text.dart
+9 -10
@@ -65,7 +65,6 @@ class ValidatableAnnotatedEditableText extends EditableText {
65 backgroundCursorColor: backgroundCursorColor,
66 onChanged: onChanged,
67 onSubmitted: onSubmitted,
68 -
68 toolbarOptions: const ToolbarOptions(
69 copy: true,
70 cut: true,
@@ -120,17 +119,17 @@ class ValidatableAnnotatedEditableTextState extends EditableTextState {
119 annotation = Annotation(
120 range: TextRange(start: 0, end: item.range.start),
121 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
123 - color: Theme.of(context).colorScheme.onSurfaceVariant,
124 - backgroundColor: Colors.transparent,
125 - ),
122 + color: Theme.of(context).colorScheme.onSurfaceVariant,
123 + backgroundColor: Colors.transparent,
124 + ),
125 );
126 } else if (prev.range.end < item.range.start) {
127 annotation = Annotation(
128 range: TextRange(start: prev.range.end, end: item.range.start),
129 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
131 - color: Theme.of(context).colorScheme.onError,
132 - backgroundColor: Colors.transparent,
133 - ),
130 + color: Theme.of(context).colorScheme.onError,
131 + backgroundColor: Colors.transparent,
132 + ),
133 );
134 }
135
@@ -146,9 +145,9 @@ class ValidatableAnnotatedEditableTextState extends EditableTextState {
145 Annotation(
146 range: TextRange(start: result.last.range.end, end: text.length),
147 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
149 - color: Theme.of(context).colorScheme.onSurfaceVariant,
150 - backgroundColor: Colors.transparent,
151 - ),
148 + color: Theme.of(context).colorScheme.onSurfaceVariant,
149 + backgroundColor: Colors.transparent,
150 + ),
151 ),
152 );
153 }
lib/src/widgets/vulnerable_seeds_popup.dart
+9 -12
@@ -36,12 +36,11 @@ class VulnerableSeedsPopup extends StatelessWidget {
36 alignment: Alignment.bottomCenter,
37 child: DefaultTextStyle(
38 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
39 - decoration: TextDecoration.none,
40 - fontSize: 24.0,
41 - fontWeight: FontWeight.bold,
42 -
43 - color: Theme.of(context).colorScheme.onSurface,
44 - ),
39 + decoration: TextDecoration.none,
40 + fontSize: 24.0,
41 + fontWeight: FontWeight.bold,
42 + color: Theme.of(context).colorScheme.onSurface,
43 + ),
44 child: Text("Emergency Notice"),
45 ),
46 ),
@@ -61,12 +60,10 @@ class VulnerableSeedsPopup extends StatelessWidget {
60 child: Text(
61 "Your Bitcoin wallet(s) below use a legacy seed format that is vulnerable, which MAY result in you losing money from these wallet(s) if no action is taken.\nWe recommend that you IMMEDIATELY create wallet(s) in Cake Wallet and immediately transfer the funds to these wallet(s).\nVulnerable wallet name(s):\n\n[${affectedWalletNames.join(", ")}]\n\nFor assistance, please use the in-app support or email support@cakewallet.com",
62 style: Theme.of(context).textTheme.bodyMedium!.copyWith(
64 - decoration: TextDecoration.none,
65 - fontSize: 16.0,
66 -
67 - color: Theme.of(context)
68 - .colorScheme.onSurface,
69 - ),
63 + decoration: TextDecoration.none,
64 + fontSize: 16.0,
65 + color: Theme.of(context).colorScheme.onSurface,
66 + ),
67 ),
68 )
69 ],
lib/store/app_store.dart
-1
@@ -48,7 +48,6 @@ abstract class AppStoreBase with Store {
48
49 SettingsStore settingsStore;
50
51 -
51 ThemeStore themeStore;
52
53 @observable
lib/store/dashboard/order_filter_store.dart
+2 -3
@@ -30,8 +30,7 @@ abstract class OrderFilterStoreBase with Store {
30 required List<OrderListItem> orders,
31 required WalletBase wallet,
32 }) {
33 - final walletOrders =
34 - orders.where((item) => item.order.walletId == wallet.id).toList();
33 + final walletOrders = orders.where((item) => item.order.walletId == wallet.id).toList();
34
35 final cakePayOrders = walletOrders.where((item) {
36 final order = item.order;
@@ -43,4 +42,4 @@ abstract class OrderFilterStoreBase with Store {
42 if (!displayCakePay) return <OrderListItem>[];
43 return cakePayOrders;
44 }
46 -}
\ No newline at end of file
45 +}
lib/store/dashboard/payjoin_transactions_store.dart
+1 -2
@@ -8,8 +8,7 @@ import 'package:mobx/mobx.dart';
8
9 part 'payjoin_transactions_store.g.dart';
10
11 -class PayjoinTransactionsStore = PayjoinTransactionsStoreBase
12 - with _$PayjoinTransactionsStore;
11 +class PayjoinTransactionsStore = PayjoinTransactionsStoreBase with _$PayjoinTransactionsStore;
12
13 abstract class PayjoinTransactionsStoreBase with Store {
14 PayjoinTransactionsStoreBase({
lib/store/dashboard/trade_filter_store.dart
+27 -25
@@ -71,20 +71,20 @@ abstract class TradeFilterStoreBase with Store {
71
72 @computed
73 int get enabledProvidersCount => [
74 - displayChangeNow,
75 - displaySideShift,
76 - displaySimpleSwap,
77 - displayTrocador,
78 - displayExolix,
79 - displayChainflip,
80 - displayThorChain,
81 - displayLetsExchange,
82 - displayStealthEx,
83 - displayXOSwap,
84 - displaySwapTrade,
85 - displaySwapXyz,
86 - displayNearIntents
87 - ].where((item) => item).length;
74 + displayChangeNow,
75 + displaySideShift,
76 + displaySimpleSwap,
77 + displayTrocador,
78 + displayExolix,
79 + displayChainflip,
80 + displayThorChain,
81 + displayLetsExchange,
82 + displayStealthEx,
83 + displayXOSwap,
84 + displaySwapTrade,
85 + displaySwapXyz,
86 + displayNearIntents
87 + ].where((item) => item).length;
88
89 @computed
90 bool get displayAllTrades =>
@@ -189,12 +189,12 @@ abstract class TradeFilterStoreBase with Store {
189 }
190
191 List<TradeListItem> filtered({required List<TradeListItem> trades, required WalletBase wallet}) {
192 - final _trades = trades
193 - .where((item) {
194 - final isSameChain = item.trade.chainId != null ? item.trade.chainId == wallet.chainId : true; // returning default as true here so it falls back to the default checks if there's no chainId
195 - return item.trade.walletId == wallet.id && isTradeInAccount(item, wallet) && isSameChain;
196 - })
197 - .toList();
192 + final _trades = trades.where((item) {
193 + final isSameChain = item.trade.chainId != null
194 + ? item.trade.chainId == wallet.chainId
195 + : true; // returning default as true here so it falls back to the default checks if there's no chainId
196 + return item.trade.walletId == wallet.id && isTradeInAccount(item, wallet) && isSameChain;
197 + }).toList();
198 final needToFilter = !displayAllTrades;
199
200 return needToFilter
@@ -217,12 +217,14 @@ abstract class TradeFilterStoreBase with Store {
217 item.trade.provider == ExchangeProviderDescription.thorChain) ||
218 (displayLetsExchange &&
219 item.trade.provider == ExchangeProviderDescription.letsExchange) ||
220 - (displayStealthEx && item.trade.provider == ExchangeProviderDescription.stealthEx) ||
220 + (displayStealthEx &&
221 + item.trade.provider == ExchangeProviderDescription.stealthEx) ||
222 (displayXOSwap && item.trade.provider == ExchangeProviderDescription.xoSwap) ||
222 - (displaySwapTrade && item.trade.provider == ExchangeProviderDescription.swapTrade) ||
223 - (displaySwapXyz &&
224 - item.trade.provider == ExchangeProviderDescription.swapsXyz) ||
225 - (displayNearIntents && item.trade.provider == ExchangeProviderDescription.nearIntents))
223 + (displaySwapTrade &&
224 + item.trade.provider == ExchangeProviderDescription.swapTrade) ||
225 + (displaySwapXyz && item.trade.provider == ExchangeProviderDescription.swapsXyz) ||
226 + (displayNearIntents &&
227 + item.trade.provider == ExchangeProviderDescription.nearIntents))
228 .toList()
229 : _trades;
230 }
lib/store/node_list_store.dart
+1
@@ -0,0 +1 @@
1 +
lib/store/seed_settings_store.dart
-1
@@ -5,7 +5,6 @@ part 'seed_settings_store.g.dart';
5 class SeedSettingsStore = SeedSettingsStoreBase with _$SeedSettingsStore;
6
7 abstract class SeedSettingsStoreBase with Store {
8 -
8 @observable
9 String? passphrase;
10 }
lib/store/settings_store.dart
+72 -88
@@ -247,7 +247,6 @@ abstract class SettingsStoreBase with Store {
247 priority[WalletType.ethereum] = initialEthereumTransactionPriority;
248 }
249
250 -
250 if (initialPolygonTransactionPriority != null) {
251 priority[WalletType.polygon] = initialPolygonTransactionPriority;
252 }
@@ -302,7 +301,8 @@ abstract class SettingsStoreBase with Store {
301 reaction((_) => shouldShowRepWarning,
302 (bool val) => sharedPreferences.setBool(PreferencesKey.shouldShowRepWarning, val));
303
305 - reaction((_)=>mwebAdDismissed, (val)=>sharedPreferences.setBool(PreferencesKey.mwebAdDismissed, val));
304 + reaction((_) => mwebAdDismissed,
305 + (val) => sharedPreferences.setBool(PreferencesKey.mwebAdDismissed, val));
306
307 priority.observe((change) {
308 final String? key;
@@ -570,42 +570,40 @@ abstract class SettingsStoreBase with Store {
570
571 reaction(
572 (_) => lookupsZcashNames,
573 - (bool looksUpZcashNames) => _sharedPreferences.setBool(
574 - PreferencesKey.lookupsZcashNames, looksUpZcashNames));
573 + (bool looksUpZcashNames) =>
574 + _sharedPreferences.setBool(PreferencesKey.lookupsZcashNames, looksUpZcashNames));
575
576 reaction(
577 - (_) => lookupsZcashAddress,
578 - (bool lookupsZcashAddress) => _sharedPreferences.setBool(
579 - PreferencesKey.lookupsZcashAddress, lookupsZcashAddress));
577 + (_) => lookupsZcashAddress,
578 + (bool lookupsZcashAddress) =>
579 + _sharedPreferences.setBool(PreferencesKey.lookupsZcashAddress, lookupsZcashAddress));
580
581 reaction(
582 (_) => lookupsWellKnown,
583 (bool looksUpWellKnown) =>
584 _sharedPreferences.setBool(PreferencesKey.lookupsWellKnown, looksUpWellKnown));
585
586 - reaction(
587 - (_) => lookupsFio,
588 - (bool lookupsFio) =>
589 - _sharedPreferences.setBool(PreferencesKey.lookupsFio, lookupsFio));
586 + reaction((_) => lookupsFio,
587 + (bool lookupsFio) => _sharedPreferences.setBool(PreferencesKey.lookupsFio, lookupsFio));
588
589 reaction(
592 - (_) => lookupsNostr,
593 - (bool lookupsNostr) =>
590 + (_) => lookupsNostr,
591 + (bool lookupsNostr) =>
592 _sharedPreferences.setBool(PreferencesKey.lookupsNostr, lookupsNostr));
593
594 reaction(
597 - (_) => lookupsThorChain,
598 - (bool lookupsThorChain) =>
595 + (_) => lookupsThorChain,
596 + (bool lookupsThorChain) =>
597 _sharedPreferences.setBool(PreferencesKey.lookupsThorChain, lookupsThorChain));
598
599 reaction(
602 - (_) => lookupsBip353,
603 - (bool lookupsBip353) =>
600 + (_) => lookupsBip353,
601 + (bool lookupsBip353) =>
602 _sharedPreferences.setBool(PreferencesKey.lookupsBip353, lookupsBip353));
603
604 reaction(
607 - (_) => lookupsLNUrl,
608 - (bool lookupsLNUrl) =>
605 + (_) => lookupsLNUrl,
606 + (bool lookupsLNUrl) =>
607 _sharedPreferences.setBool(PreferencesKey.lookupsLNUrl, lookupsLNUrl));
608
609 reaction((_) => usePayjoin,
@@ -726,8 +724,8 @@ abstract class SettingsStoreBase with Store {
724
725 reaction(
726 (_) => showZcashMissingFundsCard,
729 - (bool showZcashMissingFundsCard) =>
730 - _sharedPreferences.setBool(PreferencesKey.showZcashMissingFundsCard, showZcashMissingFundsCard));
727 + (bool showZcashMissingFundsCard) => _sharedPreferences.setBool(
728 + PreferencesKey.showZcashMissingFundsCard, showZcashMissingFundsCard));
729
730 reaction((_) => mwebEnabled,
731 (bool mwebEnabled) => _sharedPreferences.setBool(PreferencesKey.mwebEnabled, mwebEnabled));
@@ -765,8 +763,8 @@ abstract class SettingsStoreBase with Store {
763
764 reaction(
765 (_) => balanceHideCounter,
768 - (int balanceHideCounter) => _sharedPreferences.setInt(PreferencesKey.balanceHideCounter, balanceHideCounter)
769 - );
766 + (int balanceHideCounter) =>
767 + _sharedPreferences.setInt(PreferencesKey.balanceHideCounter, balanceHideCounter));
768
769 this.nodes.observe((change) {
770 if (change.newValue != null && change.key != null) {
@@ -1147,7 +1145,8 @@ abstract class SettingsStoreBase with Store {
1145 return priority[walletType];
1146 }
1147
1150 - void setPriority(WalletType walletType, TransactionPriority priority, {int? chainId}) => this.priority[walletType] = priority;
1148 + void setPriority(WalletType walletType, TransactionPriority priority, {int? chainId}) =>
1149 + this.priority[walletType] = priority;
1150
1151 bool isBitcoinBuyEnabled;
1152
@@ -1158,8 +1157,7 @@ abstract class SettingsStoreBase with Store {
1157 _sharedPreferences.setBool(PreferencesKey.shouldShowReceiveWarning, value);
1158
1159 static Future<SettingsStore> load(
1161 - {
1162 - required bool isBitcoinBuyEnabled,
1160 + {required bool isBitcoinBuyEnabled,
1161 FiatCurrency initialFiatCurrency = FiatCurrency.usd,
1162 BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance}) async {
1163 final sharedPreferences = await getIt.getAsync<SharedPreferences>();
@@ -1281,10 +1279,14 @@ abstract class SettingsStoreBase with Store {
1279 sharedPreferences.getBool(PreferencesKey.shouldShowMarketPlaceInDashboard) ?? true;
1280 final showAddressBookPopupEnabled =
1281 sharedPreferences.getBool(PreferencesKey.showAddressBookPopupEnabled) ?? true;
1284 - final forceDecentralizedExchanges = await sharedPreferences.getBool(PreferencesKey.forceDecentralizedExchanges) ?? false;
1285 - final decentralizedExchangesPromptDismissed = await sharedPreferences.getBool(PreferencesKey.decentralizedExchangesPromptDismissed) ?? false;
1282 + final forceDecentralizedExchanges =
1283 + await sharedPreferences.getBool(PreferencesKey.forceDecentralizedExchanges) ?? false;
1284 + final decentralizedExchangesPromptDismissed =
1285 + await sharedPreferences.getBool(PreferencesKey.decentralizedExchangesPromptDismissed) ??
1286 + false;
1287 final syncStatusDisplayMode = SyncStatusDisplayModeExtension.fromString(
1287 - sharedPreferences.getString(PreferencesKey.syncStatusDisplayMode) ?? SyncStatusDisplayMode.blocksRemaining.name);
1288 + sharedPreferences.getString(PreferencesKey.syncStatusDisplayMode) ??
1289 + SyncStatusDisplayMode.blocksRemaining.name);
1290 final exchangeStatus = ExchangeApiMode.deserialize(
1291 raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ??
1292 ExchangeApiMode.enabled.raw);
@@ -1323,7 +1325,8 @@ abstract class SettingsStoreBase with Store {
1325 final lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true;
1326 final lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true;
1327 final lookupsZcashNames = sharedPreferences.getBool(PreferencesKey.lookupsZcashNames) ?? true;
1326 - final lookupsZcashAddress = sharedPreferences.getBool(PreferencesKey.lookupsZcashAddress) ?? true;
1328 + final lookupsZcashAddress =
1329 + sharedPreferences.getBool(PreferencesKey.lookupsZcashAddress) ?? true;
1330 final lookupsWellKnown = sharedPreferences.getBool(PreferencesKey.lookupsWellKnown) ?? true;
1331 final lookupsFio = sharedPreferences.getBool(PreferencesKey.lookupsFio) ?? true;
1332 final lookupsNostr = sharedPreferences.getBool(PreferencesKey.lookupsNostr) ?? true;
@@ -1337,7 +1340,8 @@ abstract class SettingsStoreBase with Store {
1340 sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true;
1341 final mwebAlwaysScan = sharedPreferences.getBool(PreferencesKey.mwebAlwaysScan) ?? false;
1342 final mwebCardDisplay = sharedPreferences.getBool(PreferencesKey.mwebCardDisplay) ?? true;
1340 - final showZcashMissingFundsCard = sharedPreferences.getBool(PreferencesKey.showZcashMissingFundsCard) ?? true;
1343 + final showZcashMissingFundsCard =
1344 + sharedPreferences.getBool(PreferencesKey.showZcashMissingFundsCard) ?? true;
1345 final mwebEnabled = sharedPreferences.getBool(PreferencesKey.mwebEnabled) ?? false;
1346 final hasEnabledMwebBefore =
1347 sharedPreferences.getBool(PreferencesKey.hasEnabledMwebBefore) ?? false;
@@ -1376,7 +1380,6 @@ abstract class SettingsStoreBase with Store {
1380 final decredNodeId = sharedPreferences.getInt(PreferencesKey.currentDecredNodeIdKey);
1381 final dogecoinNodeId = sharedPreferences.getInt(PreferencesKey.currentDogecoinNodeIdKey);
1382
1379 -
1383 final nodeSource = await Node.getAll();
1384 final powNodeSource = await Node.getAllPow();
1385
@@ -1389,52 +1392,36 @@ abstract class SettingsStoreBase with Store {
1392 final litecoinElectrumServer =
1393 nodeSource.firstWhereOrNull((e) => e.id == litecoinElectrumServerId) ??
1394 nodeSource.firstWhereOrNull((e) => e.uriRaw == cakeWalletLitecoinElectrumUri);
1392 - final ethereumNode =
1393 - nodeSource.firstWhereOrNull((e) => e.id == ethereumNodeId) ??
1394 - nodeSource.firstWhereOrNull((e) => e.uriRaw == ethereumDefaultNodeUri);
1395 - final polygonNode =
1396 - nodeSource.firstWhereOrNull((e) => e.id == polygonNodeId) ??
1397 - nodeSource.firstWhereOrNull((e) => e.uriRaw == polygonDefaultNodeUri);
1398 - final baseNode =
1399 - nodeSource.firstWhereOrNull((e) => e.id == baseNodeId) ??
1400 - nodeSource.firstWhereOrNull((e) => e.uriRaw == baseDefaultNodeUri);
1401 - final arbitrumNode =
1402 - nodeSource.firstWhereOrNull((e) => e.id == arbitrumNodeId) ??
1403 - nodeSource.firstWhereOrNull((e) => e.uriRaw == arbitrumDefaultNodeUri);
1395 + final ethereumNode = nodeSource.firstWhereOrNull((e) => e.id == ethereumNodeId) ??
1396 + nodeSource.firstWhereOrNull((e) => e.uriRaw == ethereumDefaultNodeUri);
1397 + final polygonNode = nodeSource.firstWhereOrNull((e) => e.id == polygonNodeId) ??
1398 + nodeSource.firstWhereOrNull((e) => e.uriRaw == polygonDefaultNodeUri);
1399 + final baseNode = nodeSource.firstWhereOrNull((e) => e.id == baseNodeId) ??
1400 + nodeSource.firstWhereOrNull((e) => e.uriRaw == baseDefaultNodeUri);
1401 + final arbitrumNode = nodeSource.firstWhereOrNull((e) => e.id == arbitrumNodeId) ??
1402 + nodeSource.firstWhereOrNull((e) => e.uriRaw == arbitrumDefaultNodeUri);
1403 final bitcoinCashElectrumServer =
1404 nodeSource.firstWhereOrNull((e) => e.id == bitcoinCashElectrumServerId) ??
1406 - nodeSource.firstWhereOrNull(
1407 - (e) => e.uriRaw == cakeWalletBitcoinCashDefaultNodeUri);
1408 - final nanoNode =
1409 - nodeSource.firstWhereOrNull((e) => e.id == nanoNodeId) ??
1410 - nodeSource.firstWhereOrNull((e) => e.uriRaw == nanoDefaultNodeUri);
1411 - final decredNode =
1412 - nodeSource.firstWhereOrNull((e) => e.id == decredNodeId) ??
1413 - nodeSource.firstWhereOrNull((e) => e.uriRaw == decredDefaultUri);
1414 - final nanoPowNode =
1415 - powNodeSource.firstWhereOrNull((e) => e.id == nanoPowNodeId) ??
1416 - powNodeSource.firstWhereOrNull(
1417 - (e) => e.uriRaw == nanoDefaultPowNodeUri);
1418 - final solanaNode =
1419 - nodeSource.firstWhereOrNull((e) => e.id == solanaNodeId) ??
1420 - nodeSource.firstWhereOrNull((e) => e.uriRaw == solanaDefaultNodeUri);
1421 - final tronNode =
1422 - nodeSource.firstWhereOrNull((e) => e.id == tronNodeId) ??
1423 - nodeSource.firstWhereOrNull((e) => e.uriRaw == tronDefaultNodeUri);
1424 - final wowneroNode =
1425 - nodeSource.firstWhereOrNull((e) => e.id == wowneroNodeId) ??
1426 - nodeSource.firstWhereOrNull((e) => e.uriRaw == wowneroDefaultNodeUri);
1427 - final zanoNode =
1428 - nodeSource.firstWhereOrNull((e) => e.id == zanoNodeId) ??
1429 - nodeSource.firstWhereOrNull((e) => e.uriRaw == zanoDefaultNodeUri);
1430 - final dogecoinNode =
1431 - nodeSource.firstWhereOrNull((e) => e.id == dogecoinNodeId) ??
1432 - nodeSource.firstWhereOrNull((e) => e.uriRaw == dogecoinDefaultNodeUri);
1433 - final zcashNode =
1434 - nodeSource.firstWhereOrNull((e) => e.id == zcashNodeId) ??
1405 + nodeSource.firstWhereOrNull((e) => e.uriRaw == cakeWalletBitcoinCashDefaultNodeUri);
1406 + final nanoNode = nodeSource.firstWhereOrNull((e) => e.id == nanoNodeId) ??
1407 + nodeSource.firstWhereOrNull((e) => e.uriRaw == nanoDefaultNodeUri);
1408 + final decredNode = nodeSource.firstWhereOrNull((e) => e.id == decredNodeId) ??
1409 + nodeSource.firstWhereOrNull((e) => e.uriRaw == decredDefaultUri);
1410 + final nanoPowNode = powNodeSource.firstWhereOrNull((e) => e.id == nanoPowNodeId) ??
1411 + powNodeSource.firstWhereOrNull((e) => e.uriRaw == nanoDefaultPowNodeUri);
1412 + final solanaNode = nodeSource.firstWhereOrNull((e) => e.id == solanaNodeId) ??
1413 + nodeSource.firstWhereOrNull((e) => e.uriRaw == solanaDefaultNodeUri);
1414 + final tronNode = nodeSource.firstWhereOrNull((e) => e.id == tronNodeId) ??
1415 + nodeSource.firstWhereOrNull((e) => e.uriRaw == tronDefaultNodeUri);
1416 + final wowneroNode = nodeSource.firstWhereOrNull((e) => e.id == wowneroNodeId) ??
1417 + nodeSource.firstWhereOrNull((e) => e.uriRaw == wowneroDefaultNodeUri);
1418 + final zanoNode = nodeSource.firstWhereOrNull((e) => e.id == zanoNodeId) ??
1419 + nodeSource.firstWhereOrNull((e) => e.uriRaw == zanoDefaultNodeUri);
1420 + final dogecoinNode = nodeSource.firstWhereOrNull((e) => e.id == dogecoinNodeId) ??
1421 + nodeSource.firstWhereOrNull((e) => e.uriRaw == dogecoinDefaultNodeUri);
1422 + final zcashNode = nodeSource.firstWhereOrNull((e) => e.id == zcashNodeId) ??
1423 nodeSource.firstWhereOrNull((e) => e.uriRaw == zcashDefaultNodeUri);
1436 - final bscNode =
1437 - nodeSource.firstWhereOrNull((e) => e.id == bscNodeId) ??
1424 + final bscNode = nodeSource.firstWhereOrNull((e) => e.id == bscNodeId) ??
1425 nodeSource.firstWhereOrNull((e) => e.uriRaw == bscDefaultNodeUri);
1426
1427 final packageInfo = await PackageInfo.fromPlatform();
@@ -1654,7 +1641,8 @@ abstract class SettingsStoreBase with Store {
1641 final mwebAdDismissed =
1642 await sharedPreferences.getBool(PreferencesKey.mwebAdDismissed) ?? false;
1643
1657 - final balanceHideCounter = await sharedPreferences.getInt(PreferencesKey.balanceHideCounter) ?? 0;
1644 + final balanceHideCounter =
1645 + await sharedPreferences.getInt(PreferencesKey.balanceHideCounter) ?? 0;
1646
1647 return SettingsStore(
1648 secureStorage: secureStorage,
@@ -1899,7 +1887,8 @@ abstract class SettingsStoreBase with Store {
1887 sharedPreferences.getBool(PreferencesKey.showAddressBookPopupEnabled) ??
1888 showAddressBookPopupEnabled;
1889 syncStatusDisplayMode = SyncStatusDisplayModeExtension.fromString(
1902 - sharedPreferences.getString(PreferencesKey.syncStatusDisplayMode) ?? SyncStatusDisplayMode.blocksRemaining.name);
1890 + sharedPreferences.getString(PreferencesKey.syncStatusDisplayMode) ??
1891 + SyncStatusDisplayMode.blocksRemaining.name);
1892 exchangeStatus = ExchangeApiMode.deserialize(
1893 raw: sharedPreferences.getInt(PreferencesKey.exchangeStatusKey) ??
1894 ExchangeApiMode.enabled.raw);
@@ -1950,15 +1939,15 @@ abstract class SettingsStoreBase with Store {
1939 sharedPreferences.getBool(PreferencesKey.lookupsUnstoppableDomains) ?? true;
1940 lookupsOpenAlias = sharedPreferences.getBool(PreferencesKey.lookupsOpenAlias) ?? true;
1941 lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true;
1953 - lookupsZcashNames =
1954 - sharedPreferences.getBool(PreferencesKey.lookupsZcashNames) ?? true;
1942 + lookupsZcashNames = sharedPreferences.getBool(PreferencesKey.lookupsZcashNames) ?? true;
1943 lookupsWellKnown = sharedPreferences.getBool(PreferencesKey.lookupsWellKnown) ?? true;
1944 customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1;
1945 silentPaymentsCardDisplay =
1946 sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true;
1947 mwebAlwaysScan = sharedPreferences.getBool(PreferencesKey.mwebAlwaysScan) ?? false;
1948 mwebCardDisplay = sharedPreferences.getBool(PreferencesKey.mwebCardDisplay) ?? true;
1961 - showZcashMissingFundsCard = sharedPreferences.getBool(PreferencesKey.showZcashMissingFundsCard) ?? true;
1949 + showZcashMissingFundsCard =
1950 + sharedPreferences.getBool(PreferencesKey.showZcashMissingFundsCard) ?? true;
1951 mwebEnabled = sharedPreferences.getBool(PreferencesKey.mwebEnabled) ?? false;
1952 hasEnabledMwebBefore = sharedPreferences.getBool(PreferencesKey.hasEnabledMwebBefore) ?? false;
1953 final nodeId = sharedPreferences.getInt(PreferencesKey.currentNodeIdKey);
@@ -2001,7 +1990,6 @@ abstract class SettingsStoreBase with Store {
1990 final decredNode = await Node.get(decredNodeId ?? -1);
1991 final dogecoinNode = await Node.get(dogecoinNodeId ?? -1);
1992
2004 -
1993 if (moneroNode != null) {
1994 nodes[WalletType.monero] = moneroNode;
1995 }
@@ -2173,15 +2161,12 @@ abstract class SettingsStoreBase with Store {
2161 }
2162
2163 Future<void> _saveCurrentNode(Node node, WalletType walletType) async {
2176 -
2164 switch (walletType) {
2165 case WalletType.bitcoin:
2179 - await _sharedPreferences.setInt(
2180 - PreferencesKey.currentBitcoinElectrumSererIdKey, node.id);
2166 + await _sharedPreferences.setInt(PreferencesKey.currentBitcoinElectrumSererIdKey, node.id);
2167 break;
2168 case WalletType.litecoin:
2183 - await _sharedPreferences.setInt(
2184 - PreferencesKey.currentLitecoinElectrumSererIdKey, node.id);
2169 + await _sharedPreferences.setInt(PreferencesKey.currentLitecoinElectrumSererIdKey, node.id);
2170 break;
2171 case WalletType.monero:
2172 await _sharedPreferences.setInt(PreferencesKey.currentNodeIdKey, node.id);
@@ -2200,8 +2185,7 @@ abstract class SettingsStoreBase with Store {
2185 nodes[node.type] = node;
2186 break;
2187 case WalletType.bitcoinCash:
2203 - await _sharedPreferences.setInt(
2204 - PreferencesKey.currentBitcoinCashNodeIdKey, node.id);
2188 + await _sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.id);
2189 break;
2190 case WalletType.nano:
2191 await _sharedPreferences.setInt(PreferencesKey.currentNanoNodeIdKey, node.id);
lib/store/templates/send_template_store.dart
+2 -4
@@ -8,8 +8,7 @@ part 'send_template_store.g.dart';
8 class SendTemplateStore = SendTemplateBase with _$SendTemplateStore;
9
10 abstract class SendTemplateBase with Store {
11 - SendTemplateBase({required this.templateSource})
12 - : templates = ObservableList<Template>() {
11 + SendTemplateBase({required this.templateSource}) : templates = ObservableList<Template>() {
12 update();
13 }
14
@@ -19,8 +18,7 @@ abstract class SendTemplateBase with Store {
18 Box<Template> templateSource;
19
20 @action
22 - void update() =>
23 - templates.replaceRange(0, templates.length, templateSource.values.toList());
21 + void update() => templates.replaceRange(0, templates.length, templateSource.values.toList());
22
23 @action
24 Future<void> addTemplate(
lib/store/wallet_list_store.dart
+1 -1
@@ -10,4 +10,4 @@ abstract class WalletListStoreBase with Store {
10
11 @observable
12 ObservableList<WalletDescription> wallets;
13 -}
\ No newline at end of file
13 +}
lib/themes/core/theme_store.dart
+2 -2
@@ -255,14 +255,14 @@ abstract class ThemeStoreBase with Store {
255 return savedDark;
256 }
257 } catch (_) {}
258 -
258 +
259 // If no saved dark theme, check if current theme is BlackTheme with accent colors
260 // and preserve it when switching to dark mode
261 if (_currentTheme is BlackTheme) {
262 final currentBlackTheme = _currentTheme as BlackTheme;
263 return BlackTheme(currentBlackTheme.accentColor, isOled: currentBlackTheme.isOled);
264 }
265 -
265 +
266 return ThemeList.darkTheme;
267 }
268
lib/themes/custom_theme_colors/light_theme_custom_colors.dart
+6 -6
@@ -4,25 +4,25 @@ import 'package:cake_wallet/themes/core/custom_theme_colors.dart';
4 class LightThemeCustomColors extends CustomThemeColors {
5 @override
6 Color get warningContainerColor => const Color(0xFFFFCC00);
7 -
7 +
8 @override
9 Color get warningOutlineColor => const Color(0xFF312938);
10
11 @override
12 Color get backgroundMainColor => const Color(0xFF000000);
13 -
13 +
14 @override
15 Color get backgroundGradientColor => const Color(0xFFE7E7FD);
16 -
16 +
17 @override
18 Color get cardGradientColorPrimary => const Color(0xFFFFFFFF);
19 -
19 +
20 @override
21 Color get cardGradientColorSecondary => const Color(0xFFF3F3FF);
22 -
22 +
23 @override
24 Color get toggleKnobStateColor => const Color(0xFFFFFFFF);
25 -
25 +
26 @override
27 Color get toggleColorOffState => const Color(0xFFCACAE7);
28 }
lib/tron/cw_tron.dart
+2 -1
@@ -158,7 +158,8 @@ class CWTron extends Tron {
158 String? from,
159 required bool isPending,
160 }) =>
161 - TronTransactionInfo(id: id,
161 + TronTransactionInfo(
162 + id: id,
163 amount: amount,
164 fee: fee,
165 direction: direction,
lib/utils/address_formatter.dart
+6 -9
@@ -11,7 +11,6 @@ class AddressFormatter {
11 TextAlign? textAlign,
12 bool shouldTruncate = false,
13 }) {
14 -
14 final cleanAddress = address.replaceAll('bitcoincash:', '');
15 final isMWEB = address.startsWith('ltcmweb');
16 final chunkSize = walletType != null ? _getChunkSize(walletType) : 4;
@@ -27,7 +26,8 @@ class AddressFormatter {
26 isMWEB: isMWEB,
27 chunkSize: chunkSize,
28 evenTextStyle: evenTextStyle,
30 - oddTextStyle: oddTextStyle ?? evenTextStyle.copyWith(color: evenTextStyle.color!.withAlpha(150)),
29 + oddTextStyle:
30 + oddTextStyle ?? evenTextStyle.copyWith(color: evenTextStyle.color!.withAlpha(150)),
31 textAlign: textAlign,
32 );
33 } else {
@@ -36,7 +36,8 @@ class AddressFormatter {
36 isMWEB: isMWEB,
37 chunkSize: chunkSize,
38 evenTextStyle: evenTextStyle,
39 - oddTextStyle: oddTextStyle ?? evenTextStyle.copyWith(color: evenTextStyle.color!.withAlpha(128)),
39 + oddTextStyle:
40 + oddTextStyle ?? evenTextStyle.copyWith(color: evenTextStyle.color!.withAlpha(128)),
41 textAlign: textAlign,
42 );
43 }
@@ -50,7 +51,6 @@ class AddressFormatter {
51 required TextStyle oddTextStyle,
52 TextAlign? textAlign,
53 }) {
53 -
54 final chunks = <String>[];
55
56 if (isMWEB) {
@@ -95,7 +95,6 @@ class AddressFormatter {
95 required TextStyle oddTextStyle,
96 TextAlign? textAlign,
97 }) {
98 -
98 if (isMWEB) {
99 const fixedPrefix = 'ltcmweb';
100 final secondChunkStart = fixedPrefix.length;
@@ -133,10 +132,8 @@ class AddressFormatter {
132 }
133
134 final String firstPart = address.substring(0, digitCount);
136 - final String secondPart =
137 - address.substring(digitCount, digitCount * 2);
138 - final String lastPart =
139 - address.substring(address.length - digitCount);
135 + final String secondPart = address.substring(digitCount, digitCount * 2);
136 + final String lastPart = address.substring(address.length - digitCount);
137
138 final spans = <TextSpan>[
139 TextSpan(text: '$firstPart ', style: evenTextStyle),
lib/utils/brightness_util.dart
+1 -1
@@ -17,4 +17,4 @@ class BrightnessUtil {
17 // ignore: unawaited_futures
18 DeviceDisplayBrightness.resetBrightness();
19 }
20 -}
\ No newline at end of file
20 +}
lib/utils/clipboard_util.dart
+2 -1
@@ -6,7 +6,8 @@ import 'package:flutter/services.dart';
6 import 'package:sensitive_clipboard/sensitive_clipboard.dart';
7
8 class ClipboardUtil {
9 - static Future<void> setSensitiveDataToClipboard(ClipboardData data, {bool isSensitive = true}) async {
9 + static Future<void> setSensitiveDataToClipboard(ClipboardData data,
10 + {bool isSensitive = true}) async {
11 if (isSensitive && DeviceInfo.instance.isMobile) {
12 await SensitiveClipboard.copy(data.text);
13 return;
lib/utils/date_picker.dart
+9 -17
@@ -3,12 +3,11 @@ import 'package:cake_wallet/main.dart';
3 import 'package:flutter/cupertino.dart';
4 import 'package:flutter/material.dart';
5
6 -Future<DateTime?> getDate({
7 - required BuildContext context,
8 - required DateTime initialDate,
9 - required DateTime firstDate,
10 - required DateTime lastDate}) {
11 -
6 +Future<DateTime?> getDate(
7 + {required BuildContext context,
8 + required DateTime initialDate,
9 + required DateTime firstDate,
10 + required DateTime lastDate}) {
11 if (Platform.isIOS) {
12 return _buildCupertinoDataPicker(context, initialDate, firstDate, lastDate);
13 }
@@ -17,10 +16,7 @@ Future<DateTime?> getDate({
16 }
17
18 Future<DateTime?> _buildMaterialDataPicker(
20 - BuildContext context,
21 - DateTime initialDate,
22 - DateTime firstDate,
23 - DateTime lastDate) async {
19 + BuildContext context, DateTime initialDate, DateTime firstDate, DateTime lastDate) async {
20 return await showDatePicker(
21 context: context,
22 initialDate: initialDate,
@@ -30,10 +26,7 @@ Future<DateTime?> _buildMaterialDataPicker(
26 }
27
28 Future<DateTime?> _buildCupertinoDataPicker(
33 - BuildContext context,
34 - DateTime initialDate,
35 - DateTime firstDate,
36 - DateTime lastDate) async {
29 + BuildContext context, DateTime initialDate, DateTime firstDate, DateTime lastDate) async {
30 DateTime? date;
31 await showModalBottomSheet<void>(
32 context: navigatorKey.currentState!.context,
@@ -48,7 +41,6 @@ Future<DateTime?> _buildCupertinoDataPicker(
41 maximumDate: lastDate,
42 ),
43 );
51 - }
52 - );
44 + });
45 return date;
54 -}
\ No newline at end of file
46 +}
lib/utils/debounce.dart
+3 -3
@@ -3,12 +3,12 @@ import 'package:flutter/foundation.dart';
3
4 class Debounce {
5 Debounce(this.duration);
6 -
6 +
7 final Duration duration;
8 Timer? _timer;
9 -
9 +
10 void run(VoidCallback action) {
11 _timer?.cancel();
12 _timer = Timer(duration, action);
13 }
14 -}
\ No newline at end of file
14 +}
lib/utils/device_info.dart
+2 -2
@@ -6,6 +6,6 @@ class DeviceInfo {
6 static DeviceInfo get instance => DeviceInfo._();
7
8 bool get isMobile => Platform.isAndroid || Platform.isIOS;
9 -
9 +
10 bool get isDesktop => Platform.isMacOS || Platform.isWindows || Platform.isLinux;
11 -}
\ No newline at end of file
11 +}
lib/utils/feature_flag.dart
+2 -1
@@ -10,7 +10,8 @@ class FeatureFlag {
10 static const bool isBackgroundSyncEnabled = true;
11 static bool get isInAppTorEnabled => CakeTor.instance is! CakeTorDisabled;
12 static const int verificationWordsCount = kDebugMode || kProfileMode ? 0 : 2;
13 - static const bool hasDevOptions = bool.fromEnvironment('hasDevOptions', defaultValue: kDebugMode || kProfileMode);
13 + static const bool hasDevOptions =
14 + bool.fromEnvironment('hasDevOptions', defaultValue: kDebugMode || kProfileMode);
15 static const bool hasBitcoinViewOnly = true;
16 static const bool customBackgroundEnabled = false;
17 static const bool duressPinEnabled = true;
lib/utils/item_cell.dart
+1 -3
@@ -7,9 +7,7 @@ import 'package:cw_core/keyable.dart';
7 // class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
8
9 class ItemCell<Item> with Keyable {
10 - ItemCell(this.value, {
11 - required this.isSelectedBuilder,
12 - required dynamic key}) {
10 + ItemCell(this.value, {required this.isSelectedBuilder, required dynamic key}) {
11 keyIndex = key;
12 }
13
lib/utils/list_item.dart
+1 -1
@@ -1,3 +1,3 @@
1 abstract class ListItem {
2 const ListItem();
3 -}
\ No newline at end of file
3 +}
lib/utils/list_section.dart
+1 -1
@@ -2,4 +2,4 @@ class ListSection<Item> {
2 const ListSection({required this.items});
3
4 final List<Item> items;
5 -}
\ No newline at end of file
5 +}
lib/utils/mobx.dart
+4 -8
@@ -4,15 +4,13 @@ import 'package:mobx/mobx.dart';
4 import 'package:cw_core/keyable.dart';
5
6 void connectMapToListWithTransform<T extends Keyable, Y extends Keyable>(
7 - ObservableMap<dynamic, T> source,
8 - ObservableList<Y> dest,
9 - Y Function(T?) transform,
7 + ObservableMap<dynamic, T> source, ObservableList<Y> dest, Y Function(T?) transform,
8 {bool Function(T?)? filter}) {
9 source.observe((MapChange<dynamic, T> change) {
10 if (change.type == null) {
11 return;
12 }
15 -
13 +
14 switch (change.type) {
15 case OperationType.add:
16 if (filter?.call(change.newValue) ?? true) {
@@ -21,8 +19,7 @@ void connectMapToListWithTransform<T extends Keyable, Y extends Keyable>(
19 break;
20 case OperationType.remove:
21 // Hive could has equal index and key
24 - dest.removeWhere((elem) =>
25 - elem.keyIndex == (change.key ?? change.newValue?.keyIndex));
22 + dest.removeWhere((elem) => elem.keyIndex == (change.key ?? change.newValue?.keyIndex));
23 break;
24 case OperationType.update:
25 for (var i = 0; i < dest.length; i++) {
@@ -88,8 +85,7 @@ extension MobxBindable<T extends Keyable> on Box<T> {
85 return;
86 }
87
91 - dest.acceptBoxChange(event,
92 - transformed: event.deleted ? null : transform(event.value as T));
88 + dest.acceptBoxChange(event, transformed: event.deleted ? null : transform(event.value as T));
89 });
90 }
91 }
lib/utils/package_info.dart
+36 -41
@@ -2,53 +2,48 @@ import 'dart:io';
2 import 'package:package_info_plus/package_info_plus.dart' as __package_info__;
3
4 abstract class _EnvKeys {
5 - static const kWinAppName = 'CW_WIN_APP_NAME';
6 - static const kWinAppPackageName = 'CW_WIN_APP_PACKAGE_NAME';
7 - static const kWinAppVersion = 'CW_WIN_APP_VERSION';
8 - static const kWinAppBuildNumber = 'CW_WIN_APP_BUILD_NUMBER';
5 + static const kWinAppName = 'CW_WIN_APP_NAME';
6 + static const kWinAppPackageName = 'CW_WIN_APP_PACKAGE_NAME';
7 + static const kWinAppVersion = 'CW_WIN_APP_VERSION';
8 + static const kWinAppBuildNumber = 'CW_WIN_APP_BUILD_NUMBER';
9 }
10
11 class PackageInfo {
12 - static Future<PackageInfo> fromPlatform() async {
13 - if (Platform.isWindows) {
14 - return _windowsPackageInfo;
15 - }
16 -
17 - final packageInfo = await __package_info__.PackageInfo.fromPlatform();
18 - return PackageInfo._(
19 - appName: packageInfo.appName,
20 - packageName: packageInfo.packageName,
21 - version: packageInfo.version,
22 - buildNumber: packageInfo.buildNumber);
12 + static Future<PackageInfo> fromPlatform() async {
13 + if (Platform.isWindows) {
14 + return _windowsPackageInfo;
15 }
16
25 - static const _defaultCWAppName = 'Cake Wallet';
26 - static const _defaultCWAppPackageName = 'com.cakewallet.cake_wallet';
27 - static const _defaultCWAppVersion = '1.0.0';
28 - static const _defaultCWAppBuildNumber = '1';
17 + final packageInfo = await __package_info__.PackageInfo.fromPlatform();
18 + return PackageInfo._(
19 + appName: packageInfo.appName,
20 + packageName: packageInfo.packageName,
21 + version: packageInfo.version,
22 + buildNumber: packageInfo.buildNumber);
23 + }
24 +
25 + static const _defaultCWAppName = 'Cake Wallet';
26 + static const _defaultCWAppPackageName = 'com.cakewallet.cake_wallet';
27 + static const _defaultCWAppVersion = '1.0.0';
28 + static const _defaultCWAppBuildNumber = '1';
29
30 - static const _windowsPackageInfo = PackageInfo._(
31 - appName: const String
32 - .fromEnvironment(_EnvKeys.kWinAppName,
33 - defaultValue: _defaultCWAppName),
34 - packageName: const String
35 - .fromEnvironment(_EnvKeys.kWinAppPackageName,
36 - defaultValue: _defaultCWAppPackageName),
37 - version: const String
38 - .fromEnvironment(_EnvKeys.kWinAppVersion,
39 - defaultValue: _defaultCWAppVersion),
40 - buildNumber: const String
41 - .fromEnvironment(_EnvKeys.kWinAppBuildNumber,
42 - defaultValue: _defaultCWAppBuildNumber));
30 + static const _windowsPackageInfo = PackageInfo._(
31 + appName: const String.fromEnvironment(_EnvKeys.kWinAppName, defaultValue: _defaultCWAppName),
32 + packageName: const String.fromEnvironment(_EnvKeys.kWinAppPackageName,
33 + defaultValue: _defaultCWAppPackageName),
34 + version:
35 + const String.fromEnvironment(_EnvKeys.kWinAppVersion, defaultValue: _defaultCWAppVersion),
36 + buildNumber: const String.fromEnvironment(_EnvKeys.kWinAppBuildNumber,
37 + defaultValue: _defaultCWAppBuildNumber));
38
44 - final String appName;
45 - final String packageName;
46 - final String version;
47 - final String buildNumber;
39 + final String appName;
40 + final String packageName;
41 + final String version;
42 + final String buildNumber;
43
49 - const PackageInfo._({
50 - required this.appName,
51 - required this.packageName,
52 - required this.version,
53 - required this.buildNumber});
44 + const PackageInfo._(
45 + {required this.appName,
46 + required this.packageName,
47 + required this.version,
48 + required this.buildNumber});
49 }
lib/utils/tor.dart
+8 -8
@@ -59,13 +59,13 @@ Future<BuildContext> showFullscreenDialog(BuildContext context) async {
59 builder: (context) {
60 dialogContext = context;
61 return PopScope(
62 - canPop: false,
63 - child: Container(
64 - color: Colors.transparent,
65 - child: Center(
66 - child: CircularProgressIndicator(
67 - color: Colors.white,
68 - ),
62 + canPop: false,
63 + child: Container(
64 + color: Colors.transparent,
65 + child: Center(
66 + child: CircularProgressIndicator(
67 + color: Colors.white,
68 + ),
69 ),
70 ),
71 );
@@ -79,4 +79,4 @@ Future<BuildContext> showFullscreenDialog(BuildContext context) async {
79 Future<void> dismissFullscreenDialog(BuildContext context) async {
80 await Future.delayed(const Duration(seconds: 1));
81 Navigator.of(context).pop();
82 -}
\ No newline at end of file
82 +}
lib/utils/totp_utils.dart
+1 -1
@@ -22,7 +22,7 @@ String generateRandomBase32SecretKey(int byteLength) {
22 String generateOTP({required String secretKey, required int input}) {
23 /// base32 decode the secret
24 var hmacKey = base32.decode(secretKey);
25 -
25 +
26 /// initial the HMAC-SHA1 object
27 var hmacSha = Hmac(sha512, hmacKey);
28
lib/view_model/animated_ur_model.dart
+2 -3
@@ -3,8 +3,7 @@ import 'package:cw_core/wallet_base.dart';
3 import 'package:mobx/mobx.dart';
4
5 class AnimatedURModel with Store {
6 - AnimatedURModel(this.appStore)
7 - : wallet = appStore.wallet!;
6 + AnimatedURModel(this.appStore) : wallet = appStore.wallet!;
7 final AppStore appStore;
8 final WalletBase wallet;
10 -}
\ No newline at end of file
9 +}
lib/view_model/auth_state.dart
-1
@@ -5,4 +5,3 @@ class AuthenticationBanned extends ExecutionState {
5
6 final String error;
7 }
8 -
lib/view_model/auth_view_model.dart
+1 -1
@@ -121,4 +121,4 @@ abstract class AuthViewModelBase with Store {
121 _authService.saveLastAuthTime();
122 }
123 }
124 -}
\ No newline at end of file
124 +}
lib/view_model/backup_view_model.dart
+3 -3
@@ -30,13 +30,13 @@ abstract class BackupViewModelBase with Store {
30 init();
31
32 reaction((_) => editBackupPasswordViewModel.backupPassword, (value) {
33 - if(value != backupPassword) {
33 + if (value != backupPassword) {
34 backupPassword = value;
35 }
36 });
37
38 - reaction((_)=>backupPassword, (value){
39 - if(value != editBackupPasswordViewModel.backupPassword) {
38 + reaction((_) => backupPassword, (value) {
39 + if (value != editBackupPasswordViewModel.backupPassword) {
40 editBackupPasswordViewModel.backupPassword = value;
41 }
42 });
lib/view_model/bridge/bridge_details_view_model.dart
+2 -2
@@ -98,8 +98,8 @@ abstract class BridgeDetailsViewModelBase with Store {
98
99 final sourceName =
100 evm?.getChainInfoByChainId(transfer.sourceChainId)?.name ?? '${transfer.sourceChainId}';
101 - final destName =
102 - evm?.getChainInfoByChainId(transfer.destinationChainId)?.name ?? '${transfer.destinationChainId}';
101 + final destName = evm?.getChainInfoByChainId(transfer.destinationChainId)?.name ??
102 + '${transfer.destinationChainId}';
103
104 items.add(
105 StandartListItem(
lib/view_model/bridge/bridge_view_model.dart
+8 -12
@@ -142,13 +142,13 @@ abstract class BridgeViewModelBase extends WalletChangeListenerViewModel with St
142
143 @computed
144 String get amountDisplayFormatted {
145 - if (selectedToken == null) return "0.00";
145 + if (selectedToken == null) return "0.00";
146
147 - return amountParsingProxy.getDisplayCryptoAmount(
148 - amount.replaceAll(',', '.'),
149 - selectedToken!,
150 - );
151 - }
147 + return amountParsingProxy.getDisplayCryptoAmount(
148 + amount.replaceAll(',', '.'),
149 + selectedToken!,
150 + );
151 + }
152
153 DecimalAmountValidator get decimalAmountValidator => DecimalAmountValidator(
154 currency: selectedToken!,
@@ -176,8 +176,7 @@ abstract class BridgeViewModelBase extends WalletChangeListenerViewModel with St
176 String get quoteNativeFee {
177 if (quote == null) return '—';
178
179 - return amountParsingProxy.asDisplayString(
180 - Money(quote!.nativeFee, wallet.currency));
179 + return amountParsingProxy.asDisplayString(Money(quote!.nativeFee, wallet.currency));
180 }
181
182 @computed
@@ -281,10 +280,7 @@ abstract class BridgeViewModelBase extends WalletChangeListenerViewModel with St
280 return;
281 }
282 setAmount(
284 - amountParsingProxy.asDisplayString(Money(
285 - selectedTokenBalance,
286 - token)
287 - ),
283 + amountParsingProxy.asDisplayString(Money(selectedTokenBalance, token)),
284 );
285 }
286
lib/view_model/buy/buy_amount_view_model.dart
+2 -2
@@ -11,8 +11,8 @@ abstract class BuyAmountViewModelBase with Store {
11 BuyAmountViewModelBase()
12 : amount = '',
13 fiatCurrency = FiatCurrency.usd {
14 - int selectedIndex = FiatCurrency.currenciesAvailableToBuyWith
15 - .indexOf(getIt.get<SettingsStore>().fiatCurrency);
14 + int selectedIndex =
15 + FiatCurrency.currenciesAvailableToBuyWith.indexOf(getIt.get<SettingsStore>().fiatCurrency);
16
17 if (selectedIndex != -1) {
18 fiatCurrency = FiatCurrency.currenciesAvailableToBuyWith[selectedIndex];
lib/view_model/buy/buy_item.dart
+2 -3
@@ -18,8 +18,7 @@ class BuyItem {
18 BuyAmount _buyAmount;
19
20 try {
21 - _buyAmount = await provider
22 - .calculateAmount(amount?.toString() ?? '', fiatCurrency.title);
21 + _buyAmount = await provider.calculateAmount(amount?.toString() ?? '', fiatCurrency.title);
22 } catch (e) {
23 _buyAmount = BuyAmount(sourceAmount: 0.0, destAmount: 0.0);
24 printV(e.toString());
@@ -27,4 +26,4 @@ class BuyItem {
26
27 return _buyAmount;
28 }
30 -}
\ No newline at end of file
29 +}
lib/view_model/buy/buy_sell_view_model.dart
+10 -8
@@ -476,8 +476,7 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S
476 validQuotes.where((element) => !uniqueProviderQuotes.contains(element)).toList());
477
478 if (sortedRecommendedQuotes.isNotEmpty) {
479 - sortedRecommendedQuotes.first
480 - ..setIsBestRate = true;
479 + sortedRecommendedQuotes.first..setIsBestRate = true;
480 bestRateQuote = sortedRecommendedQuotes.first;
481
482 sortedRecommendedQuotes.sort((a, b) {
@@ -486,14 +485,17 @@ abstract class BuySellViewModelBase extends WalletChangeListenerViewModel with S
485 return 0;
486 });
487
489 - final Quote effectiveBestRateQuote =
490 - sortedRecommendedQuotes.reduce((a, b) {
491 - return isBuyAction ? a.rate < b.rate ? a : b : a.rate > b.rate ? a : b;
488 + final Quote effectiveBestRateQuote = sortedRecommendedQuotes.reduce((a, b) {
489 + return isBuyAction
490 + ? a.rate < b.rate
491 + ? a
492 + : b
493 + : a.rate > b.rate
494 + ? a
495 + : b;
496 });
497
494 -
495 - effectiveBestRateQuote.recommendations
496 - .add(ProviderRecommendation.bestRate);
498 + effectiveBestRateQuote.recommendations.add(ProviderRecommendation.bestRate);
499
500 selectedQuote = sortedRecommendedQuotes.first;
501 sortedRecommendedQuotes.first.setIsSelected = true;
lib/view_model/cake_pay/cake_pay_buy_card_view_model.dart
+4 -3
@@ -162,8 +162,9 @@ abstract class CakePayBuyCardViewModelBase with Store {
162 confirmsVoidedRefund: confirmsVoidedRefund,
163 confirmsTermsAgreed: confirmsTermsAgreed,
164 );
165 - final paymentData =
166 - CakePayOrder.getPaymentDataFor(method: selectedPaymentMethod, order: order); // TODO should hande other currencies if added
165 + final paymentData = CakePayOrder.getPaymentDataFor(
166 + method: selectedPaymentMethod,
167 + order: order); // TODO should hande other currencies if added
168 if (paymentData == null || order == null)
169 throw Exception('Payment data or order is not available.');
170
@@ -240,7 +241,7 @@ abstract class CakePayBuyCardViewModelBase with Store {
241 formattedRemainingTime = formatDuration(remainingTime!);
242 }
243 }
243 -
244 +
245 Future<void> logout() async => await _cakePayService.logout();
246
247 void _startExpirationTimer() {
lib/view_model/cake_pay/cake_pay_cards_list_view_model.dart
-1
@@ -153,7 +153,6 @@ abstract class CakePayCardsListViewModelBase with Store {
153 .toList(growable: false);
154 }
155
156 -
156 bool get hasFiltersChanged {
157 return selectedCountry != _initialSelectedCountry ||
158 displayPrepaidCards != _initialDisplayPrepaidCards ||
lib/view_model/contact_list/contact_view_model.dart
+12 -14
@@ -19,8 +19,7 @@ part 'contact_view_model.g.dart';
19 class ContactViewModel = ContactViewModelBase with _$ContactViewModel;
20
21 abstract class ContactViewModelBase with Store {
22 - ContactViewModelBase(this._contacts, this.appStore,this.adrResService,
23 - {ContactRecord? contact})
22 + ContactViewModelBase(this._contacts, this.appStore, this.adrResService, {ContactRecord? contact})
23 : state = InitialExecutionState(),
24 currencies = CryptoCurrency.all,
25 _contact = contact,
@@ -33,7 +32,6 @@ abstract class ContactViewModelBase with Store {
32 final AppStore appStore;
33 final AddressResolverService adrResService;
34
36 -
35 @observable
36 ExecutionState state;
37
@@ -53,9 +51,7 @@ abstract class ContactViewModelBase with Store {
51
52 @computed
53 bool get isReady =>
56 - name.isNotEmpty &&
57 - (currency?.toString().isNotEmpty ?? false) &&
58 - address.isNotEmpty;
54 + name.isNotEmpty && (currency?.toString().isNotEmpty ?? false) && address.isNotEmpty;
55
56 final List<CryptoCurrency> currencies;
57 final Box<Contact> _contacts;
@@ -78,7 +74,6 @@ abstract class ContactViewModelBase with Store {
74 if (currentCurrency == null) return null;
75 if (query.isEmpty) return null;
76
81 -
77 // Check if the address is valid for the current currency (except for Zano, which can use handles as addresses)
78 if (currentCurrency != CryptoCurrency.zano) {
79 final isValidAddress = AddressValidator(type: currentCurrency).isValid(query);
@@ -108,9 +103,8 @@ abstract class ContactViewModelBase with Store {
103 if (resolvedAddress == null || resolvedAddress.isEmpty) return;
104
105 address = resolvedAddress;
111 - displayName = parsedAddress.profileName.isNotEmpty
112 - ? parsedAddress.profileName
113 - : parsedAddress.handle;
106 + displayName =
107 + parsedAddress.profileName.isNotEmpty ? parsedAddress.profileName : parsedAddress.handle;
108 }
109
110 Future<void> save() async {
@@ -135,11 +129,15 @@ abstract class ContactViewModelBase with Store {
129 _contact.lastChange = now;
130 await _contact.save();
131 } else {
138 - await _contacts
139 - .add(Contact(name: name, address: address, type: currency!, lastChange: now, displayName: displayName));
132 + await _contacts.add(Contact(
133 + name: name,
134 + address: address,
135 + type: currency!,
136 + lastChange: now,
137 + displayName: displayName));
138 }
139
142 - lastChange = now;
140 + lastChange = now;
141 state = ExecutedSuccessfullyState();
142 } catch (e) {
143 state = FailureState(e.toString());
@@ -149,4 +147,4 @@ abstract class ContactViewModelBase with Store {
147 bool doesContactNameExist(String name) {
148 return _contacts.values.any((contact) => contact.name == name);
149 }
152 -}
\ No newline at end of file
150 +}
lib/view_model/dashboard/action_list_item.dart
+1 -1
@@ -5,4 +5,4 @@ abstract class ActionListItem {
5
6 DateTime get date;
7 Key key;
8 -}
\ No newline at end of file
8 +}
lib/view_model/dashboard/dashboard_view_model.dart
+15 -18
@@ -252,7 +252,6 @@ abstract class DashboardViewModelBase with Store {
252 tradeMonitor.monitorActiveTrades(wallet.id);
253 }
254
255 -
255 void loadFilterItems() {
256 filterItems = [
257 // FilterItem(
@@ -276,14 +275,12 @@ abstract class DashboardViewModelBase with Store {
275 SwapFilterItem(
276 enabledProviders: () => tradeFilterStore.enabledProvidersCount,
277 allEnabled: () => tradeFilterStore.displayAllTrades,
279 - value: () => tradeFilterStore.enabledProvidersCount>0,
280 - onChanged: () =>
281 - tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.all)),
278 + value: () => tradeFilterStore.enabledProvidersCount > 0,
279 + onChanged: () => tradeFilterStore.toggleDisplayExchange(ExchangeProviderDescription.all)),
280 FilterItem(
281 value: () => orderFilterStore.displayCakePay,
282 caption: 'Cake Pay',
285 - onChanged: () =>
286 - orderFilterStore.toggleDisplayOrder(OrderProviderDescription.cakePay)),
283 + onChanged: () => orderFilterStore.toggleDisplayOrder(OrderProviderDescription.cakePay)),
284 ];
285 exchangeFilterItems = [
286 SwapProviderFilterItem(
@@ -354,8 +351,6 @@ abstract class DashboardViewModelBase with Store {
351 ];
352 }
353
357 -
358 -
354 bool _isTransactionDisposerCallbackRunning = false;
355
356 @action
@@ -402,9 +397,9 @@ abstract class DashboardViewModelBase with Store {
397 }
398
399 bool showBridge(CryptoCurrency currency) {
405 - if(!isEVMCompatibleChain(wallet.type)) return false;
400 + if (!isEVMCompatibleChain(wallet.type)) return false;
401
407 - if(evm!.isUSDT0Token(wallet, currency)) return true;
402 + if (evm!.isUSDT0Token(wallet, currency)) return true;
403
404 return false;
405 }
@@ -513,7 +508,8 @@ abstract class DashboardViewModelBase with Store {
508 // printV("Transaction disposer callback (relevantTxs: ${relevantTxs.length} current: ${transactions.length})");
509
510 // TODO(malik) update this in a saner way during the vm refactor
516 - String _txIdentityString(String txHash, TransactionDirection direction) => "${txHash}_$direction";
511 + String _txIdentityString(String txHash, TransactionDirection direction) =>
512 + "${txHash}_$direction";
513 String _txIdentityStringConfirmations(
514 String txHash, TransactionDirection direction, int confirmations, bool isPending) =>
515 "${txHash}_${direction}_${confirmations}_$isPending";
@@ -542,7 +538,8 @@ abstract class DashboardViewModelBase with Store {
538 .toSet();
539
540 transactions.removeWhere(
545 - (item) => newKeys.contains(_txIdentityString(item.transaction.txHash, item.transaction.direction)),
541 + (item) => newKeys
542 + .contains(_txIdentityString(item.transaction.txHash, item.transaction.direction)),
543 );
544
545 transactions.addAll(newTransactions);
@@ -684,7 +681,9 @@ abstract class DashboardViewModelBase with Store {
681 }).toList();
682
683 @computed
687 - bool get shouldShowBalanceHiddenMessage => balanceDisplayMode == BalanceDisplayMode.hiddenBalance && appStore.settingsStore.balanceHideCounter < 10;
684 + bool get shouldShowBalanceHiddenMessage =>
685 + balanceDisplayMode == BalanceDisplayMode.hiddenBalance &&
686 + appStore.settingsStore.balanceHideCounter < 10;
687
688 @computed
689 List<OrderListItem> get orders =>
@@ -736,10 +735,8 @@ abstract class DashboardViewModelBase with Store {
735 static const shortHistoryLength = 3;
736
737 @computed
739 - List<ActionListItem> get itemsShort => items
740 - .where((item) => item is! DateSectionItem)
741 - .take(shortHistoryLength)
742 - .toList();
738 + List<ActionListItem> get itemsShort =>
739 + items.where((item) => item is! DateSectionItem).take(shortHistoryLength).toList();
740
741 @observable
742 WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet;
@@ -809,7 +806,7 @@ abstract class DashboardViewModelBase with Store {
806 // if (wallet.seed == "") "wallet seed is empty",
807 // if (monero!.getSubaddressList(wallet).getAll(wallet)[0].address ==
808 // "41d7FXjswpK1111111111111111111111111111111111111111111111111111111111111111111111111111112KhNi4")
812 - // "primary address is invalid, you won't be able to receive / spend funds",
809 + // "primary address is invalid, you won't be able to receive / spend funds",
810 ];
811 return errors;
812 }
lib/view_model/dashboard/filter_item.dart
+7 -12
@@ -1,10 +1,7 @@
1 import 'package:cake_wallet/exchange/exchange_provider_description.dart';
2
3 class FilterItem {
4 - FilterItem({
5 - required this.value,
6 - required this.caption,
7 - required this.onChanged});
4 + FilterItem({required this.value, required this.caption, required this.onChanged});
5
6 bool Function() value;
7 String caption;
@@ -24,17 +21,15 @@ class SwapFilterItem extends FilterItem {
21 bool Function() allEnabled;
22 }
23
27 -
24 class SwapProviderFilterItem extends FilterItem {
29 - SwapProviderFilterItem({
30 - required super.value,
31 - required super.onChanged,
32 - required this.providerDescription,
33 - super.caption = ""
34 -});
25 + SwapProviderFilterItem(
26 + {required super.value,
27 + required super.onChanged,
28 + required this.providerDescription,
29 + super.caption = ""});
30
31 @override
32 String get caption => providerDescription.title;
33
34 final ExchangeProviderDescription providerDescription;
40 -}
\ No newline at end of file
35 +}
lib/view_model/dashboard/home_settings_view_model.dart
+11 -13
@@ -34,10 +34,9 @@ abstract class HomeSettingsViewModelBase with Store {
34 showCombinedBalance = _balanceViewModel.wallet.walletInfo.showCombinedBalance,
35 favoriteToken = _balanceViewModel.wallet.currency {
36 _updateTokensList();
37 - _updateLocalFavoriteToken();
38 -
37 + _updateLocalFavoriteToken();
38
40 - // React to wallet changes
39 + // React to wallet changes
40 reaction((_) => _balanceViewModel.wallet, (_) {
41 _updateTokensList();
42 });
@@ -61,7 +60,8 @@ abstract class HomeSettingsViewModelBase with Store {
60 final ObservableSet<CryptoCurrency> tokens;
61
62 @computed
64 - List<CryptoCurrency> get enabledTokens => [_balanceViewModel.wallet.currency, ...tokens.where((item)=>item.enabled).toList()];
63 + List<CryptoCurrency> get enabledTokens =>
64 + [_balanceViewModel.wallet.currency, ...tokens.where((item) => item.enabled).toList()];
65
66 WalletType get walletType => _balanceViewModel.wallet.type;
67
@@ -413,11 +413,10 @@ abstract class HomeSettingsViewModelBase with Store {
413 void _updateFiatPrices(CryptoCurrency token) async {
414 if (token.isPotentialScam) return; // don't fetch price data for potential scam tokens
415 try {
416 - _balanceViewModel.fiatConversionStore.prices[token] =
417 - await FiatConversionService.fetchPrice(
418 - crypto: token,
419 - fiat: _settingsStore.fiatCurrency,
420 - torOnly: _settingsStore.fiatApiMode == FiatApiMode.torOnly);
416 + _balanceViewModel.fiatConversionStore.prices[token] = await FiatConversionService.fetchPrice(
417 + crypto: token,
418 + fiat: _settingsStore.fiatCurrency,
419 + torOnly: _settingsStore.fiatApiMode == FiatApiMode.torOnly);
420 } catch (_) {}
421 }
422
@@ -499,7 +498,6 @@ abstract class HomeSettingsViewModelBase with Store {
498 }
499 }
500
502 -
501 // FIXME these two observables cause duplicated state and are needed because mobx. remove them as part of the refactor and replace with proper getters
502 @observable
503 bool showCombinedBalance;
@@ -519,7 +517,7 @@ abstract class HomeSettingsViewModelBase with Store {
517 Future<void> setFavoriteToken(CryptoCurrency token) async {
518 final String? address;
519
522 - if(token == _balanceViewModel.wallet.currency) {
520 + if (token == _balanceViewModel.wallet.currency) {
521 address = null;
522 } else {
523 address = getTokenAddressBasedOnWallet(token);
@@ -533,11 +531,11 @@ abstract class HomeSettingsViewModelBase with Store {
531 @action
532 Future<void> _updateLocalFavoriteToken() async {
533 favoriteToken = await TokenUtilities.findTokenByAddress(
536 - walletType: _balanceViewModel.wallet.type, address: _balanceViewModel.wallet.walletInfo.favoriteTokenAddress ?? "") ??
534 + walletType: _balanceViewModel.wallet.type,
535 + address: _balanceViewModel.wallet.walletInfo.favoriteTokenAddress ?? "") ??
536 _balanceViewModel.wallet.currency;
537 }
538
540 -
539 @action
540 void _refreshTokensList() {
541 final _tokens = Set.of(tokens);
lib/view_model/dashboard/order_list_item.dart
+1 -1
@@ -23,4 +23,4 @@ class OrderListItem extends ActionListItem {
23
24 @override
25 DateTime get date => order.createdAt;
26 -}
\ No newline at end of file
26 +}
lib/view_model/dashboard/receive_option_view_model.dart
-1
@@ -31,7 +31,6 @@ abstract class ReceiveOptionViewModelBase with Store {
31
32 String get walletTypeString => walletTypeToString(_wallet.type);
33
34 -
34 @action
35 void selectReceiveOption(ReceivePageOption option) => selectedReceiveOption = option;
36 }
lib/view_model/dashboard/transaction_list_item.dart
+1 -3
@@ -55,7 +55,6 @@ class TransactionListItem extends ActionListItem with Keyable {
55 }
56
57 String get formattedTitle {
58 -
58 if (balanceViewModel.wallet.type == WalletType.bitcoin &&
59 transaction.additionalInfo['hasMissingInputTx'] == true) {
60 return 'Transaction has missing data';
@@ -90,8 +89,7 @@ class TransactionListItem extends ActionListItem with Keyable {
89 case WalletType.litecoin:
90 bool isPegOut = (transaction.additionalInfo["isPegOut"] as bool?) ?? false;
91 bool fromPegOut = (transaction.additionalInfo["fromPegOut"] as bool?) ?? false;
93 - if(isPegOut || fromPegOut)
94 - return 6;
92 + if (isPegOut || fromPegOut) return 6;
93 default:
94 return 0;
95 }
lib/view_model/dashboard/wallet_balance.dart
+1 -1
@@ -3,4 +3,4 @@ class WalletBalance {
3
4 String unlockedBalance;
5 String totalBalance;
6 -}
\ No newline at end of file
6 +}
lib/view_model/dev/background_sync_logs_view_model.dart
+5 -3
@@ -2,7 +2,9 @@ import 'package:flutter_daemon/flutter_daemon.dart';
2 import 'package:mobx/mobx.dart';
3
4 part 'background_sync_logs_view_model.g.dart';
5 -class BackgroundSyncLogsViewModel = BackgroundSyncLogsViewModelBase with _$BackgroundSyncLogsViewModel;
5 +
6 +class BackgroundSyncLogsViewModel = BackgroundSyncLogsViewModelBase
7 + with _$BackgroundSyncLogsViewModel;
8
9 abstract class BackgroundSyncLogsViewModelBase with Store {
10 final FlutterDaemon _daemon = FlutterDaemon();
@@ -26,7 +28,7 @@ abstract class BackgroundSyncLogsViewModelBase with Store {
28 Future<void> loadLogs() async {
29 isLoading = true;
30 error = null;
29 -
31 +
32 try {
33 logData = await _daemon.getLogs();
34 } catch (e) {
@@ -41,4 +43,4 @@ abstract class BackgroundSyncLogsViewModelBase with Store {
43 await _daemon.clearLogs();
44 await loadLogs();
45 }
44 -}
\ No newline at end of file
46 +}
lib/view_model/dev/exchange_provider_logs_view_model.dart
+3 -2
@@ -6,7 +6,8 @@ part 'exchange_provider_logs_view_model.g.dart';
6
7 enum LogFilter { all, success, error }
8
9 -class ExchangeProviderLogsViewModel = ExchangeProviderLogsViewModelBase with _$ExchangeProviderLogsViewModel;
9 +class ExchangeProviderLogsViewModel = ExchangeProviderLogsViewModelBase
10 + with _$ExchangeProviderLogsViewModel;
11
12 abstract class ExchangeProviderLogsViewModelBase with Store {
13 @observable
@@ -60,7 +61,7 @@ abstract class ExchangeProviderLogsViewModelBase with Store {
61 void loadLogs() {
62 isLoading = true;
63 error = null;
63 -
64 +
65 try {
66 logs.clear();
67 logs.addAll(ExchangeProviderLogger.logs);
lib/view_model/dev/network_requests_view_model.dart
+1 -1
@@ -13,4 +13,4 @@ abstract class NetworkRequestsViewModelBase with Store {
13 Future<void> loadLogs() async {
14 logs = MemoryProxyLogger.logs;
15 }
16 -}
\ No newline at end of file
16 +}
lib/view_model/dev/qr_tools_view_model.dart
+12 -14
@@ -22,8 +22,6 @@ abstract class QRToolsViewModelBase with Store {
22 @observable
23 String input = '';
24
25 -
26 -
25 @computed
26 Map<String, dynamic> get data => _getResult(input);
27
@@ -33,7 +31,6 @@ abstract class QRToolsViewModelBase with Store {
31 return out.$1;
32 }
33
36 -
34 Map<String, dynamic> _getResult(String input) {
35 try {
36 final decoder = URDecoder();
@@ -49,15 +46,17 @@ abstract class QRToolsViewModelBase with Store {
46 decoder.receivePart(part);
47 }
48 return {
52 - "result": (decoder.result != null) ? switch (decoder.result.runtimeType) {
53 - UR => {
54 - "cbor": (decoder.result as UR).cbor,
55 - "_cbor.decode.base64": base64.encode(_decodeCBOR((decoder.result as UR).cbor)),
56 - "type": (decoder.result as UR).type,
57 - "toString": (decoder.result as UR).toString(),
58 - },
59 - _ => "unknown type: ${decoder.result.runtimeType}"
60 - } : null,
49 + "result": (decoder.result != null)
50 + ? switch (decoder.result.runtimeType) {
51 + UR => {
52 + "cbor": (decoder.result as UR).cbor,
53 + "_cbor.decode.base64": base64.encode(_decodeCBOR((decoder.result as UR).cbor)),
54 + "type": (decoder.result as UR).type,
55 + "toString": (decoder.result as UR).toString(),
56 + },
57 + _ => "unknown type: ${decoder.result.runtimeType}"
58 + }
59 + : null,
60 "expectedType": decoder.expectedType,
61 "estimatedPercentComplete": decoder.estimatedPercentComplete(),
62 "processedPartsCount": decoder.processedPartsCount(),
@@ -70,7 +69,6 @@ abstract class QRToolsViewModelBase with Store {
69 "resultError": decoder.resultError(),
70 "resultMessage": decoder.resultMessage(),
71 "toString": decoder.toString(),
73 -
72 };
73 } catch (e) {
74 return {
@@ -78,4 +76,4 @@ abstract class QRToolsViewModelBase with Store {
76 };
77 }
78 }
81 -}
\ No newline at end of file
79 +}
lib/view_model/dev/secure_preferences.dart
+4 -15
@@ -6,14 +6,7 @@ part 'secure_preferences.g.dart';
6
7 class DevSecurePreferences = DevSecurePreferencesBase with _$DevSecurePreferences;
8
9 -enum PreferenceType {
10 - unknown,
11 - string,
12 - int,
13 - double,
14 - bool,
15 - listString
16 -}
9 +enum PreferenceType { unknown, string, int, double, bool, listString }
10
11 abstract class DevSecurePreferencesBase with Store {
12 DevSecurePreferencesBase() {
@@ -29,9 +22,7 @@ abstract class DevSecurePreferencesBase with Store {
22 List<String> get keys => values.keys.toList()..sort();
23
24 @action
32 - Future<void> delete(String key) async {
33 -
34 - }
25 + Future<void> delete(String key) async {}
26
27 dynamic get(String key) {
28 if (!values.containsKey(key)) {
@@ -42,13 +33,11 @@ abstract class DevSecurePreferencesBase with Store {
33 final decodedPassword = decodeWalletPassword(password: values[key]!);
34 return values[key]! + "\n\nDecoded: $decodedPassword";
35 } catch (e) {
45 - return values[key]! +"\n$e";
36 + return values[key]! + "\n$e";
37 }
38 }
39
49 - Future<void> set(String key, PreferenceType type, dynamic value) async {
50 -
51 - }
40 + Future<void> set(String key, PreferenceType type, dynamic value) async {}
41
42 PreferenceType getPreferenceType(String key) {
43 if (!values.containsKey(key)) {
lib/view_model/dev/send_network_requests_view_model.dart
+3 -2
@@ -3,7 +3,8 @@ import 'package:mobx/mobx.dart';
3
4 part 'send_network_requests_view_model.g.dart';
5
6 -class SendNetworkRequestsViewModel = SendNetworkRequestsViewModelBase with _$SendNetworkRequestsViewModel;
6 +class SendNetworkRequestsViewModel = SendNetworkRequestsViewModelBase
7 + with _$SendNetworkRequestsViewModel;
8
9 abstract class SendNetworkRequestsViewModelBase with Store {
10 @observable
@@ -13,4 +14,4 @@ abstract class SendNetworkRequestsViewModelBase with Store {
14 Future<void> loadLogs() async {
15 logs = MemoryProxyLogger.logs;
16 }
16 -}
\ No newline at end of file
17 +}
lib/view_model/dev/shared_preferences.dart
+1 -8
@@ -5,14 +5,7 @@ part 'shared_preferences.g.dart';
5
6 class DevSharedPreferences = DevSharedPreferencesBase with _$DevSharedPreferences;
7
8 -enum PreferenceType {
9 - unknown,
10 - string,
11 - int,
12 - double,
13 - bool,
14 - listString
15 -}
8 +enum PreferenceType { unknown, string, int, double, bool, listString }
9
10 abstract class DevSharedPreferencesBase with Store {
11 DevSharedPreferencesBase() {
lib/view_model/dev/socket_health_logs_view_model.dart
-1
@@ -6,7 +6,6 @@ part 'socket_health_logs_view_model.g.dart';
6 class SocketHealthLogsViewModel = SocketHealthLogsViewModelBase with _$SocketHealthLogsViewModel;
7
8 abstract class SocketHealthLogsViewModelBase with Store {
9 -
9 @observable
10 bool isLoading = false;
11
lib/view_model/edit_backup_password_view_model.dart
+6 -3
@@ -9,9 +9,12 @@ class EditBackupPasswordViewModel = EditBackupPasswordViewModelBase
9 with _$EditBackupPasswordViewModel;
10
11 abstract class EditBackupPasswordViewModelBase with Store {
12 - EditBackupPasswordViewModelBase(this.secureStorage,)
13 - : backupPassword = "",
14 - _originalPassword = ''{init();}
12 + EditBackupPasswordViewModelBase(
13 + this.secureStorage,
14 + ) : backupPassword = "",
15 + _originalPassword = '' {
16 + init();
17 + }
18
19 final SecureStorage secureStorage;
20
lib/view_model/exchange/exchange_trade_view_model.dart
+16 -22
@@ -50,7 +50,8 @@ abstract class ExchangeTradeViewModelBase with Store {
50 required this.feesViewModel,
51 required this.fiatConversionStore,
52 }) : trade = tradesStore.trade!,
53 - isSwapsXYZCanSendFromExternal = _checkIfSwapsXYZCanSendFromExternal(tradesStore.trade!, wallet),
53 + isSwapsXYZCanSendFromExternal =
54 + _checkIfSwapsXYZCanSendFromExternal(tradesStore.trade!, wallet),
55 items = ObservableList<ExchangeTradeItem>() {
56 setUpOutput();
57 switch (trade.provider) {
@@ -307,18 +308,17 @@ abstract class ExchangeTradeViewModelBase with Store {
308 items.add(
309 isSwapsXYZCanSendFromExternal
310 ? ExchangeTradeItem(
310 - title: S.current.send_to_this_address('${tradeFrom}', tagFrom) +
311 - ':',
312 - data: trade.inputAddress ?? '',
313 - isCopied: false,
314 - isReceiveDetail: false,
315 - isExternalSendDetail: true)
311 + title: S.current.send_to_this_address('${tradeFrom}', tagFrom) + ':',
312 + data: trade.inputAddress ?? '',
313 + isCopied: false,
314 + isReceiveDetail: false,
315 + isExternalSendDetail: true)
316 : ExchangeTradeItem(
317 - title: 'Smart contract call (no address required)',
318 - data: 'Wallet will execute a contract call. On-chain transaction',
319 - isCopied: false,
320 - isReceiveDetail: false,
321 - isExternalSendDetail: true),
317 + title: 'Smart contract call (no address required)',
318 + data: 'Wallet will execute a contract call. On-chain transaction',
319 + isCopied: false,
320 + isReceiveDetail: false,
321 + isExternalSendDetail: true),
322 );
323 }
324
@@ -369,8 +369,7 @@ abstract class ExchangeTradeViewModelBase with Store {
369 }
370
371 final canSend = _sameCurrency(tradeFrom, wallet.currency) ||
372 - (_sameCurrency(tradeFrom, CryptoCurrency.btcln) &&
373 - wallet.currency == CryptoCurrency.btc) ||
372 + (_sameCurrency(tradeFrom, CryptoCurrency.btcln) && wallet.currency == CryptoCurrency.btc) ||
373 trade.provider == ExchangeProviderDescription.xmrto ||
374 _isTokenBelongingToWallet(CryptoCurrency.eth) ||
375 _isTokenBelongingToWallet(CryptoCurrency.maticpoly) ||
@@ -408,13 +407,10 @@ abstract class ExchangeTradeViewModelBase with Store {
407 static bool _checkIfSwapsXYZCanSendFromExternal(Trade trade, WalletBase wallet) {
408 final provider = trade.provider;
409
411 - if (provider == ExchangeProviderDescription.swapsXyz &&
412 - isEVMCompatibleChain(wallet.type)) {
413 -
414 - if(trade.routerData != null && trade.routerData != '0x') {
410 + if (provider == ExchangeProviderDescription.swapsXyz && isEVMCompatibleChain(wallet.type)) {
411 + if (trade.routerData != null && trade.routerData != '0x') {
412 return false;
413 }
417 -
414 }
415 return true;
416 }
@@ -463,9 +459,7 @@ abstract class ExchangeTradeViewModelBase with Store {
459 case WalletType.monero:
460 return MoneroURI(address: inputAddress, amount: amount);
461 case WalletType.wownero:
466 - return MoneroURI(
467 - address: inputAddress,
468 - amount: amount);
462 + return MoneroURI(address: inputAddress, amount: amount);
463 case WalletType.litecoin:
464 return LitecoinURI(amount: amount, address: inputAddress);
465 case WalletType.nano:
lib/view_model/exchange/exchange_view_model.dart
+52 -41
@@ -175,7 +175,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
175 useSameWalletAddress(depositCurrency) ? wallet.walletAddresses.addressForExchange : '';
176
177 _disposers.add(reaction((_) => receiveAddress, (_) {
178 - if(!(tradeState is TradeIsCreatedSuccessfully)) {
178 + if (!(tradeState is TradeIsCreatedSuccessfully)) {
179 receiveAddressDisplayName = null;
180 }
181 }));
@@ -254,8 +254,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
254 c.title == depositCurrency.title &&
255 (c.tag == depositCurrency.tag || c.tag == depositCurrency.title),
256 );
257 - final balanceForCurrency =
258 - balanceCurrency != null ? wallet.balance[balanceCurrency] : null;
257 + final balanceForCurrency = balanceCurrency != null ? wallet.balance[balanceCurrency] : null;
258 if (depositCurrency == currency && balanceForCurrency != null) {
259 depositAvailableAmount =
260 _appStore.amountParsingProxy.asDisplayStringWithSymbol(balanceForCurrency.available);
@@ -281,7 +280,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
280
281 bool useSameWalletAddress(CryptoCurrency currency) =>
282 currency == wallet.currency ||
284 - (currency == CryptoCurrency.btcln && wallet.currency == CryptoCurrency.btc && wallet.isSoftwareWallet) ||
283 + (currency == CryptoCurrency.btcln &&
284 + wallet.currency == CryptoCurrency.btc &&
285 + wallet.isSoftwareWallet) ||
286 (currency.tag != null && currency.tag == wallet.currency.tag) ||
287 currency.tag == wallet.currency.title;
288
@@ -294,7 +295,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
295
296 bool get hideAddressAfterExchange =>
297 [WalletType.monero, WalletType.wownero, WalletType.zcash].contains(wallet.type) ||
297 - isElectrumWallet;
298 + isElectrumWallet;
299
300 bool _useTorOnly;
301 final ExchangeTemplateStore _exchangeTemplateStore;
@@ -465,7 +466,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
466 type = cryptoCurrencyOrTokenToWalletType(depositCurrency);
467 if (type == null) {
468 try {
468 - type = cryptoCurrencyOrTokenToWalletType(CryptoCurrency.fromString(depositCurrency.tag ?? ""));
469 + type =
470 + cryptoCurrencyOrTokenToWalletType(CryptoCurrency.fromString(depositCurrency.tag ?? ""));
471 } catch (_) {}
472 }
473
@@ -495,7 +497,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
497 @computed
498 String? get balanceDisplay {
499 CryptoCurrency? balanceCurrency;
498 - if (isEVMCompatibleChain(wallet.type) || wallet.type == WalletType.solana || wallet.type == WalletType.tron) {
500 + if (isEVMCompatibleChain(wallet.type) ||
501 + wallet.type == WalletType.solana ||
502 + wallet.type == WalletType.tron) {
503 balanceCurrency = wallet.balance.keys.firstWhereOrNull(
504 (c) =>
505 c.title == depositCurrency.title &&
@@ -523,7 +527,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
527 }
528
529 @computed
526 - bool get decentralizedExchangesPromptDismissed => _settingsStore.decentralizedExchangesPromptDismissed;
530 + bool get decentralizedExchangesPromptDismissed =>
531 + _settingsStore.decentralizedExchangesPromptDismissed;
532
533 @action
534 void dismissDecentralizedExchangesPrompt() {
@@ -707,7 +712,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
712 }
713 try {
714 return double.parse(depositAmount).toStringAsPrecision(digits);
710 - } catch(e) {
715 + } catch (e) {
716 return "0";
717 }
718 }
@@ -718,7 +723,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
723 }
724 try {
725 return double.parse(receiveAmount).toStringAsPrecision(digits);
721 - } catch(e) {
726 + } catch (e) {
727 return "0";
728 }
729 }
@@ -850,6 +855,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
855 _receiveAmount = null;
856 return;
857 }
858 +
859 /// For fixed-rate transactions, we don't want to recalculate receive amount
860 /// as it should remain exactly what the user set
861 if (isFixedRateMode) return;
@@ -1014,9 +1020,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1020 final entries = await Future.wait(futures);
1021 _providerLimits = Map.fromEntries(entries);
1022
1017 - _providerLimits.values
1018 - .whereType<Limits>()
1019 - .forEach((tempLimits) {
1023 + _providerLimits.values.whereType<Limits>().forEach((tempLimits) {
1024 if (lowestMin != null && (tempLimits.min ?? -1) < lowestMin!) {
1025 lowestMin = tempLimits.min;
1026 }
@@ -1072,10 +1076,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1076 ? '$depositAmountValue is not a valid amount for depositAmount'
1077 : '$receiveAmountValue is not a valid amount for receiveAmount';
1078
1075 - tradeState = TradeIsCreatedFailure(
1076 - title: S.current.trade_not_created,
1077 - error: invalidAmountError
1078 - );
1079 + tradeState =
1080 + TradeIsCreatedFailure(title: S.current.trade_not_created, error: invalidAmountError);
1081 return;
1082 }
1083
@@ -1085,8 +1087,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1087
1088 if (limits.min != null && amount != null && amount < limits.min!) {
1089 tradeState = TradeIsCreatedFailure(
1088 - title: S.current.trade_not_created,
1089 - error: S.current.amount_is_below_minimum_limit(limits.min!.toString()),
1090 + title: S.current.trade_not_created,
1091 + error: S.current.amount_is_below_minimum_limit(limits.min!.toString()),
1092 );
1093 return;
1094 }
@@ -1212,8 +1214,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1214 }
1215
1216 // Skip Swaps.xyz when sending from external
1215 - if (isSendFromExternal &&
1216 - provider.description == ExchangeProviderDescription.swapsXyz) {
1217 + if (isSendFromExternal && provider.description == ExchangeProviderDescription.swapsXyz) {
1218 printV('Skipping Swaps.xyz for external send');
1219 continue;
1220 }
@@ -1264,10 +1265,10 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1265 trade.walletId = wallet.id;
1266 trade.chainId = wallet.chainId;
1267 trade.fromWalletAddress = wallet.walletAddresses.address;
1267 - if(trade.from == null) {
1268 + if (trade.from == null) {
1269 trade.from = depositCurrency;
1270 }
1270 - if(trade.to == null) {
1271 + if (trade.to == null) {
1272 trade.to = receiveCurrency;
1273 }
1274
@@ -1385,7 +1386,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1386 } else if (wallet.type == WalletType.monero) {
1387 final amount = await unspentCoinsListViewModel.getSendingBalance(UnspentCoinType.any);
1388
1388 - changeDepositAmount(amount: wallet.currency.formatAmount(BigInt.from(amount)), isCanonical: true);
1389 + changeDepositAmount(
1390 + amount: wallet.currency.formatAmount(BigInt.from(amount)), isCanonical: true);
1391 } else if (isEVMCompatibleChain(wallet.type)) {
1392 final balanceCurrency = wallet.balance.keys.firstWhereOrNull(
1393 (currency) =>
@@ -1399,7 +1401,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1401 return;
1402 }
1403
1402 - final balanceAmount = _appStore.amountParsingProxy.asDisplayString(balanceForCurrency.available);
1404 + final balanceAmount =
1405 + _appStore.amountParsingProxy.asDisplayString(balanceForCurrency.available);
1406 final balanceDouble = double.tryParse(balanceAmount.replaceAll(',', '.')) ?? 0.0;
1407 if (balanceDouble <= 0) {
1408 changeDepositAmount(amount: wallet.currency.formatAmount(BigInt.zero), isCanonical: true);
@@ -1431,7 +1434,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1434 final feeWei = BigInt.parse(feeString);
1435 final amountAfterFeeWei = balanceWei > feeWei ? balanceWei - feeWei : BigInt.zero;
1436 changeDepositAmount(
1434 - amount: wallet.currency.formatAmount(amountAfterFeeWei), isCanonical: true);
1437 + amount: wallet.currency.formatAmount(amountAfterFeeWei), isCanonical: true);
1438 } catch (e) {
1439 printV('Error calculating send all for EVM: $e');
1440 changeDepositAmount(amount: balanceAmount, isCanonical: true);
@@ -1588,16 +1591,19 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1591 }
1592
1593 String? _addressTypeValidation(String refundAddress, String receiveAddress) {
1591 - final isRefundAddressSP = RegExp(AddressValidator.silentPaymentAddressPatternMainnet).hasMatch(refundAddress);
1594 + final isRefundAddressSP =
1595 + RegExp(AddressValidator.silentPaymentAddressPatternMainnet).hasMatch(refundAddress);
1596 if (isRefundAddressSP) return 'Silent Payment ${S.current.address_not_allowed_as_refund}';
1597
1594 - final isReceiveAddressSP = RegExp(AddressValidator.silentPaymentAddressPatternMainnet).hasMatch(receiveAddress);
1598 + final isReceiveAddressSP =
1599 + RegExp(AddressValidator.silentPaymentAddressPatternMainnet).hasMatch(receiveAddress);
1600 if (isReceiveAddressSP) return 'Silent Payment ${S.current.address_not_allowed_as_receive}';
1601
1602 final isRefundAddressMWEB = RegExp(AddressValidator.mWebAddressPattern).hasMatch(refundAddress);
1603 if (isRefundAddressMWEB) return 'MWEB ${S.current.address_not_allowed_as_refund}';
1604
1600 - final isReceiveAddressMWEB = RegExp(AddressValidator.mWebAddressPattern).hasMatch(receiveAddress);
1605 + final isReceiveAddressMWEB =
1606 + RegExp(AddressValidator.mWebAddressPattern).hasMatch(receiveAddress);
1607 if (isReceiveAddressMWEB) return 'MWEB ${S.current.address_not_allowed_as_receive}';
1608 return null;
1609 }
@@ -1678,7 +1684,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1684 @action
1685 void toggleForceDecentralizedExchanges() {
1686 _settingsStore.forceDecentralizedExchanges = !_settingsStore.forceDecentralizedExchanges;
1681 - if(forceDecentralizedExchanges) {
1687 + if (forceDecentralizedExchanges) {
1688 final providers = selectedProviders.toList();
1689 for (final provider in providers) {
1690 if (forceDecentralizedExchanges && provider.description.isCentralized) {
@@ -1686,13 +1692,12 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1692 }
1693 }
1694 } else {
1689 - for(final provider in providerList) {
1690 - if(!selectedProviders.contains(provider) && provider.description.isCentralized) {
1695 + for (final provider in providerList) {
1696 + if (!selectedProviders.contains(provider) && provider.description.isCentralized) {
1697 addExchangeProvider(provider);
1698 }
1699 }
1700 }
1695 -
1701 }
1702
1703 void _setAvailableProviders() {
@@ -1714,9 +1719,7 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1719 int get receiveMaxDigits => receiveCurrency.decimals;
1720
1721 Future<CreateTradeResult> isCanCreateTrade(Trade trade) async {
1717 -
1722 if (trade.provider == ExchangeProviderDescription.swapsXyz) {
1719 -
1723 final tradeFrom = trade.from;
1724
1725 if (tradeFrom == null) {
@@ -1726,7 +1729,8 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1729 );
1730 }
1731
1729 - final isNativeSupportedToken = walletTypes.contains(cryptoCurrencyOrTokenToWalletType(tradeFrom));
1732 + final isNativeSupportedToken =
1733 + walletTypes.contains(cryptoCurrencyOrTokenToWalletType(tradeFrom));
1734
1735 if (!isNativeSupportedToken) {
1736 bool _isEthToken() =>
@@ -1734,10 +1738,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1738
1739 bool _isPolygonToken() =>
1740 wallet.currency == CryptoCurrency.maticpoly &&
1737 - tradeFrom.tag == CryptoCurrency.maticpoly.tag;
1741 + tradeFrom.tag == CryptoCurrency.maticpoly.tag;
1742
1743 bool _isBaseToken() =>
1740 - wallet.currency == CryptoCurrency.baseEth && tradeFrom.tag == CryptoCurrency.baseEth.tag;
1744 + wallet.currency == CryptoCurrency.baseEth &&
1745 + tradeFrom.tag == CryptoCurrency.baseEth.tag;
1746
1747 bool _isTronToken() =>
1748 wallet.currency == CryptoCurrency.trx && tradeFrom.tag == CryptoCurrency.trx.title;
@@ -1751,14 +1756,20 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1756 bool isBscToken() =>
1757 wallet.currency == CryptoCurrency.bnb && tradeFrom.tag == CryptoCurrency.bnb.tag;
1758
1754 - if(!(_isEthToken() || _isPolygonToken() || _isBaseToken() || _isTronToken() || _isSplToken() || isArbitrumToken() || isBscToken())) {
1759 + if (!(_isEthToken() ||
1760 + _isPolygonToken() ||
1761 + _isBaseToken() ||
1762 + _isTronToken() ||
1763 + _isSplToken() ||
1764 + isArbitrumToken() ||
1765 + isBscToken())) {
1766 return CreateTradeResult(
1767 result: false,
1757 - errorMessage: 'This token isn’t supported on the current wallet/network for Swaps.xyz. Switch to a supported wallet or asset',
1768 + errorMessage:
1769 + 'This token isn’t supported on the current wallet/network for Swaps.xyz. Switch to a supported wallet or asset',
1770 );
1771 }
1772 }
1761 -
1773 }
1774
1775 if (trade.provider == ExchangeProviderDescription.thorChain) {
lib/view_model/hardware_wallet/bitbox_view_model.dart
+3 -2
@@ -25,7 +25,7 @@ abstract class BitboxViewModelBase extends HardwareWalletViewModel with Store {
25 BitboxViewModelBase() {
26 if (!Platform.isIOS && !isMoneroOnly) {
27 bitboxManager = sdk.BitboxManager();
28 - }
28 + }
29 }
30
31 @override
@@ -100,7 +100,8 @@ abstract class BitboxViewModelBase extends HardwareWalletViewModel with Store {
100 switch (wallet.type) {
101 case WalletType.bitcoin:
102 case WalletType.litecoin:
103 - return bitcoin!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
103 + return bitcoin!
104 + .setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
105 case WalletType.ethereum:
106 case WalletType.polygon:
107 return evm!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
lib/view_model/hardware_wallet/hardware_wallet_view_model.dart
-1
@@ -27,4 +27,3 @@ abstract class HardwareWalletViewModel {
27
28 String? interpretErrorCode(String error) => null;
29 }
30 -
lib/view_model/hardware_wallet/ledger_view_model.dart
+9 -11
@@ -120,14 +120,12 @@ abstract class LedgerViewModelBase extends HardwareWalletViewModel with Store {
120 } catch (_) {}
121 }
122
123 - final ledger = device.connectionType == HardwareWalletConnectionType.ble
124 - ? ledgerPlusBLE
125 - : ledgerPlusUSB;
123 + final ledger =
124 + device.connectionType == HardwareWalletConnectionType.ble ? ledgerPlusBLE : ledgerPlusUSB;
125
126 if (_connectionChangeSubscription == null) {
128 - _connectionChangeSubscription = ledger
129 - .deviceStateChanges(device.device.id)
130 - .listen(_connectionChangeListener);
127 + _connectionChangeSubscription =
128 + ledger.deviceStateChanges(device.device.id).listen(_connectionChangeListener);
129 }
130
131 try {
@@ -182,9 +180,11 @@ abstract class LedgerViewModelBase extends HardwareWalletViewModel with Store {
180 case WalletType.monero:
181 return monero!.setLedgerConnection(wallet, connection);
182 case WalletType.bitcoin:
185 - return bitcoin!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
183 + return bitcoin!
184 + .setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
185 case WalletType.litecoin:
187 - return bitcoin!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
186 + return bitcoin!
187 + .setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
188 case WalletType.ethereum:
189 case WalletType.polygon:
190 return evm!.setHardwareWalletService(wallet, await getHardwareWalletService(wallet.type));
@@ -210,7 +210,6 @@ abstract class LedgerViewModelBase extends HardwareWalletViewModel with Store {
210 }
211 }
212
213 -
213 @override
214 String? interpretErrorCode(String error) {
215 if (error.contains("Make sure no other program is communicating with the Ledger")) {
@@ -224,8 +223,7 @@ abstract class LedgerViewModelBase extends HardwareWalletViewModel with Store {
223 return S.current.ledger_error_tx_rejected_by_user;
224 } else if (errorCode.contains("5515")) {
225 return S.current.ledger_error_device_locked;
227 - } else
228 - if (["6e01", "6a87", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
226 + } else if (["6e01", "6a87", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
227 return S.current.ledger_error_wrong_app;
228 }
229 return null;
lib/view_model/hardware_wallet/trezor_connect_view_model.dart
+7 -10
@@ -142,12 +142,10 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S
142 isDismissible: false,
143 enableDrag: false,
144 useSafeArea: true,
145 - builder: (context) =>
146 - HardwareWalletProceedOnDeviceSheet(
147 - hardwareWalletType: hardwareWalletType,
148 - trezorConnectVM: this,
149 - onRetry: () => connectDevice(device, type, true)
150 - ),
145 + builder: (context) => HardwareWalletProceedOnDeviceSheet(
146 + hardwareWalletType: hardwareWalletType,
147 + trezorConnectVM: this,
148 + onRetry: () => connectDevice(device, type, true)),
149 );
150 }
151
@@ -234,7 +232,6 @@ abstract class TrezorConnectViewModelBase extends HardwareWalletViewModel with S
232 }
233 }
234
237 -
235 abstract class TrezorParingState {
236 static TrezorParingState initial = InitialTrezorParingState();
237 static TrezorParingState enterPin = EnterPinTrezorParingState();
@@ -243,11 +240,11 @@ abstract class TrezorParingState {
240 static TrezorParingState fail(String message) => FailTrezorParingState(message);
241 }
242
246 -class InitialTrezorParingState extends TrezorParingState {}
243 +class InitialTrezorParingState extends TrezorParingState {}
244
248 -class EnterPinTrezorParingState extends TrezorParingState {}
245 +class EnterPinTrezorParingState extends TrezorParingState {}
246
250 -class VerifyingPinTrezorParingState extends TrezorParingState {}
247 +class VerifyingPinTrezorParingState extends TrezorParingState {}
248
249 class SuccessTrezorParingState extends TrezorParingState {}
250
lib/view_model/integrations/deuro_view_model.dart
+3 -2
@@ -23,7 +23,8 @@ class DEuroViewModel = DEuroViewModelBase with _$DEuroViewModel;
23 abstract class DEuroViewModelBase with Store {
24 final AppStore _appStore;
25
26 - static Money get MIN_ACCRUED_INTEREST => Money(BigInt.parse("1000000000000"), CryptoCurrency.deuro);
26 + static Money get MIN_ACCRUED_INTEREST =>
27 + Money(BigInt.parse("1000000000000"), CryptoCurrency.deuro);
28
29 static Money get ZERO => Money.zero(CryptoCurrency.deuro);
30
@@ -178,7 +179,7 @@ abstract class DEuroViewModelBase with Store {
179 }
180
181 final amount = tryParseFixed(amountRaw, 18);
181 -
182 +
183 if (amount == BigInt.zero || amount == null) {
184 throw Exception("Invalid amount: amount cannot be zero");
185 }
lib/view_model/monero_account_list/account_list_item.dart
+1 -2
@@ -1,6 +1,5 @@
1 class AccountListItem {
2 - AccountListItem(
3 - {required this.label, required this.id, this.balance, this.isSelected = false});
2 + AccountListItem({required this.label, required this.id, this.balance, this.isSelected = false});
3
4 final String label;
5 final int id;
lib/view_model/monero_account_list/monero_account_edit_or_create_view_model.dart
+7 -16
@@ -21,7 +21,7 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store {
21 {required WalletBase wallet, AccountListItem? accountListItem})
22 : state = InitialExecutionState(),
23 isEdit = accountListItem != null,
24 - label = accountListItem?.label??'',
24 + label = accountListItem?.label ?? '',
25 _accountListItem = accountListItem,
26 _wallet = wallet;
27
@@ -76,14 +76,10 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store {
76 state = IsExecutingState();
77
78 if (_accountListItem != null) {
79 - await _moneroAccountList.setLabelAccount(
80 - _wallet,
81 - accountIndex: _accountListItem.id,
82 - label: label);
79 + await _moneroAccountList.setLabelAccount(_wallet,
80 + accountIndex: _accountListItem.id, label: label);
81 } else {
84 - await _moneroAccountList.addAccount(
85 - _wallet,
86 - label: label);
82 + await _moneroAccountList.addAccount(_wallet, label: label);
83 }
84
85 await _wallet.save();
@@ -98,14 +94,10 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store {
94 state = IsExecutingState();
95
96 if (_accountListItem != null) {
101 - await _wowneroAccountList?.setLabelAccount(
102 - _wallet,
103 - accountIndex: _accountListItem.id,
104 - label: label);
97 + await _wowneroAccountList?.setLabelAccount(_wallet,
98 + accountIndex: _accountListItem.id, label: label);
99 } else {
106 - await _wowneroAccountList?.addAccount(
107 - _wallet,
108 - label: label);
100 + await _wowneroAccountList?.addAccount(_wallet, label: label);
101 }
102
103 await _wallet.save();
@@ -114,5 +106,4 @@ abstract class MoneroAccountEditOrCreateViewModelBase with Store {
106 state = FailureState(e.toString());
107 }
108 }
117 -
109 }
lib/view_model/monero_account_list/monero_account_list_view_model.dart
+22 -21
@@ -10,11 +10,10 @@ import 'package:cake_wallet/monero/monero.dart';
10
11 part 'monero_account_list_view_model.g.dart';
12
13 -class MoneroAccountListViewModel = MoneroAccountListViewModelBase
14 - with _$MoneroAccountListViewModel;
13 +class MoneroAccountListViewModel = MoneroAccountListViewModelBase with _$MoneroAccountListViewModel;
14
15 abstract class MoneroAccountListViewModelBase with Store {
17 - MoneroAccountListViewModelBase(this._wallet,this.settingsStore) : scrollOffsetFromTop = 0;
16 + MoneroAccountListViewModelBase(this._wallet, this.settingsStore) : scrollOffsetFromTop = 0;
17
18 final SettingsStore settingsStore;
19
@@ -32,25 +31,27 @@ abstract class MoneroAccountListViewModelBase with Store {
31 List<AccountListItem> get accounts {
32 final hideBalance = settingsStore.balanceDisplayMode == BalanceDisplayMode.hiddenBalance;
33 if (_wallet.type == WalletType.monero) {
35 - return monero
36 - !.getAccountList(_wallet)
37 - .accounts.map((acc) => AccountListItem(
38 - label: acc.label,
39 - id: acc.id,
40 - balance: hideBalance ? '●●●●●●' : acc.balance,
41 - isSelected: acc.id == monero!.getCurrentAccount(_wallet).id))
42 - .toList();
34 + return monero!
35 + .getAccountList(_wallet)
36 + .accounts
37 + .map((acc) => AccountListItem(
38 + label: acc.label,
39 + id: acc.id,
40 + balance: hideBalance ? '●●●●●●' : acc.balance,
41 + isSelected: acc.id == monero!.getCurrentAccount(_wallet).id))
42 + .toList();
43 }
44
45 if (_wallet.type == WalletType.wownero) {
46 - return wownero
47 - !.getAccountList(_wallet)
48 - .accounts.map((acc) => AccountListItem(
49 - label: acc.label,
50 - id: acc.id,
51 - balance: hideBalance ? '●●●●●●' : acc.balance,
52 - isSelected: acc.id == wownero!.getCurrentAccount(_wallet).id))
53 - .toList();
46 + return wownero!
47 + .getAccountList(_wallet)
48 + .accounts
49 + .map((acc) => AccountListItem(
50 + label: acc.label,
51 + id: acc.id,
52 + balance: hideBalance ? '●●●●●●' : acc.balance,
53 + isSelected: acc.id == wownero!.getCurrentAccount(_wallet).id))
54 + .toList();
55 }
56
57 throw Exception('Unexpected wallet type: ${_wallet.type} for monero');
@@ -71,7 +72,7 @@ abstract class MoneroAccountListViewModelBase with Store {
72 item.id,
73 item.label,
74 item.balance,
74 - );
75 + );
76 }
77
78 if (_wallet.type == WalletType.wownero) {
@@ -80,7 +81,7 @@ abstract class MoneroAccountListViewModelBase with Store {
81 item.id,
82 item.label,
83 item.balance,
83 - );
84 + );
85 }
86 }
87 }
lib/view_model/node_list/node_create_or_edit_view_model.dart
+11 -20
@@ -12,28 +12,25 @@ import 'package:permission_handler/permission_handler.dart';
12
13 part 'node_create_or_edit_view_model.g.dart';
14
15 -class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase
16 - with _$NodeCreateOrEditViewModel;
15 +class NodeCreateOrEditViewModel = NodeCreateOrEditViewModelBase with _$NodeCreateOrEditViewModel;
16
17 abstract class NodeCreateOrEditViewModelBase with Store {
19 - NodeCreateOrEditViewModelBase(
20 - this.isPow, this.walletType, this._settingsStore, {this.editingNode})
18 + NodeCreateOrEditViewModelBase(this.isPow, this.walletType, this._settingsStore,
19 + {this.editingNode})
20 : state = InitialExecutionState(),
21 connectionState = InitialExecutionState(),
22 label = editingNode?.label ?? '',
23 address = editingNode?.uri.host.toString() ?? '',
24 path = editingNode?.path.toString() ?? '',
26 - port = (editingNode != null && editingNode.uri.hasPort)
27 - ? editingNode.uri.port.toString()
28 - : '',
25 + port =
26 + (editingNode != null && editingNode.uri.hasPort) ? editingNode.uri.port.toString() : '',
27 login = editingNode?.login ?? '',
28 password = editingNode?.password ?? '',
29 socksProxyAddress = editingNode?.socksProxyAddress ?? '',
30 trusted = editingNode?.trusted ?? false,
33 - isEnabledForAutoSwitching =
34 - editingNode?.isEnabledForAutoSwitching ?? false,
35 - useSocksProxy = editingNode?.socksProxyAddress != null &&
36 - editingNode!.socksProxyAddress!.isNotEmpty,
31 + isEnabledForAutoSwitching = editingNode?.isEnabledForAutoSwitching ?? false,
32 + useSocksProxy =
33 + editingNode?.socksProxyAddress != null && editingNode!.socksProxyAddress!.isNotEmpty,
34 useSSL = editingNode?.useSSL ?? false {}
35
36 final nodeLabelUIKey = 'node_label_row_key';
@@ -113,11 +110,9 @@ abstract class NodeCreateOrEditViewModelBase with Store {
110 @observable
111 bool isPow;
112
116 -
113 @computed
114 bool get isReady =>
119 - (address.isNotEmpty) ||
120 - walletType == WalletType.decred; // Allow an empty address.
115 + (address.isNotEmpty) || walletType == WalletType.decred; // Allow an empty address.
116
117 bool get hasAuthCredentials =>
118 walletType == WalletType.monero ||
@@ -240,8 +235,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
235 void setTrusted(bool val) => trusted = val;
236
237 @action
243 - void setIsEnabledForAutoSwitching(bool val) =>
244 - isEnabledForAutoSwitching = val;
238 + void setIsEnabledForAutoSwitching(bool val) => isEnabledForAutoSwitching = val;
239
240 @action
241 void setSocksProxy(bool val) => useSocksProxy = val;
@@ -276,7 +270,6 @@ abstract class NodeCreateOrEditViewModelBase with Store {
270 }
271
272 state = ExecutedSuccessfullyState();
279 -
273 } catch (e) {
274 state = FailureState(e.toString());
275 }
@@ -303,7 +296,6 @@ abstract class NodeCreateOrEditViewModelBase with Store {
296 }
297 }
298
306 -
299 @action
300 void setAsCurrent(Node node) => _settingsStore.nodes[walletType] = node;
301
@@ -320,8 +312,7 @@ abstract class NodeCreateOrEditViewModelBase with Store {
312 throw Exception('Unexpected scan QR code value: value is empty');
313 }
314
323 - if (code.startsWith("monero_node:"))
324 - code = code.replaceFirst("monero_node:", "tcp://");
315 + if (code.startsWith("monero_node:")) code = code.replaceFirst("monero_node:", "tcp://");
316 if (!code.contains('://')) code = 'tcp://$code';
317
318 final uri = Uri.tryParse(code);
lib/view_model/node_list/node_list_view_model.dart
+14 -20
@@ -16,7 +16,6 @@ import 'package:cake_wallet/reactions/wallet_connect.dart';
16
17 part 'node_list_view_model.g.dart';
18
19 -
19 class NodeSpeed {
20 final String iconPath;
21 final String darkIconPath;
@@ -24,21 +23,20 @@ class NodeSpeed {
23 // fraction of best node ping needed to be classified as this speed.
24 final double treshold;
25
27 - const NodeSpeed._(this.iconPath, this.darkIconPath, this.treshold);
26 + const NodeSpeed._(this.iconPath, this.darkIconPath, this.treshold);
27
29 - static const disconnected = NodeSpeed._(
30 - "assets/new-ui/node_speed_badges/disconnected.svg", "assets/new-ui/node_speed_badges/disconnected-dark.svg", 0);
31 - static const slow = NodeSpeed._(
32 - "assets/new-ui/node_speed_badges/slow.svg", "assets/new-ui/node_speed_badges/slow-dark.svg", 0);
33 - static const medium = NodeSpeed._(
34 - "assets/new-ui/node_speed_badges/medium.svg", "assets/new-ui/node_speed_badges/medium.svg", 0.5);
28 + static const disconnected = NodeSpeed._("assets/new-ui/node_speed_badges/disconnected.svg",
29 + "assets/new-ui/node_speed_badges/disconnected-dark.svg", 0);
30 + static const slow = NodeSpeed._("assets/new-ui/node_speed_badges/slow.svg",
31 + "assets/new-ui/node_speed_badges/slow-dark.svg", 0);
32 + static const medium = NodeSpeed._("assets/new-ui/node_speed_badges/medium.svg",
33 + "assets/new-ui/node_speed_badges/medium.svg", 0.5);
34 static const fast = NodeSpeed._(
35 "assets/new-ui/node_speed_badges/fast.svg", "assets/new-ui/node_speed_badges/fast.svg", 0.8);
36
37 static const all = [fast, medium, slow, disconnected];
38 }
39
41 -
40 class NodeListViewModel = NodeListViewModelBase with _$NodeListViewModel;
41
42 abstract class NodeListViewModelBase with Store {
@@ -63,7 +61,6 @@ abstract class NodeListViewModelBase with Store {
61 bindNodes();
62 });
63 }
66 -
64
65 @computed
66 Node get currentNode {
@@ -103,9 +100,8 @@ abstract class NodeListViewModelBase with Store {
100 final bool isPow;
101 final ObservableMap<String, int> _nodeSpeeds;
102
106 -
103 @computed
108 - List<Node> get nonCurrentNodes => nodes.where((item)=>item != currentNode).toList();
104 + List<Node> get nonCurrentNodes => nodes.where((item) => item != currentNode).toList();
105
106 @observable
107 bool isTestingNodeSpeed = false;
@@ -117,9 +113,8 @@ abstract class NodeListViewModelBase with Store {
113 final nodes = this.nodes.toList();
114 await Future.wait(nodes.map((node) async {
115 final sw = Stopwatch()..start();
120 - final res = await node
121 - .requestNode()
122 - .timeout(const Duration(seconds: 10), onTimeout: () => false);
116 + final res =
117 + await node.requestNode().timeout(const Duration(seconds: 10), onTimeout: () => false);
118 sw.stop();
119 if (res) {
120 _nodeSpeeds[node.uriRaw] = sw.elapsedMilliseconds;
@@ -163,7 +158,6 @@ abstract class NodeListViewModelBase with Store {
158 Node node;
159 if (walletType == WalletType.bitcoin && wallet.isTestnet) {
160 node = (await getBitcoinTestnetDefaultElectrumServer())!;
166 -
161 } else if (isEVMCompatibleChain(walletType)) {
162 final chainId = evm!.getSelectedChainId(wallet);
163 if (chainId != null) {
@@ -205,12 +199,11 @@ abstract class NodeListViewModelBase with Store {
199 }
200
201 // For non-EVM wallets, use the wallet type directly
208 - if(isPow) {
202 + if (isPow) {
203 settingsStore.powNodes[walletType] = node;
204 } else {
205 settingsStore.nodes[walletType] = node;
206 }
213 -
207 }
208
209 @action
@@ -235,7 +228,8 @@ abstract class NodeListViewModelBase with Store {
228 }
229
230 // For non-EVM wallets, use the wallet type directly
238 - nodes.addAll(isPow ? await Node.getAllForWalletTypePow(walletType) : await Node.getAllForWalletType(walletType));
239 -
231 + nodes.addAll(isPow
232 + ? await Node.getAllForWalletTypePow(walletType)
233 + : await Node.getAllForWalletType(walletType));
234 }
235 }
lib/view_model/node_list/pow_node_list_view_model.dart
+1
@@ -0,0 +1 @@
1 +
lib/view_model/payjoin_details_view_model.dart
+2 -4
@@ -18,8 +18,7 @@ import 'package:url_launcher/url_launcher.dart';
18
19 part 'payjoin_details_view_model.g.dart';
20
21 -class PayjoinDetailsViewModel = PayjoinDetailsViewModelBase
22 - with _$PayjoinDetailsViewModel;
21 +class PayjoinDetailsViewModel = PayjoinDetailsViewModelBase with _$PayjoinDetailsViewModel;
22
23 abstract class PayjoinDetailsViewModelBase with Store {
24 PayjoinDetailsViewModelBase(
@@ -61,8 +60,7 @@ abstract class PayjoinDetailsViewModelBase with Store {
60 ),
61 TradeDetailsListCardItem(
62 id: "${payjoinSession.isSenderSession ? S.current.outgoing : S.current.incoming} Payjoin",
64 - createdAt:
65 - dateFormat.format(payjoinSession.inProgressSince!).toString(),
63 + createdAt: dateFormat.format(payjoinSession.inProgressSince!).toString(),
64 pair:
65 '${bitcoin!.formatterBitcoinAmountToString(amount: payjoinSession.amount.toInt())} BTC',
66 onTap: (_) {},
lib/view_model/rescan_view_model.dart
+1 -1
@@ -31,7 +31,7 @@ abstract class RescanViewModelBase with Store {
31
32 @computed
33 bool get isMwebScan => wallet.type == WalletType.litecoin;
34 -
34 +
35 Future<bool> get isBitcoinMempoolAPIEnabled async =>
36 wallet.type == WalletType.bitcoin && await bitcoin!.checkIfMempoolAPIIsEnabled(wallet);
37
lib/view_model/restore/restore_mode.dart
+1 -1
@@ -1 +1 @@
1 -enum WalletRestoreMode { seed, keys, txids }
\ No newline at end of file
1 +enum WalletRestoreMode { seed, keys, txids }
lib/view_model/restore_from_backup_view_model.dart
+3 -2
@@ -32,7 +32,7 @@ abstract class RestoreFromBackupViewModelBase with Store {
32 void reset() => filePath = '';
33
34 @action
35 - Future<void> import(String password,{bool checkBackupApp = true}) async {
35 + Future<void> import(String password, {bool checkBackupApp = true}) async {
36 try {
37 state = IsExecutingState();
38
@@ -49,7 +49,8 @@ abstract class RestoreFromBackupViewModelBase with Store {
49 rethrow;
50 } catch (e, s) {
51 if (e.toString().contains("unknown_backup_version")) {
52 - state = FailureState('This is not a valid backup file, please make sure you have selected the correct one');
52 + state = FailureState(
53 + 'This is not a valid backup file, please make sure you have selected the correct one');
54 } else {
55 state = FailureState(e.toString() + "\n" + s.toString());
56 }
lib/view_model/seed_settings_view_model.dart
+2 -1
@@ -14,7 +14,8 @@ abstract class SeedSettingsViewModelBase with Store {
14 MoneroSeedType get moneroSeedType => _appStore.settingsStore.moneroSeedType;
15
16 @action
17 - void setMoneroSeedType(MoneroSeedType seedType) => _appStore.settingsStore.moneroSeedType = seedType;
17 + void setMoneroSeedType(MoneroSeedType seedType) =>
18 + _appStore.settingsStore.moneroSeedType = seedType;
19
20 @computed
21 BitcoinSeedType get bitcoinSeedType => _appStore.settingsStore.bitcoinSeedType;
lib/view_model/send/output.dart
+8 -7
@@ -37,8 +37,7 @@ class Output = OutputBase with _$Output;
37
38 abstract class OutputBase with Store {
39 OutputBase(this._wallet, this._appStore, this._fiatConversationStore, this.cryptoCurrencyHandler)
40 - :
41 - key = UniqueKey(),
40 + : key = UniqueKey(),
41 sendAll = false,
42 cryptoAmount = '',
43 cryptoFullBalance = '',
@@ -57,7 +56,6 @@ abstract class OutputBase with Store {
56 });
57 }
58
60 -
59 Key key;
60
61 bool get useSatoshi => _appStore.amountParsingProxy.useSatoshi(cryptoCurrencyHandler());
@@ -98,7 +96,6 @@ abstract class OutputBase with Store {
96 @observable
97 String extractedAddress;
98
101 -
99 @computed
100 bool get isParsedAddress =>
101 parsedAddress.addressSource != AddressSource.notParsed && parsedAddress.handle.isNotEmpty;
@@ -172,9 +169,11 @@ abstract class OutputBase with Store {
169 break;
170 case WalletType.tron:
171 if (cryptoCurrencyHandler() == CryptoCurrency.trx) {
175 - estimatedFee = tron!.getTronNativeEstimatedFee(_wallet) ?? Money.zero(CryptoCurrency.trx);
172 + estimatedFee =
173 + tron!.getTronNativeEstimatedFee(_wallet) ?? Money.zero(CryptoCurrency.trx);
174 } else {
177 - estimatedFee = tron!.getTronTRC20EstimatedFee(_wallet) ?? Money.zero(CryptoCurrency.trx);
175 + estimatedFee =
176 + tron!.getTronTRC20EstimatedFee(_wallet) ?? Money.zero(CryptoCurrency.trx);
177 }
178 break;
179
@@ -200,7 +199,8 @@ abstract class OutputBase with Store {
199 ? evm!.getEVMNativeEstimatedFee(_wallet)
200 : evm!.getEVMERC20EstimatedFee(_wallet);
201
203 - estimatedFee = Money(BigInt.parse(fee ?? '0.0'), walletTypeToCryptoCurrency(_wallet.type));
202 + estimatedFee =
203 + Money(BigInt.parse(fee ?? '0.0'), walletTypeToCryptoCurrency(_wallet.type));
204 break;
205
206 /// end EVMs
@@ -293,6 +293,7 @@ abstract class OutputBase with Store {
293 }
294
295 @action
296 +
297 /// [setCryptoAmount] always takes in the canonical representation eg. Bitcoin and not Sats
298 void setCryptoAmount(String amount) {
299 if (amount.toUpperCase() != S.current.all) sendAll = false;
lib/view_model/send/send_template_view_model.dart
+1 -3
@@ -35,9 +35,7 @@ abstract class SendTemplateViewModelBase with Store {
35 @action
36 void addRecipient() {
37 recipients.add(TemplateViewModel(
38 - wallet: _wallet,
39 - appStore: _appStore,
40 - fiatConversationStore: _fiatConversationStore));
38 + wallet: _wallet, appStore: _appStore, fiatConversationStore: _fiatConversationStore));
39 }
40
41 @action
lib/view_model/send/send_view_model.dart
+60 -84
@@ -85,8 +85,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
85 currencies = wallet.balance.keys.toList();
86 selectedCryptoCurrency =
87 coinTypeToSpendFrom == UnspentCoinType.lightning ? CryptoCurrency.btcln : wallet.currency;
88 - hasMultipleTokens = isEVMWallet ||
89 - [WalletType.solana, WalletType.tron, WalletType.zano].contains(wallet.type);
88 + hasMultipleTokens =
89 + isEVMWallet || [WalletType.solana, WalletType.tron, WalletType.zano].contains(wallet.type);
90
91 for (final output in outputs) {
92 output.updateWallet(wallet);
@@ -195,7 +195,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
195 if (isValidAddress) return null;
196 }
197
198 -
198 final results = await _adrResService.resolve(
199 query: query,
200 wallet: wallet,
@@ -411,9 +410,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
410
411 final sp = RegExp(AddressValidator.silentPaymentAddressPatternMainnet);
412
414 - final address = output.extractedAddress.isNotEmpty
415 - ? output.extractedAddress
416 - : output.address;
413 + final address = output.extractedAddress.isNotEmpty ? output.extractedAddress : output.address;
414
415 return sp.hasMatch(address);
416 }
@@ -467,7 +464,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
464 FiatCurrency get fiatCurrency => _settingsStore.fiatCurrency;
465
466 set fiatCurrency(FiatCurrency value) {
470 - _settingsStore.fiatCurrency = value;
467 + _settingsStore.fiatCurrency = value;
468 }
469
470 List<FiatCurrency> fiatCurrencies;
@@ -530,7 +527,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
527
528 @computed
529 TransactionInfo? get transactionInfo {
533 - if(isEVMCompatibleChain(walletType)) {
530 + if (isEVMCompatibleChain(walletType)) {
531 return wallet.transactionHistory.transactions[pendingTransaction?.evmTxHashFromRawHex];
532 }
533 if (walletType == WalletType.monero) {
@@ -633,7 +630,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
630 clearOutputs();
631
632 outputs.first.address = paymentRequest.address;
636 - outputs.first.parsedAddress = ParsedAddress(parsedAddressByCurrencyMap: {currency:paymentRequest.address}, handle: ocpRequest!.receiverName);
633 + outputs.first.parsedAddress = ParsedAddress(
634 + parsedAddressByCurrencyMap: {currency: paymentRequest.address},
635 + handle: ocpRequest!.receiverName);
636 outputs.first.setCryptoAmount(paymentRequest.amount);
637 outputs.first.note = ocpRequest!.receiverName;
638
@@ -694,13 +693,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
693 final routerTo = trade.inputAddress;
694 final routerData = trade.routerData;
695
697 -
696 if (routerData != null && routerData != '0x') {
697 final tokenContract = (trade.sourceTokenAddress ?? '').toLowerCase();
700 - final priority = _settingsStore.getPriority(
701 - walletType, chainId: selectedChainId);
702 - final routerValueWei = BigInt.tryParse(trade.routerValue ?? '0') ??
703 - BigInt.zero;
698 + final priority = _settingsStore.getPriority(walletType, chainId: selectedChainId);
699 + final routerValueWei = BigInt.tryParse(trade.routerValue ?? '0') ?? BigInt.zero;
700
701 if (routerTo == null || routerTo.isEmpty) {
702 state = FailureState('Invalid router address');
@@ -730,33 +726,26 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
726
727 // Smart Swap (Requires Approval)
728 if (selector == swapAndExecuteSig) {
733 - final requiredAmount = BigInt.tryParse(
734 - (trade.sourceTokenAmountRaw ?? '0').replaceAll('n', '')) ??
735 - BigInt.zero;
736 -
737 - final needsApproval = tokenContract.isNotEmpty &&
738 - requiredAmount > BigInt.zero
739 - ? await evm!.isApprovalRequired(
740 - wallet, tokenContract, routerTo, requiredAmount)
729 + final requiredAmount =
730 + BigInt.tryParse((trade.sourceTokenAmountRaw ?? '0').replaceAll('n', '')) ??
731 + BigInt.zero;
732 +
733 + final needsApproval = tokenContract.isNotEmpty && requiredAmount > BigInt.zero
734 + ? await evm!.isApprovalRequired(wallet, tokenContract, routerTo, requiredAmount)
735 : false;
736
737 printV(
744 - '[Swaps.xyz sending flow] Approval required: $needsApproval for token ${trade
745 - .from?.title} ${trade.from?.tag ??
746 - ''} with amount $requiredAmount');
738 + '[Swaps.xyz sending flow] Approval required: $needsApproval for token ${trade.from?.title} ${trade.from?.tag ?? ''} with amount $requiredAmount');
739
740 if (needsApproval) {
741 // USDT Approval Flow (Special Case). We must reset allowance to 0 first.
742 final isUSDTMainnet = selectedChainId == 1 &&
751 - tokenContract.toLowerCase() ==
752 - '0xdac17f958d2ee523a2206206994597c13d831ec7';
743 + tokenContract.toLowerCase() == '0xdac17f958d2ee523a2206206994597c13d831ec7';
744
745 if (isUSDTMainnet) {
755 - final currentAllowance = await evm!.getAllowance(
756 - wallet, tokenContract, routerTo);
746 + final currentAllowance = await evm!.getAllowance(wallet, tokenContract, routerTo);
747
758 - if (currentAllowance != null &&
759 - currentAllowance > BigInt.zero) {
748 + if (currentAllowance != null && currentAllowance > BigInt.zero) {
749 printV(
750 '[Swaps.xyz sending flow] currentAllowance USDT: $currentAllowance. Resetting to 0 before setting new allowance.');
751
@@ -766,8 +755,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
755 requiredAmount: BigInt.zero,
756 // Approve 0
757 sourceTokenDecimals: trade.sourceTokenDecimals,
769 - priority: priority
770 - );
758 + priority: priority);
759
760 if (resetTx != null) {
761 await resetTx.commit();
@@ -780,8 +768,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
768 );
769
770 if (!resetConfirmed) {
783 - state = FailureState(
784 - 'Failed to reset USDT allowance. Please try again.');
771 + state = FailureState('Failed to reset USDT allowance. Please try again.');
772 return null;
773 }
774 printV(
@@ -796,8 +783,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
783 tokenContract: tokenContract,
784 requiredAmount: requiredAmount,
785 sourceTokenDecimals: trade.sourceTokenDecimals,
799 - priority: priority
800 - );
786 + priority: priority);
787
788 if (approvalTx == null) {
789 state = FailureState('Failed to build approval transaction');
@@ -808,8 +794,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
794
795 try {
796 printV(
811 - '[Swaps.xyz sending flow] Submitting approval transaction for token ${trade
812 - .from?.title} ${trade.from?.tag ?? ''} ');
797 + '[Swaps.xyz sending flow] Submitting approval transaction for token ${trade.from?.title} ${trade.from?.tag ?? ''} ');
798 await approvalTx.commit();
799
800 // Wait for the approval to be mined on-chain
@@ -827,10 +812,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
812 printV(
813 '[Swaps.xyz sending flow] Approval transaction confirmed on-chain. Proceeding with swap execution.');
814 } catch (e, s) {
830 - printV(
831 - '[Swaps.xyz sending flow] Approval transaction error: $e\n$s');
832 - state = FailureState(
833 - translateErrorMessage(e, wallet.type, wallet.currency));
815 + printV('[Swaps.xyz sending flow] Approval transaction error: $e\n$s');
816 + state = FailureState(translateErrorMessage(e, wallet.type, wallet.currency));
817 return null;
818 }
819 }
@@ -859,8 +842,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
842 } catch (e, s) {
843 printV('Swaps.xyz transaction error: $e\n$s');
844 state = FailureState(
862 - 'Failed to create Swaps.xyz transaction - ${translateErrorMessage(
863 - e, wallet.type, wallet.currency)}');
845 + 'Failed to create Swaps.xyz transaction - ${translateErrorMessage(e, wallet.type, wallet.currency)}');
846 return null;
847 }
848 }
@@ -902,14 +884,12 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
884
885 // Regular flow
886
905 -
887 final isSendAll = outputs.any((output) => output.sendAll);
907 -
888 +
889 if (!isSendAll) {
909 - final estimateTxAmountDouble = outputs.fold<double>(0, (acc, output) =>
910 - acc + (double.tryParse(output.cryptoAmount) ?? 0));
911 - if (estimateTxAmountDouble <= 0) throw Exception(
912 - 'Amount must be greater than 0');
890 + final estimateTxAmountDouble = outputs.fold<double>(
891 + 0, (acc, output) => acc + (double.tryParse(output.cryptoAmount) ?? 0));
892 + if (estimateTxAmountDouble <= 0) throw Exception('Amount must be greater than 0');
893 }
894
895 pendingTransaction = await wallet.createTransaction(_credentials(provider));
@@ -942,7 +922,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
922 }
923 }
924
945 -
925 if (wallet.type == WalletType.bitcoin) {
926 final updatedOutputs = bitcoin!.updateOutputs(pendingTransaction!, outputs);
927
@@ -1030,7 +1009,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1009 throw Exception("Pending transaction doesn't exist. It should not be happened.");
1010 }
1011
1033 -
1012 try {
1013 state = wallet.isHardwareWallet && walletType == WalletType.monero
1014 ? IsAwaitingDeviceResponseState()
@@ -1124,7 +1102,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1102 }
1103
1104 // Immediate transaction update for EVM chains, Tron, and Nano
1127 - if (isEVMWallet || [WalletType.bitcoin, WalletType.solana, WalletType.tron, WalletType.nano].contains(walletType)) {
1105 + if (isEVMWallet ||
1106 + [WalletType.bitcoin, WalletType.solana, WalletType.tron, WalletType.nano]
1107 + .contains(walletType)) {
1108 Future.delayed(Duration(seconds: 4), () async {
1109 try {
1110 await Future.wait([
@@ -1140,7 +1120,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1120 // FIXME(malik) ideally, this should be done wallet-side.
1121 // it is required because evm, solana and tron don't actually save the transaction info when you send something.
1122 // instead, they rely on the tx to eventually get fetched at sync time, which can take a while
1143 - if(isEVMWallet) {
1123 + if (isEVMWallet) {
1124 wallet.transactionHistory.addOne(evm!.getTransactionInfo(
1125 id: pendingTransaction!.evmTxHashFromRawHex!,
1126 height: 0,
@@ -1154,8 +1134,8 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1134 chainId: wallet.chainId ?? 0,
1135 ));
1136 }
1157 -
1158 - if(walletType == WalletType.solana) {
1137 +
1138 + if (walletType == WalletType.solana) {
1139 wallet.transactionHistory.addOne(solana!.getTransactionInfo(
1140 id: pendingTransaction!.id,
1141 blockTime: DateTime.now(),
@@ -1211,7 +1191,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1191 Future<void> updateWalletBalance() async => await wallet.updateBalance();
1192
1193 Future<void> _addTransactionDescription() async {
1214 - String address = outputs.fold('', (acc, value) {
1194 + String address = outputs.fold('', (acc, value) {
1195 final canonical = value.extractedAddress.trim().isNotEmpty
1196 ? value.extractedAddress.trim()
1197 : value.address.trim();
@@ -1360,15 +1340,15 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1340 @computed
1341 int get maxMemoLength => _maxMemoLengths[wallet.type] ?? 9999999;
1342
1363 -
1343 ContactRecord? newContactAddress() {
1344 final Set<String> contactAddresses =
1345 Set.from(contactListViewModel.contacts.map((contact) => contact.address))
1346 ..addAll(contactListViewModel.walletContacts.map((contact) => contact.address));
1347
1348 for (final output in outputs) {
1370 - final address =
1371 - output.isParsedAddress ? output.parsedAddress.parsedAddressByCurrencyMap[selectedCryptoCurrency] ?? '' : output.address;
1349 + final address = output.isParsedAddress
1350 + ? output.parsedAddress.parsedAddressByCurrencyMap[selectedCryptoCurrency] ?? ''
1351 + : output.address;
1352
1353 if (address.isNotEmpty &&
1354 !contactAddresses.contains(address) &&
@@ -1400,14 +1380,16 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1380 int attempts = 0;
1381 const int maxAttempts = 30; // ~60 seconds
1382
1403 - printV('[Swaps.xyz sending flow] Starting allowance check. Target: $requiredAmount (Exact match: $waitForExactMatch)');
1383 + printV(
1384 + '[Swaps.xyz sending flow] Starting allowance check. Target: $requiredAmount (Exact match: $waitForExactMatch)');
1385
1386 while (attempts < maxAttempts) {
1387 try {
1388 final currentAllowance = await evm!.getAllowance(wallet, tokenContract, spender);
1389
1390 if (currentAllowance != null) {
1410 - printV('[Swaps.xyz sending flow] Current Allowance: $currentAllowance / Target: $requiredAmount');
1391 + printV(
1392 + '[Swaps.xyz sending flow] Current Allowance: $currentAllowance / Target: $requiredAmount');
1393
1394 if (waitForExactMatch) {
1395 // For Reset (Target 0): We need it to be exactly 0 (or less, though it can't be negative)
@@ -1443,17 +1425,16 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1425 required TransactionPriority? priority,
1426 int? sourceTokenDecimals,
1427 }) async {
1446 -
1428 final erc20Token = wallet.balance.keys.whereType<Erc20Token>().firstWhere(
1429 (t) => t.contractAddress.toLowerCase() == tokenContract.toLowerCase(),
1449 - orElse: () => Erc20Token(
1450 - name: '',
1451 - symbol: '',
1452 - contractAddress: tokenContract,
1453 - decimal: sourceTokenDecimals ?? 18,
1454 - enabled: true,
1455 - ),
1456 - );
1430 + orElse: () => Erc20Token(
1431 + name: '',
1432 + symbol: '',
1433 + contractAddress: tokenContract,
1434 + decimal: sourceTokenDecimals ?? 18,
1435 + enabled: true,
1436 + ),
1437 + );
1438
1439 return await evm!.createTokenApproval(
1440 wallet,
@@ -1461,7 +1442,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1442 spender,
1443 priority,
1444 useBlinkProtection:
1464 - canSupportBlinkProtection(selectedChainId) ? _settingsStore.useBlinkProtection : false,
1445 + canSupportBlinkProtection(selectedChainId) ? _settingsStore.useBlinkProtection : false,
1446 );
1447 }
1448
@@ -1646,9 +1627,9 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1627 return S.current.tx_invalid_input;
1628 }
1629
1649 - if(wallet.type == WalletType.bitcoin) {
1630 + if (wallet.type == WalletType.bitcoin) {
1631 final lnError = getLightningErrorMessage(error);
1651 - if(lnError != null) return lnError;
1632 + if (lnError != null) return lnError;
1633 }
1634
1635 return errorMessage;
@@ -1656,12 +1637,10 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1637
1638 String? getLightningErrorMessage(Object error) {
1639 // TODO add more patterns
1659 - Map<String, String> errorPatterns = {
1660 - "insufficient funds": S.current.insufficient_funds_for_tx
1661 - };
1640 + Map<String, String> errorPatterns = {"insufficient funds": S.current.insufficient_funds_for_tx};
1641
1663 - for(final pattern in errorPatterns.keys) {
1664 - if(error.toString().contains(pattern)) return errorPatterns[pattern]!;
1642 + for (final pattern in errorPatterns.keys) {
1643 + if (error.toString().contains(pattern)) return errorPatterns[pattern]!;
1644 }
1645
1646 return null;
@@ -1677,7 +1656,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1656
1657 Future<void> registerSwapsXyzTransaction(Trade trade) async {
1658 try {
1680 -
1659 // register only for vmId is alt-vm or bridgeId is alt-vm (trade.needToRegisterInSwapXyz)
1660 final needToRegister = trade.needToRegisterInSwapXyz ?? false;
1661 if (!needToRegister) return;
@@ -1688,9 +1666,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
1666 return;
1667 }
1668
1691 - final txHash = pendingTransaction?.evmTxHashFromRawHex
1692 - ?? pendingTransaction?.id
1693 - ?? '';
1669 + final txHash = pendingTransaction?.evmTxHashFromRawHex ?? pendingTransaction?.id ?? '';
1670
1671 if (txHash.isEmpty) {
1672 printV('SwapsXyz: transaction register: skipped (txHash empty)');
lib/view_model/send/send_view_model_state.dart
+3
@@ -1,6 +1,9 @@
1 import 'package:cake_wallet/core/execution_state.dart';
2
3 class IsDeviceSigningResponseState extends IsExecutingState {}
4 +
5 class IsAwaitingDeviceResponseState extends IsExecutingState {}
6 +
7 class TransactionCommitting extends ExecutionState {}
8 +
9 class TransactionCommitted extends ExecutionState {}
lib/view_model/settings/connection_sync_view_model.dart
+4 -2
@@ -232,7 +232,6 @@ abstract class ConnectionSyncViewModelBase with Store {
232 @computed
233 bool get canUseTronGrid => _wallet.type == WalletType.tron;
234
235 -
235 @action
236 void setUseMempoolFeeAPI(bool value) => _settingsStore.useMempoolFeeAPI = value;
237
@@ -249,7 +248,10 @@ abstract class ConnectionSyncViewModelBase with Store {
248 @action
249 void setUseBlinkProtection(bool value) => _settingsStore.useBlinkProtection = value;
250
252 - bool get hasRescan => _wallet.hasRescan && _wallet.type != WalletType.bitcoin && _wallet.type != WalletType.litecoin;
251 + bool get hasRescan =>
252 + _wallet.hasRescan &&
253 + _wallet.type != WalletType.bitcoin &&
254 + _wallet.type != WalletType.litecoin;
255
256 @action
257 void setUseEtherscan(bool value) {
lib/view_model/settings/display_settings_view_model.dart
+3 -2
@@ -59,7 +59,7 @@ abstract class DisplaySettingsViewModelBase with Store {
59
60 @computed
61 bool get showAddressBookPopup => _settingsStore.showAddressBookPopupEnabled;
62 -
62 +
63 @computed
64 bool get showZcashCard => _settingsStore.showZcashMissingFundsCard;
65
@@ -126,7 +126,8 @@ abstract class DisplaySettingsViewModelBase with Store {
126 bool get showZcashCardSetting => _appStore.wallet?.type == WalletType.zcash;
127
128 @action
129 - void setDisplayAmountsInSatoshi(BitcoinAmountDisplayMode value) => _settingsStore.displayAmountsInSatoshi = value;
129 + void setDisplayAmountsInSatoshi(BitcoinAmountDisplayMode value) =>
130 + _settingsStore.displayAmountsInSatoshi = value;
131
132 @action
133 void setShowZcashCard(bool value) => _settingsStore.showZcashMissingFundsCard = value;
lib/view_model/settings/link_list_item.dart
+6 -6
@@ -5,11 +5,11 @@ import 'package:flutter/material.dart';
5 class LinkListItem extends SettingsListItem {
6 LinkListItem(
7 {required String title,
8 - required this.link,
9 - required this.linkTitle,
10 - this.icon,
11 - this.lightIcon,
12 - this.hasIconColor = false})
8 + required this.link,
9 + required this.linkTitle,
10 + this.icon,
11 + this.lightIcon,
12 + this.hasIconColor = false})
13 : super(title);
14
15 final String? icon;
@@ -17,4 +17,4 @@ class LinkListItem extends SettingsListItem {
17 final String link;
18 final String linkTitle;
19 final bool hasIconColor;
20 -}
\ No newline at end of file
20 +}
lib/view_model/settings/other_settings_view_model.dart
+9 -9
@@ -66,18 +66,18 @@ abstract class OtherSettingsViewModelBase with Store {
66 void setAutoGenerateSubaddresses(bool value) {
67 _wallet.isEnabledAutoGenerateSubaddress = value;
68 _settingsStore.autoGenerateSubaddressStatus =
69 - value ? AutoGenerateSubaddressStatus.enabled : AutoGenerateSubaddressStatus.disabled;
69 + value ? AutoGenerateSubaddressStatus.enabled : AutoGenerateSubaddressStatus.disabled;
70 }
71
72 bool get isAutoGenerateSubaddressesVisible => [
73 - WalletType.monero,
74 - WalletType.wownero,
75 - WalletType.bitcoin,
76 - WalletType.litecoin,
77 - WalletType.bitcoinCash,
78 - WalletType.dogecoin,
79 - WalletType.decred
80 - ].contains(_wallet.type);
73 + WalletType.monero,
74 + WalletType.wownero,
75 + WalletType.bitcoin,
76 + WalletType.litecoin,
77 + WalletType.bitcoinCash,
78 + WalletType.dogecoin,
79 + WalletType.decred
80 + ].contains(_wallet.type);
81
82 @computed
83 bool get isMoneroWallet => _wallet.type == WalletType.monero;
lib/view_model/settings/privacy_settings_view_model.dart
+3 -3
@@ -49,8 +49,7 @@ abstract class PrivacySettingsViewModelBase with Store {
49 ].contains(_wallet.type);
50
51 @computed
52 - bool get hasCoinControl =>
53 - [
52 + bool get hasCoinControl => [
53 WalletType.bitcoin,
54 WalletType.litecoin,
55 WalletType.monero,
@@ -112,7 +111,8 @@ abstract class PrivacySettingsViewModelBase with Store {
111 bool get canUsePayjoin => _wallet.type == WalletType.bitcoin && DeviceInfo.instance.isMobile;
112
113 @computed
115 - bool get canUseLightning => _wallet.type == WalletType.bitcoin && !Platform.isWindows && !Platform.isLinux;
114 + bool get canUseLightning =>
115 + _wallet.type == WalletType.bitcoin && !Platform.isWindows && !Platform.isLinux;
116
117 @computed
118 bool get useLightning => _wallet.type == WalletType.bitcoin && bitcoin!.useLightning(_wallet);
lib/view_model/settings/regular_list_item.dart
+1 -1
@@ -5,4 +5,4 @@ class RegularListItem extends SettingsListItem {
5 RegularListItem({required String title, this.handler}) : super(title);
6
7 final void Function(BuildContext context)? handler;
8 -}
\ No newline at end of file
8 +}
lib/view_model/settings/security_settings_view_model.dart
+3 -4
@@ -9,7 +9,8 @@ part 'security_settings_view_model.g.dart';
9 class SecuritySettingsViewModel = SecuritySettingsViewModelBase with _$SecuritySettingsViewModel;
10
11 abstract class SecuritySettingsViewModelBase with Store {
12 - SecuritySettingsViewModelBase(this._settingsStore, this._authService) : _biometricAuth = BiometricAuth();
12 + SecuritySettingsViewModelBase(this._settingsStore, this._authService)
13 + : _biometricAuth = BiometricAuth();
14
15 final BiometricAuth _biometricAuth;
16 final SettingsStore _settingsStore;
@@ -51,9 +52,7 @@ abstract class SecuritySettingsViewModelBase with Store {
52 _settingsStore.pinTimeOutDuration = duration;
53
54 @action
54 - void setEnableDuressPin(bool value) =>
55 - _settingsStore.enableDuressPin = value;
55 + void setEnableDuressPin(bool value) => _settingsStore.enableDuressPin = value;
56
57 Future<void> clearDuressPin() async => await _authService.clearDuressPin();
58 -
58 }
lib/view_model/settings/switcher_list_item.dart
+1 -4
@@ -3,10 +3,7 @@ import 'package:flutter/foundation.dart';
3 import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
4
5 class SwitcherListItem extends SettingsListItem {
6 - SwitcherListItem(
7 - {required String title,
8 - required this.value,
9 - required this.onValueChange})
6 + SwitcherListItem({required String title, required this.value, required this.onValueChange})
7 : super(title);
8
9 final bool Function() value;
lib/view_model/settings/trocador_providers_view_model.dart
+1 -4
@@ -28,10 +28,7 @@ abstract class TrocadorProvidersViewModelBase with Store {
28 ObservableFuture(trocadorExchangeProvider.fetchProviders().then((providers) {
29 var providerNames = providers.map((e) => e.name).toList();
30
31 - providerRatings = {
32 - for (var provider in providers)
33 - provider.name: provider.rating
34 - };
31 + providerRatings = {for (var provider in providers) provider.name: provider.rating};
32
33 return _settingsStore
34 .updateAllTrocadorProviderStates(providerNames)
lib/view_model/settings/version_list_item.dart
+1 -1
@@ -3,4 +3,4 @@ import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
3
4 class VersionListItem extends SettingsListItem {
5 VersionListItem({required String title}) : super(title);
6 -}
\ No newline at end of file
6 +}
lib/view_model/setup_pin_code_view_model.dart
+1 -4
@@ -4,8 +4,7 @@ import 'package:cake_wallet/entities/secret_store_key.dart';
4 import 'package:cake_wallet/store/settings_store.dart';
5
6 class SetupPinCodeViewModel {
7 - SetupPinCodeViewModel(this._authService, this._settingsStore,
8 - {this.isDuressPin = false})
7 + SetupPinCodeViewModel(this._authService, this._settingsStore, {this.isDuressPin = false})
8 : _pinCodeLength = _settingsStore.pinCodeLength;
9
10 String originalPinCode = '';
@@ -46,7 +45,6 @@ class SetupPinCodeViewModel {
45 originalPinCode = pin;
46
47 if (isDuressPin && pin.length == pinCodeLength) {
49 -
48 final regularKey = generateStoreKeyFor(key: SecretStoreKey.pinCodePassword);
49 final encodedRegularPin = await _authService.secureStorage.read(key: regularKey);
50
@@ -84,7 +82,6 @@ class SetupPinCodeViewModel {
82 return;
83 }
84
87 -
85 await _authService.setPassword(repeatedPinCode);
86 _settingsStore.pinCodeLength = pinCodeLength;
87 }
lib/view_model/start_tor_view_model.dart
+8 -5
@@ -40,7 +40,7 @@ abstract class StartTorViewModelBase with Store {
40 remainingSeconds = waitTimeInSeconds;
41 _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
42 remainingSeconds -= 1;
43 -
43 +
44 if (remainingSeconds <= 0) {
45 timer.cancel();
46 timeoutReached = true;
@@ -66,7 +66,8 @@ abstract class StartTorViewModelBase with Store {
66 didStartTor = true;
67 final appStore = getIt.get<AppStore>();
68 bootstrapOnline(navigatorKey, loadWallet: true);
69 - appStore.wallet?.connectToNode(node: appStore.settingsStore.getCurrentNode(appStore.wallet!.type));
69 + appStore.wallet
70 + ?.connectToNode(node: appStore.settingsStore.getCurrentNode(appStore.wallet!.type));
71 Navigator.pushReplacementNamed(context, Routes.login);
72 }
73
@@ -76,7 +77,8 @@ abstract class StartTorViewModelBase with Store {
77 settingsStore.currentBuiltinTor = false;
78 bootstrapOnline(navigatorKey, loadWallet: true);
79 final appStore = getIt.get<AppStore>();
79 - appStore.wallet?.connectToNode(node: appStore.settingsStore.getCurrentNode(appStore.wallet!.type));
80 + appStore.wallet
81 + ?.connectToNode(node: appStore.settingsStore.getCurrentNode(appStore.wallet!.type));
82 Navigator.pushReplacementNamed(context, Routes.login);
83 }
84
@@ -84,7 +86,8 @@ abstract class StartTorViewModelBase with Store {
86 void ignoreAndLaunchApp(BuildContext context) {
87 bootstrapOnline(navigatorKey, loadWallet: true);
88 final appStore = getIt.get<AppStore>();
87 - appStore.wallet?.connectToNode(node: appStore.settingsStore.getCurrentNode(appStore.wallet!.type));
89 + appStore.wallet
90 + ?.connectToNode(node: appStore.settingsStore.getCurrentNode(appStore.wallet!.type));
91 Navigator.pushReplacementNamed(context, Routes.login);
92 }
93
@@ -92,4 +95,4 @@ abstract class StartTorViewModelBase with Store {
95 _timer?.cancel();
96 _timer = null;
97 }
95 -}
\ No newline at end of file
98 +}
lib/view_model/trade_details_view_model.dart
+10 -14
@@ -117,13 +117,13 @@ abstract class TradeDetailsViewModelBase with Store {
117 case ExchangeProviderDescription.chainflip:
118 return 'https://scan.chainflip.io/channels/${trade.id}';
119 case ExchangeProviderDescription.xoSwap:
120 - return 'https://orders.xoswap.com/${trade.id}';
120 + return 'https://orders.xoswap.com/${trade.id}';
121 case ExchangeProviderDescription.swapsXyz:
122 - return 'https://scan.swaps.xyz/transactions/${trade.id}';
122 + return 'https://scan.swaps.xyz/transactions/${trade.id}';
123 case ExchangeProviderDescription.jupiter:
124 return 'https://solscan.io/tx/${trade.txId}';
125 case ExchangeProviderDescription.nearIntents:
126 - return 'https://explorer.near-intents.org/transactions/${trade.id}';
126 + return 'https://explorer.near-intents.org/transactions/${trade.id}';
127 }
128 return null;
129 }
@@ -167,7 +167,7 @@ abstract class TradeDetailsViewModelBase with Store {
167 DetailsListStatusItem(title: S.current.trade_details_state, value: trade.state.toString()));
168
169 final tradeFrom = trade.from;
170 - final tradeTo = trade.to;
170 + final tradeTo = trade.to;
171
172 if (tradeFrom != null && tradeTo != null) {
173 items.add(TradeDetailsListCardItem.tradeDetails(
@@ -185,9 +185,7 @@ abstract class TradeDetailsViewModelBase with Store {
185
186 final destinationMemo = trade.toAddressExtraId;
187 final destinationCurrency = trade.to;
188 - if (destinationMemo != null &&
189 - destinationMemo.isNotEmpty &&
190 - destinationCurrency != null) {
188 + if (destinationMemo != null && destinationMemo.isNotEmpty && destinationCurrency != null) {
189 final isDestinationTag =
190 memoLabelTypeFor(destinationCurrency) == MemoLabelType.destinationTag;
191 items.add(StandartListItem(
@@ -205,8 +203,7 @@ abstract class TradeDetailsViewModelBase with Store {
203 }
204
205 if (trade.isRefund == true) {
208 - items.add(StandartListItem(
209 - title: 'Refund', value: trade.refundAddress ?? ''));
206 + items.add(StandartListItem(title: 'Refund', value: trade.refundAddress ?? ''));
207 }
208
209 if (trade.provider == ExchangeProviderDescription.trocador) {
@@ -220,9 +217,10 @@ abstract class TradeDetailsViewModelBase with Store {
217 }
218 }
219
223 - if (trade.provider == ExchangeProviderDescription.swapsXyz && trade.txId != null && trade.txId!.isNotEmpty) {
224 - items.add(StandartListItem(
225 - title: 'Transaction ID', value: trade.txId!));
220 + if (trade.provider == ExchangeProviderDescription.swapsXyz &&
221 + trade.txId != null &&
222 + trade.txId!.isNotEmpty) {
223 + items.add(StandartListItem(title: 'Transaction ID', value: trade.txId!));
224 }
225 }
226
@@ -232,6 +230,4 @@ abstract class TradeDetailsViewModelBase with Store {
230 launchUrl(uri, mode: LaunchMode.externalApplication);
231 } catch (e) {}
232 }
235 -
236 -
233 }
lib/view_model/transaction_details_view_model.dart
+13 -39
@@ -76,7 +76,9 @@ class TxDetailRowDefinition {
76 TxDetailRowDefinition(
77 keyString: "standard_list_item_transaction_details_date_key",
78 title: S.current.transaction_details_date,
79 - valueGetter: (vm) => DateFormat("d MMMM yyyy, HH:mm", vm._appStore.settingsStore.languageCode).format(vm.transactionInfo.date)),
79 + valueGetter: (vm) =>
80 + DateFormat("d MMMM yyyy, HH:mm", vm._appStore.settingsStore.languageCode)
81 + .format(vm.transactionInfo.date)),
82 TxDetailRowDefinition(
83 keyString: "standard_list_item_transaction_details_height_key",
84 title: S.current.transaction_details_height,
@@ -85,7 +87,6 @@ class TxDetailRowDefinition {
87 ![WalletType.solana, WalletType.tron].contains(vm.wallet.type) ||
88 !isLightning(vm.transactionInfo),
89 ),
88 -
90 TxDetailRowDefinition(
91 keyString: "standard_list_item_transaction_details_fee_key",
92 title: S.current.transaction_details_fee,
@@ -93,8 +94,6 @@ class TxDetailRowDefinition {
94 applicable: (vm) =>
95 vm.wallet.type != WalletType.nano &&
96 (vm.transactionInfo.fee?.toStringWithSymbol() ?? "").isNotEmpty),
96 -
97 -
97 TxDetailRowDefinition(
98 keyString: "standard_list_item_transaction_confirmations_key",
99 title: S.current.confirmations,
@@ -104,8 +103,6 @@ class TxDetailRowDefinition {
103 .contains(vm.wallet.type) &&
104 !isLightning(vm.transactionInfo),
105 listItemBuilder: ConfirmationsListItem.new),
107 -
108 -
106 TxDetailRowDefinition(
107 keyString: "standard_list_item_transaction_details_recipient_address_key",
108 title: S.current.transaction_details_recipient_address,
@@ -125,12 +122,12 @@ class TxDetailRowDefinition {
122 .firstOrNull ??
123 "";
124 case WalletType.tron:
128 - if(vm.transactionInfo.to != null)
129 - ret = tron!.getTronBase58Address(vm.transactionInfo.to!, vm.wallet);
125 + if (vm.transactionInfo.to != null)
126 + ret = tron!.getTronBase58Address(vm.transactionInfo.to!, vm.wallet);
127 default:
128 break;
129 }
133 - if(ret == null) {
130 + if (ret == null) {
131 ret = vm.transactionInfo.to ?? "";
132 }
133 final resolvedAddress = _moneroRecipientAddressForDisplay(ret, vm.wallet.type);
@@ -144,8 +141,6 @@ class TxDetailRowDefinition {
141 vm.wallet.type == WalletType.bitcoin &&
142 vm.transactionInfo.direction == TransactionDirection.incoming),
143 listItemBuilder: AddressListItem.new),
147 -
148 -
144 TxDetailRowDefinition(
145 keyString: "standard_list_item_transaction_details_source_address_key",
146 title: S.current.transaction_details_source_address,
@@ -159,7 +154,6 @@ class TxDetailRowDefinition {
154 },
155 applicable: (vm) => vm.transactionInfo.from != null,
156 listItemBuilder: AddressListItem.new),
162 -
157 TxDetailRowDefinition(
158 keyString: "standard_list_item_address_label_key",
159 title: S.current.address_label,
@@ -168,8 +162,6 @@ class TxDetailRowDefinition {
162 vm.transactionInfo.additionalInfo['accountIndex'] as int,
163 vm.transactionInfo.additionalInfo['addressIndex'] as int),
164 applicable: (vm) => vm.wallet.type == WalletType.monero),
171 -
172 -
165 TxDetailRowDefinition(
166 keyString: "standard_list_item_transaction_key",
167 title: S.current.transaction_key,
@@ -185,7 +177,6 @@ class TxDetailRowDefinition {
177 "";
178 },
179 applicable: (vm) => vm.wallet.type == WalletType.monero),
188 -
180 TxDetailRowDefinition(
181 keyString: "standard_list_item_lightning_preimage",
182 title: S.current.transaction_preimage,
@@ -193,14 +184,11 @@ class TxDetailRowDefinition {
184 applicable: (vm) =>
185 hasLightningPreimage(vm.transactionInfo) && isLightning(vm.transactionInfo),
186 ),
196 -
187 TxDetailRowDefinition(
188 keyString: "standard_list_item_transaction_confirmed_key",
189 title: S.current.confirmed_tx,
190 valueGetter: (vm) => (vm.transactionInfo.confirmations > 0).toString(),
191 applicable: (vm) => vm.wallet.type == WalletType.nano),
202 -
203 -
192 TxDetailRowDefinition(
193 keyString: "standard_list_item_transaction_details_memo_key",
194 title: S.current.memo,
@@ -208,23 +196,17 @@ class TxDetailRowDefinition {
196 applicable: (vm) =>
197 vm.wallet.type == WalletType.zcash &&
198 vm.transactionInfo.additionalInfo["memo"] != null),
211 -
212 -
199 TxDetailRowDefinition(
200 keyString: "standard_list_item_transaction_details_asset_id_key",
201 title: "Asset ID",
202 valueGetter: (vm) =>
203 vm.transactionInfo.additionalInfo["assetId"] as String? ?? "Unknown asset id",
204 applicable: (vm) => vm.wallet.type == WalletType.zano),
219 -
220 -
205 TxDetailRowDefinition(
206 keyString: "standard_list_item_transaction_details_comment_key",
207 title: S.current.transaction_details_title,
208 valueGetter: (vm) => vm.transactionInfo.additionalInfo['comment'] as String? ?? "",
209 applicable: (vm) => vm.wallet.type == WalletType.zano),
226 -
227 -
210 TxDetailRowDefinition(
211 keyString: "standard_list_item_transaction_details_id_key",
212 title: S.current.transaction_details_transaction_id,
@@ -272,7 +254,8 @@ abstract class TransactionDetailsViewModelBase with Store {
254 final recipientAddress = description.recipientAddress;
255
256 if (recipientAddress?.isNotEmpty ?? false) {
275 - final recipientAddressForDisplay = _moneroRecipientAddressForDisplay(recipientAddress!, wallet.type);
257 + final recipientAddressForDisplay =
258 + _moneroRecipientAddressForDisplay(recipientAddress!, wallet.type);
259 items.add(
260 AddressListItem(
261 title: S.current.transaction_details_recipient_address,
@@ -287,7 +270,7 @@ abstract class TransactionDetailsViewModelBase with Store {
270 void updateNote(String note) {
271 final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
272 final description = transactionDescriptionBox.values.firstWhere(
290 - (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
273 + (val) => val.id == descriptionKey || val.id == transactionInfo.txHash,
274 orElse: () => TransactionDescription(id: descriptionKey));
275
276 description.transactionNote = note;
@@ -301,9 +284,9 @@ abstract class TransactionDetailsViewModelBase with Store {
284
285 String get note {
286 final descriptionKey = '${transactionInfo.txHash}_${wallet.walletAddresses.primaryAddress}';
304 - final description = transactionDescriptionBox.values.firstWhereOrNull(
305 - (val) => val.id == descriptionKey || val.id == transactionInfo.txHash);
306 - return description?.transactionNote??"";
287 + final description = transactionDescriptionBox.values
288 + .firstWhereOrNull((val) => val.id == descriptionKey || val.id == transactionInfo.txHash);
289 + return description?.transactionNote ?? "";
290 }
291
292 final TransactionInfo transactionInfo;
@@ -400,16 +383,13 @@ abstract class TransactionDetailsViewModelBase with Store {
383 case WalletType.litecoin:
384 bool isPegOut = (transactionInfo.additionalInfo["isPegOut"] as bool?) ?? false;
385 bool fromPegOut = (transactionInfo.additionalInfo["fromPegOut"] as bool?) ?? false;
403 - if(isPegOut || fromPegOut)
404 - return 6;
386 + if (isPegOut || fromPegOut) return 6;
387 default:
388 return 0;
389 }
390 return 0;
391 }
392
411 -
412 -
393 String get formattedTitle {
394 if (transactionInfo.additionalInfo['autoShield'] == true) {
395 return "Autoshield";
@@ -425,7 +405,6 @@ abstract class TransactionDetailsViewModelBase with Store {
405 bool canReplaceByFee;
406
407 String get _explorerUrl {
428 -
408 final txId = transactionInfo.txHash;
409 if (wallet.chainId != null) {
410 final explorerUrl = evm!.getExplorerUrlForChainId(wallet.chainId!);
@@ -569,9 +548,6 @@ abstract class TransactionDetailsViewModelBase with Store {
548 }
549 }
550
572 -
573 -
574 -
551 @action
552 Future<void> _checkForRBF(TransactionInfo tx) async {
553 if (wallet.type == WalletType.bitcoin &&
@@ -634,6 +610,4 @@ abstract class TransactionDetailsViewModelBase with Store {
610 String get pendingTransactionFeeFiatAmountFormatted => sendViewModel.isFiatDisabled
611 ? ''
612 : sendViewModel.pendingTransactionFeeFiatAmount + ' ' + sendViewModel.fiat.title;
637 -
638 -
613 }
lib/view_model/unspent_coins/unspent_coins_details_view_model.dart
+2 -1
@@ -46,7 +46,8 @@ abstract class UnspentCoinsDetailsViewModelBase with Store {
46 })
47 ];
48
49 - if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, WalletType.dogecoin].contains(_type)) {
49 + if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, WalletType.dogecoin]
50 + .contains(_type)) {
51 items.add(BlockExplorerListItem(
52 title: S.current.view_in_block_explorer,
53 value: _explorerDescription(_type),
lib/view_model/unspent_coins/unspent_coins_item.dart
+13 -15
@@ -6,20 +6,19 @@ part 'unspent_coins_item.g.dart';
6 class UnspentCoinsItem = UnspentCoinsItemBase with _$UnspentCoinsItem;
7
8 abstract class UnspentCoinsItemBase with Store, UnspentComparable {
9 - UnspentCoinsItemBase({
10 - required this.address,
11 - required this.amount,
12 - required this.hash,
13 - required this.isFrozen,
14 - required this.note,
15 - required this.isSending,
16 - required this.isChange,
17 - required this.value,
18 - required this.vout,
19 - required this.keyImage,
20 - required this.isSilentPayment,
21 - this.isBeingSaved = false
22 - });
9 + UnspentCoinsItemBase(
10 + {required this.address,
11 + required this.amount,
12 + required this.hash,
13 + required this.isFrozen,
14 + required this.note,
15 + required this.isSending,
16 + required this.isChange,
17 + required this.value,
18 + required this.vout,
19 + required this.keyImage,
20 + required this.isSilentPayment,
21 + this.isBeingSaved = false});
22
23 @observable
24 String address;
@@ -54,7 +53,6 @@ abstract class UnspentCoinsItemBase with Store, UnspentComparable {
53 @observable
54 bool isSilentPayment;
55
57 -
56 @observable
57 bool isBeingSaved;
58 }
lib/view_model/unspent_coins/unspent_coins_list_view_model.dart
+5 -5
@@ -50,10 +50,10 @@ abstract class UnspentCoinsListViewModelBase with Store {
50 ObservableList<UnspentCoinsItem> items;
51
52 @computed
53 - List<UnspentCoinsItem> get nonFrozenItems => items.where((e)=>!e.isFrozen).toList();
53 + List<UnspentCoinsItem> get nonFrozenItems => items.where((e) => !e.isFrozen).toList();
54
55 @computed
56 - List<UnspentCoinsItem> get frozenItems => items.where((e)=>e.isFrozen).toList();
56 + List<UnspentCoinsItem> get frozenItems => items.where((e) => e.isFrozen).toList();
57
58 final Map<String, Map<String, dynamic>> _originalState;
59
@@ -74,7 +74,6 @@ abstract class UnspentCoinsListViewModelBase with Store {
74
75 @computed
76 Map<String, String> get fiatAmounts {
77 -
77 final currency = wallet.currency;
78 final price = _fiatConversationStore.prices[currency];
79 if (price == null || price == 0.0 || isFiatDisabled) return {};
@@ -149,7 +148,8 @@ abstract class UnspentCoinsListViewModelBase with Store {
148 if (wallet.type == WalletType.wownero) {
149 await wownero!.updateUnspents(wallet);
150 }
152 - if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, WalletType.dogecoin].contains(wallet.type)) {
151 + if ([WalletType.bitcoin, WalletType.litecoin, WalletType.bitcoinCash, WalletType.dogecoin]
152 + .contains(wallet.type)) {
153 await bitcoin!.updateUnspents(wallet);
154 }
155 if (wallet.type == WalletType.decred) {
@@ -176,7 +176,7 @@ abstract class UnspentCoinsListViewModelBase with Store {
176 }
177 }
178
179 - List<Unspent> _getSpecificUnspents(UnspentCoinType overrideCoinTypeToSpendFrom) {
179 + List<Unspent> _getSpecificUnspents(UnspentCoinType overrideCoinTypeToSpendFrom) {
180 switch (wallet.type) {
181 case WalletType.monero:
182 return monero!.getUnspents(wallet);
lib/view_model/unspent_coins/unspent_coins_switch_item.dart
+7 -6
@@ -1,12 +1,13 @@
1 import 'package:cake_wallet/src/screens/transaction_details/transaction_details_list_item.dart';
2
3 class UnspentCoinsSwitchItem extends TransactionDetailsListItem {
4 - UnspentCoinsSwitchItem({
5 - required String title,
6 - required String value,
7 - required this.switchValue,
8 - required this.onSwitchValueChange}) : super(title: title, value: value);
4 + UnspentCoinsSwitchItem(
5 + {required String title,
6 + required String value,
7 + required this.switchValue,
8 + required this.onSwitchValueChange})
9 + : super(title: title, value: value);
10
11 final bool Function() switchValue;
12 final void Function(bool value) onSwitchValueChange;
12 -}
\ No newline at end of file
13 +}
lib/view_model/wallet_address_list/wallet_account_list_header.dart
+1 -1
@@ -1,3 +1,3 @@
1 import 'package:cake_wallet/utils/list_item.dart';
2
3 -class WalletAccountListHeader extends ListItem {}
\ No newline at end of file
3 +class WalletAccountListHeader extends ListItem {}
lib/view_model/wallet_address_list/wallet_address_hidden_list_header.dart
+1 -1
@@ -1,3 +1,3 @@
1 import 'package:cake_wallet/utils/list_item.dart';
2
3 -class WalletAddressHiddenListHeader extends ListItem {}
\ No newline at end of file
3 +class WalletAddressHiddenListHeader extends ListItem {}
lib/view_model/wallet_address_list/wallet_address_list_item.dart
+15 -15
@@ -1,21 +1,21 @@
1 import 'package:cake_wallet/utils/list_item.dart';
2
3 class WalletAddressListItem extends ListItem {
4 - WalletAddressListItem({
5 - required this.address,
6 - required this.isPrimary,
7 - this.id,
8 - this.name,
9 - this.txCount,
10 - this.balance,
11 - this.isChange = false,
12 - // Address that is only ever used once, shouldn't be used to receive funds, copy and paste, share etc
13 - this.isOneTimeReceiveAddress = false,
14 - this.isHidden = false,
15 - this.isManual = false,
16 - this.isLegacyDerivation = false,
17 - this.derivationPath
18 - }) : super();
4 + WalletAddressListItem(
5 + {required this.address,
6 + required this.isPrimary,
7 + this.id,
8 + this.name,
9 + this.txCount,
10 + this.balance,
11 + this.isChange = false,
12 + // Address that is only ever used once, shouldn't be used to receive funds, copy and paste, share etc
13 + this.isOneTimeReceiveAddress = false,
14 + this.isHidden = false,
15 + this.isManual = false,
16 + this.isLegacyDerivation = false,
17 + this.derivationPath})
18 + : super();
19
20 final int? id;
21 final bool isPrimary;
lib/view_model/wallet_address_list/wallet_address_list_view_model.dart
+17 -10
@@ -73,8 +73,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
73
74 double? _fiatRate;
75
76 - List<Currency> get currencies =>
77 - [tokenCurrency ?? wallet.currency, ...FiatCurrency.all];
76 + List<Currency> get currencies => [tokenCurrency ?? wallet.currency, ...FiatCurrency.all];
77
78 List<Currency> get tokenCurrencies => wallet.balance.keys.toList();
79
@@ -86,7 +85,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
85 _appStore.amountParsingProxy.getCryptoSymbol(tokenCurrency ?? wallet.currency);
86
87 void setTokenCurrency(Currency curr) {
89 - if(curr == wallet.currency || curr == CryptoCurrency.btcln) {
88 + if (curr == wallet.currency || curr == CryptoCurrency.btcln) {
89 tokenCurrency = null;
90 selectedCurrency = wallet.currency;
91 return;
@@ -144,7 +143,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
143 if (_amount.isEmpty) return "";
144 var cryptoCurrency = tokenCurrency ?? wallet.currency;
145 if (cryptoCurrency == CryptoCurrency.btcln) cryptoCurrency = CryptoCurrency.btc;
147 - if(selectedCurrency is FiatCurrency && _fiatRate != null) {
146 + if (selectedCurrency is FiatCurrency && _fiatRate != null) {
147 return selectedCurrencyFiatAmount;
148 }
149
@@ -168,7 +167,10 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
167
168 // payjoinEndpoint getter is broken, but uri works
169 bool get hasPayjoin =>
171 - wallet.type == WalletType.bitcoin && !isLightning && !isSilentPayments && uri.toString().contains("payjo.in");
170 + wallet.type == WalletType.bitcoin &&
171 + !isLightning &&
172 + !isSilentPayments &&
173 + uri.toString().contains("payjo.in");
174
175 AmountParsingProxy get amountParsingProxy => _appStore.amountParsingProxy;
176
@@ -461,7 +463,8 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
463 String get walletTypeName => walletTypeToString(type);
464
465 @computed
464 - bool get hasAddressList => [
466 + bool get hasAddressList =>
467 + [
468 WalletType.monero,
469 WalletType.wownero,
470 WalletType.haven,
@@ -471,7 +474,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
474 WalletType.decred,
475 WalletType.dogecoin,
476 WalletType.zcash
474 - ].contains(wallet.type) && !isLightning && isZCashTransparent;
477 + ].contains(wallet.type) &&
478 + !isLightning &&
479 + isZCashTransparent;
480
481 @computed
482 bool get hasAddressRotation => hasAddressList && wallet.type != WalletType.zcash;
@@ -576,11 +581,13 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
581 wallet.type == WalletType.bitcoin && bitcoin!.hasSelectedSilentPayments(wallet);
582
583 @computed
579 - bool get isLightning => wallet.type == WalletType.bitcoin && (wallet.walletAddresses.getPaymentUri(_amount) is LightningPaymentRequest);
584 + bool get isLightning =>
585 + wallet.type == WalletType.bitcoin &&
586 + (wallet.walletAddresses.getPaymentUri(_amount) is LightningPaymentRequest);
587
588 @computed
589 bool get isZCashTransparent {
583 - if(wallet.type != WalletType.zcash) {
590 + if (wallet.type != WalletType.zcash) {
591 return true;
592 }
593 receivePageOption;
@@ -619,7 +626,7 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
626
627 @action
628 Future<void> rotateAddress() async {
622 - if(isRotatingAddress) {
629 + if (isRotatingAddress) {
630 return;
631 }
632 try {
lib/view_model/wallet_address_list/wallet_address_util.dart
+3 -7
@@ -25,18 +25,14 @@ Future<void> createNewAddress(WalletBase wallet, String label) async {
25 await monero!
26 .getSubaddressList(wallet)
27 .addSubaddress(wallet, accountIndex: monero!.getCurrentAccount(wallet).id, label: label);
28 - final subaddressList = await monero!
29 - .getSubaddressList(wallet)
30 - .subaddresses;
31 - if(subaddressList.isEmpty) {
28 + final subaddressList = await monero!.getSubaddressList(wallet).subaddresses;
29 + if (subaddressList.isEmpty) {
30 // this shouldn't happen, we just added an addr.
31 // somehow, it happened once in prod regardless.
32 // we just return instead of crashing, user can press the button again ig
33 return;
34 }
37 - final addr = subaddressList
38 - .first
39 - .address; // first because the order is reversed
35 + final addr = subaddressList.first.address; // first because the order is reversed
36 wallet.walletAddresses.manualAddresses.add(addr);
37 await wallet.save();
38 }
lib/view_model/wallet_creation_vm.dart
+6 -7
@@ -25,8 +25,7 @@ part 'wallet_creation_vm.g.dart';
25 class WalletCreationVM = WalletCreationVMBase with _$WalletCreationVM;
26
27 abstract class WalletCreationVMBase with Store {
28 - WalletCreationVMBase(this._appStore, this.walletCreationService,
29 - this.seedSettingsViewModel,
28 + WalletCreationVMBase(this._appStore, this.walletCreationService, this.seedSettingsViewModel,
29 {required this.type, required this.isRecovery})
30 : state = InitialExecutionState(),
31 name = '';
@@ -81,7 +80,6 @@ abstract class WalletCreationVMBase with Store {
80 Future<void> _create({dynamic options}) async {
81 final type = this.type;
82 try {
84 -
83 state = IsExecutingState();
84 if (name.isEmpty) {
85 name = await generateName();
@@ -101,9 +99,9 @@ abstract class WalletCreationVMBase with Store {
99
100 final credentials = getCredentials(options);
101
104 - final di = ((credentials.derivationInfo?.derivationPath??"") == "")
105 - ? getDefaultCreateDerivation()
106 - : credentials.derivationInfo;
102 + final di = ((credentials.derivationInfo?.derivationPath ?? "") == "")
103 + ? getDefaultCreateDerivation()
104 + : credentials.derivationInfo;
105
106 final diId = await di!.save();
107 credentials.derivationInfo = di;
@@ -118,7 +116,8 @@ abstract class WalletCreationVMBase with Store {
116 path: path,
117 dirPath: dirPath,
118 address: '',
121 - showIntroCakePayCard: (!await walletCreationService.typeExists(type)) && type != WalletType.haven,
119 + showIntroCakePayCard:
120 + (!await walletCreationService.typeExists(type)) && type != WalletType.haven,
121 derivationInfoId: diId,
122 hardwareWalletType: credentials.hardwareWalletType,
123 );
lib/view_model/wallet_groups_display_view_model.dart
+11 -12
@@ -24,7 +24,7 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
24 this._walletManager,
25 this.walletListViewModel, {
26 required this.type,
27 - }) : isFetchingMnemonic = false {
27 + }) : isFetchingMnemonic = false {
28 reaction((_) => _appStore.wallet, (_) => unawaited(updateWalletInfoSourceList()));
29 unawaited(updateWalletInfoSourceList());
30 }
@@ -47,7 +47,6 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
47 @observable
48 WalletInfo? selectedSingleWallet;
49
50 -
50 @observable
51 bool isFetchingMnemonic;
52
@@ -116,8 +115,8 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
115
116 // Check for nano derivation type
117 final di = await wallet.getDerivationInfo();
119 - bool isNanoDerivationType = wallet.type == WalletType.nano &&
120 - di.derivationType == DerivationType.nano;
118 + bool isNanoDerivationType =
119 + wallet.type == WalletType.nano && di.derivationType == DerivationType.nano;
120
121 // Check for electrum derivation type
122 bool isElectrumDerivationType =
@@ -129,17 +128,17 @@ abstract class WalletGroupsDisplayViewModelBase with Store {
128
129 bool isNonSeedWallet = wallet.isNonSeedWallet;
130
132 - bool isNotMoneroBip39Wallet = wallet.type == WalletType.monero &&
133 - di.derivationType != DerivationType.bip39;
131 + bool isNotMoneroBip39Wallet =
132 + wallet.type == WalletType.monero && di.derivationType != DerivationType.bip39;
133
134 // Exclude if any of these conditions are true
135 shouldExcludeGroup = shouldExcludeGroup ||
137 - isNonBIP39Wallet ||
138 - isNanoDerivationType ||
139 - isElectrumDerivationType ||
140 - isSameTypeAsSelectedWallet ||
141 - isNonSeedWallet ||
142 - isNotMoneroBip39Wallet;
136 + isNonBIP39Wallet ||
137 + isNanoDerivationType ||
138 + isElectrumDerivationType ||
139 + isSameTypeAsSelectedWallet ||
140 + isNonSeedWallet ||
141 + isNotMoneroBip39Wallet;
142 }
143
144 if (shouldExcludeGroup) continue;
lib/view_model/wallet_hardware_restore_view_model.dart
+6 -11
@@ -26,14 +26,10 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
26
27 int _nextIndex = 0;
28
29 - WalletHardwareRestoreViewModelBase(
30 - this.hardwareWalletVM,
31 - AppStore appStore,
32 - WalletCreationService walletCreationService,
33 - SeedSettingsViewModel seedSettingsViewModel,
29 + WalletHardwareRestoreViewModelBase(this.hardwareWalletVM, AppStore appStore,
30 + WalletCreationService walletCreationService, SeedSettingsViewModel seedSettingsViewModel,
31 {required WalletType type})
35 - : super(appStore, walletCreationService, seedSettingsViewModel,
36 - type: type, isRecovery: true);
32 + : super(appStore, walletCreationService, seedSettingsViewModel, type: type, isRecovery: true);
33
34 @observable
35 String name = "";
@@ -54,8 +50,7 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
50 Future<void> getNextAvailableAccounts(int limit) async {
51 try {
52 final service = await hardwareWalletVM.getHardwareWalletService(type);
57 - final accounts = await service
58 - .getAvailableAccounts(index: _nextIndex, limit: limit);
53 + final accounts = await service.getAvailableAccounts(index: _nextIndex, limit: limit);
54
55 availableAccounts.addAll(accounts);
56 _nextIndex += limit;
@@ -74,8 +69,8 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
69 switch (type) {
70 case WalletType.bitcoin:
71 case WalletType.litecoin:
77 - credentials =
78 - bitcoin!.createBitcoinHardwareWalletCredentials(name: name, accountData: selectedAccount!);
72 + credentials = bitcoin!
73 + .createBitcoinHardwareWalletCredentials(name: name, accountData: selectedAccount!);
74 break;
75 case WalletType.ethereum:
76 case WalletType.polygon:
lib/view_model/wallet_list/wallet_list_view_model.dart
+3 -4
@@ -70,8 +70,7 @@ abstract class WalletListViewModelBase with Store {
70 WalletType get currentWalletType => _appStore.wallet!.type;
71
72 Future<bool> requireHardwareWalletConnection(WalletListItem walletItem) async =>
73 - _walletLoadingService.requireHardwareWalletConnection(
74 - walletItem.type, walletItem.name);
73 + _walletLoadingService.requireHardwareWalletConnection(walletItem.type, walletItem.name);
74
75 @action
76 Future<void> loadWallet(WalletListItem walletItem) async {
@@ -89,8 +88,8 @@ abstract class WalletListViewModelBase with Store {
88
89 bool get ascending => _appStore.settingsStore.walletListAscending;
90
92 - /// Serializes updateList() calls: each caller waits for the previous one to finish, then runs.
93 - ///
91 + /// Serializes updateList() calls: each caller waits for the previous one to finish, then runs.
92 + ///
93 /// This basically ensures that all calls to updateList() are executed.
94 Future<void> _lastUpdate = Future.value();
95
lib/view_model/wallet_restore_view_model.dart
+12 -14
@@ -255,15 +255,14 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
255
256 case WalletType.monero:
257 return monero!.createMoneroRestoreWalletFromKeysCredentials(
258 - name: name,
259 - height: height,
260 - spendKey: spendKey!,
261 - viewKey: viewKey!,
262 - address: address!,
263 - password: password,
264 - language: 'English',
265 - hardwareWalletType: hardwareWalletType
266 - );
258 + name: name,
259 + height: height,
260 + spendKey: spendKey!,
261 + viewKey: viewKey!,
262 + address: address!,
263 + password: password,
264 + language: 'English',
265 + hardwareWalletType: hardwareWalletType);
266
267 case WalletType.nano:
268 return nano!.createNanoRestoreWalletFromKeysCredentials(
@@ -312,11 +311,10 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
311 );
312 case WalletType.zcash:
313 return zcash!.createZcashRestoreWalletFromPrivateKey(
315 - name: name,
316 - privateKey: options['private_key'] as String,
317 - password: password,
318 - height: height
319 - );
314 + name: name,
315 + privateKey: options['private_key'] as String,
316 + password: password,
317 + height: height);
318 default:
319 break;
320 }
lib/view_model/wallet_seed_view_model.dart
-1
@@ -21,7 +21,6 @@ abstract class WalletSeedViewModelBase with Store {
21 setupSeedVerification();
22 }
23
24 -
24 @observable
25 String name;
26
lib/wallet_type_utils.dart
+8 -10
@@ -2,23 +2,21 @@ import 'package:cw_core/wallet_type.dart';
2 import 'package:cake_wallet/wallet_types.g.dart';
3
4 bool get isMoneroOnly {
5 - return availableWalletTypes.length == 1
6 - && availableWalletTypes.first == WalletType.monero;
5 + return availableWalletTypes.length == 1 && availableWalletTypes.first == WalletType.monero;
6 }
7
9 -
8 bool get isSingleCoin {
11 - return availableWalletTypes.length == 1;
9 + return availableWalletTypes.length == 1;
10 }
11
12 bool get hasMonero {
15 - return availableWalletTypes.contains(WalletType.monero);
13 + return availableWalletTypes.contains(WalletType.monero);
14 }
15
16 String get approximatedAppName {
19 - if (isMoneroOnly) {
20 - return 'Monero.com';
21 - }
22 -
23 - return 'Cake Wallet';
17 + if (isMoneroOnly) {
18 + return 'Monero.com';
19 + }
20 +
21 + return 'Cake Wallet';
22 }
lib/wownero/cw_wownero.dart
+10 -2
@@ -230,7 +230,11 @@ class CWWownero extends Wownero {
230 required int height,
231 required String mnemonic}) =>
232 WowneroRestoreWalletFromSeedCredentials(
233 - name: name, password: password, passphrase: passphrase, height: height, mnemonic: mnemonic);
233 + name: name,
234 + password: password,
235 + passphrase: passphrase,
236 + height: height,
237 + mnemonic: mnemonic);
238
239 @override
240 WalletCredentials createWowneroNewWalletCredentials(
@@ -240,7 +244,11 @@ class CWWownero extends Wownero {
244 String? password,
245 String? passphrase}) =>
246 WowneroNewWalletCredentials(
243 - name: name, password: password, language: language, isPolyseed: isPolyseed, passphrase: passphrase);
247 + name: name,
248 + password: password,
249 + language: language,
250 + isPolyseed: isPolyseed,
251 + passphrase: passphrase);
252
253 @override
254 Map<String, String> getKeys(Object wallet) {
lib/zano/cw_zano.dart
+23 -11
@@ -1,17 +1,20 @@
1 part of 'zano.dart';
2
3 class CWZano extends Zano {
4 -
5 - List<ZanoAsset> getZanoAssets(WalletBase wallet) => (wallet as ZanoWallet).zanoAssets.values.toList();
4 + List<ZanoAsset> getZanoAssets(WalletBase wallet) =>
5 + (wallet as ZanoWallet).zanoAssets.values.toList();
6
7 @override
8 - Future<CryptoCurrency> addZanoAssetById(WalletBase wallet, String assetId) async => await (wallet as ZanoWallet).addZanoAssetById(assetId);
8 + Future<CryptoCurrency> addZanoAssetById(WalletBase wallet, String assetId) async =>
9 + await (wallet as ZanoWallet).addZanoAssetById(assetId);
10
11 @override
11 - Future<void> changeZanoAssetAvailability(WalletBase wallet, CryptoCurrency token) async => await (wallet as ZanoWallet).changeZanoAssetAvailability(token as ZanoAsset);
12 + Future<void> changeZanoAssetAvailability(WalletBase wallet, CryptoCurrency token) async =>
13 + await (wallet as ZanoWallet).changeZanoAssetAvailability(token as ZanoAsset);
14
15 @override
14 - Future<void> deleteZanoAsset(WalletBase wallet, CryptoCurrency token) async => await (wallet as ZanoWallet).deleteZanoAsset(token as ZanoAsset);
16 + Future<void> deleteZanoAsset(WalletBase wallet, CryptoCurrency token) async =>
17 + await (wallet as ZanoWallet).deleteZanoAsset(token as ZanoAsset);
18
19 @override
20 Future<ZanoAsset?> getZanoAsset(WalletBase wallet, String assetId) async {
@@ -48,12 +51,18 @@ class CWZano extends Zano {
51
52 @override
53 WalletCredentials createZanoRestoreWalletFromSeedCredentials(
51 - {required String name, required String password, required int height, required String passphrase, required String mnemonic}) {
52 - return ZanoRestoreWalletFromSeedCredentials(name: name, password: password, passphrase: passphrase, height: height, mnemonic: mnemonic);
54 + {required String name,
55 + required String password,
56 + required int height,
57 + required String passphrase,
58 + required String mnemonic}) {
59 + return ZanoRestoreWalletFromSeedCredentials(
60 + name: name, password: password, passphrase: passphrase, height: height, mnemonic: mnemonic);
61 }
62
63 @override
56 - WalletCredentials createZanoNewWalletCredentials({required String name, required String? password, required String? passphrase}) {
64 + WalletCredentials createZanoNewWalletCredentials(
65 + {required String name, required String? password, required String? passphrase}) {
66 return ZanoNewWalletCredentials(name: name, password: password, passphrase: passphrase);
67 }
68
@@ -91,10 +100,12 @@ class CWZano extends Zano {
100 );
101
102 @override
94 - double formatterIntAmountToDouble({required int amount, required CryptoCurrency currency, required bool forFee}) {
103 + double formatterIntAmountToDouble(
104 + {required int amount, required CryptoCurrency currency, required bool forFee}) {
105 // fee always counted in zano with default decimal points
106 if (forFee) return ZanoFormatter.intAmountToDouble(amount);
97 - if (currency is ZanoAsset) return ZanoFormatter.intAmountToDouble(amount, currency.decimalPoint);
107 + if (currency is ZanoAsset)
108 + return ZanoFormatter.intAmountToDouble(amount, currency.decimalPoint);
109 return ZanoFormatter.intAmountToDouble(amount);
110 }
111
@@ -122,7 +133,8 @@ class CWZano extends Zano {
133 return CryptoCurrency.zano;
134 }
135 wallet as ZanoWallet;
125 - final asset = wallet.zanoAssets.values.firstWhereOrNull((element) => element?.ticker == transaction.tokenSymbol);
136 + final asset = wallet.zanoAssets.values
137 + .firstWhereOrNull((element) => element?.ticker == transaction.tokenSymbol);
138 return asset;
139 }
140
lib/zcash/cw_zcash.dart
+16 -23
@@ -69,21 +69,20 @@ class CWZcash extends Zcash {
69 {required CryptoCurrency currency, required int feeRate}) {
70 return ZcashTransactionCredentials(
71 outputs: outputs,
72 - priority:
73 - getZcashTransactionPriorityAutomatic() as MoneroTransactionPriority,
72 + priority: getZcashTransactionPriorityAutomatic() as MoneroTransactionPriority,
73 currency: currency,
74 );
75 }
76
77 @override
79 - WalletService<WalletCredentials, WalletCredentials, WalletCredentials,
80 - WalletCredentials> createZcashWalletService(bool isDirect) {
78 + WalletService<WalletCredentials, WalletCredentials, WalletCredentials, WalletCredentials>
79 + createZcashWalletService(bool isDirect) {
80 return ZcashWalletService();
81 }
82
83 @override
84 double formatterZcashAmountToDouble({TransactionInfo? transaction, BigInt? amount}) {
86 - return cryptoAmountToDouble(amount: amount?.toInt()??0, divider: 1e8);
85 + return cryptoAmountToDouble(amount: amount?.toInt() ?? 0, divider: 1e8);
86 }
87
88 @override
@@ -98,18 +97,14 @@ class CWZcash extends Zcash {
97
98 @override
99 String getAddress(
101 - WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
102 - TransactionInfo>
103 - wallet) {
100 + WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet) {
101 final zcashWallet = wallet as ZcashWallet;
102 return zcashWallet.walletAddresses.address;
103 }
104
105 @override
106 String getPrivateKey(
110 - WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
111 - TransactionInfo>
112 - wallet) {
107 + WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet) {
108 final zcashWallet = wallet as ZcashWallet;
109 final seed = zcashWallet.seed;
110 return seed ?? '';
@@ -117,9 +112,7 @@ class CWZcash extends Zcash {
112
113 @override
114 String getPublicKey(
120 - WalletBase<Balance, TransactionHistoryBase<TransactionInfo>,
121 - TransactionInfo>
122 - wallet) {
115 + WalletBase<Balance, TransactionHistoryBase<TransactionInfo>, TransactionInfo> wallet) {
116 return getAddress(wallet);
117 }
118
@@ -130,7 +123,7 @@ class CWZcash extends Zcash {
123
124 return <String, String>{
125 if (seed != null) 'seed': seed,
133 - ...(zcashWallet.keys as Map<String, String?>).map((final k, final v) => MapEntry(k, v??'')),
126 + ...(zcashWallet.keys as Map<String, String?>).map((final k, final v) => MapEntry(k, v ?? '')),
127 };
128 }
129
@@ -142,8 +135,7 @@ class CWZcash extends Zcash {
135 @override
136 List<WalletInfoAddressInfo> getAddressInfos(Object wallet) {
137 final zcashWallet = wallet as ZcashWallet;
145 - return (zcashWallet.walletAddresses as ZcashWalletAddresses)
146 - .getAddressInfos();
138 + return (zcashWallet.walletAddresses as ZcashWalletAddresses).getAddressInfos();
139 }
140
141 @override
@@ -169,7 +161,8 @@ class CWZcash extends Zcash {
161 @override
162 ReceivePageOption getSelectedAddressType(Object wallet) {
163 final zcashWallet = wallet as ZcashWallet;
172 - final t = (zcashWallet.walletAddresses as ZcashWalletAddresses).walletInfo.addressPageType??"";
164 + final t =
165 + (zcashWallet.walletAddresses as ZcashWalletAddresses).walletInfo.addressPageType ?? "";
166 return ZcashReceivePageOption.fromType(ZcashReceivePageOption.typeFromString(t));
167 }
168
@@ -177,7 +170,6 @@ class CWZcash extends Zcash {
170 return getSelectedAddressType(wallet) == ZcashReceivePageOption.transparentRotated;
171 }
172
180 -
173 @override
174 dynamic getZcashAddressType(ReceivePageOption option) {
175 switch (option) {
@@ -197,19 +189,20 @@ class CWZcash extends Zcash {
189 @override
190 Future<void> setAddressType(Object wallet, dynamic option) async {
191 final zcashWallet = wallet as ZcashWallet;
200 - await (zcashWallet.walletAddresses as ZcashWalletAddresses).setAddressType(option as ZcashAddressType);
192 + await (zcashWallet.walletAddresses as ZcashWalletAddresses)
193 + .setAddressType(option as ZcashAddressType);
194 }
195
196 @override
197 dynamic getOptionToType(ReceivePageOption option) {
198 return (option as ZcashReceivePageOption).toType();
199 }
207 -
200 +
201 @override
202 void unlockDatabase(String password) {
203 return ZcashWalletBase.unlockDatabase(password);
204 }
212 -
205 +
206 @override
207 Future<int> getHeightByDate(DateTime date) {
208 return ZcashWalletBase.getHeightByDate(date);
@@ -220,7 +213,7 @@ class CWZcash extends Zcash {
213 final zcashWallet = wallet as ZcashWallet;
214 return zcashWallet.couldBeZashiWallet();
215 }
223 -
216 +
217 @override
218 Future<void> rescanInternalChange(WalletBase wallet) {
219 final zcashWallet = wallet as ZcashWallet;