Merge remote-tracking branch 'origin/staging' into fusion

This commit is contained in:
sneurlax 2023-07-26 15:31:28 -05:00
commit 5cd8b4864e
88 changed files with 3965 additions and 1315 deletions

View file

@ -4,7 +4,7 @@
# This file should be version controlled.
version:
revision: f1875d570e39de09040c8f79aa13cc56baab8db1
revision: f92f44110e87bad5ff168335c36da6f6053036e6
channel: stable
project_type: app
@ -13,17 +13,11 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
- platform: linux
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
create_revision: f92f44110e87bad5ff168335c36da6f6053036e6
base_revision: f92f44110e87bad5ff168335c36da6f6053036e6
- platform: macos
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
- platform: windows
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
create_revision: f92f44110e87bad5ff168335c36da6f6053036e6
base_revision: f92f44110e87bad5ff168335c36da6f6053036e6
# User provided section

BIN
assets/icon/macos-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -1 +1 @@
Subproject commit e1df088733695ad06d377087d069eae1746d55a7
Subproject commit f677dec0b34d3f9fe8fce2bc8ff5c508c3f3bb9a

@ -1 +1 @@
Subproject commit ec3cf5e8e1b90e006188aa8c323d4cd52dbfa9b9
Subproject commit 9cd241b5ea142e21c01dd7639b42603281c43287

@ -1 +1 @@
Subproject commit 26a152fea3ca4b8c3f1130392a02f579c2ff218c
Subproject commit e48952185556a10f182184fd572bcb04365f5831

View file

@ -134,10 +134,28 @@ flutter run linux
Visual Studio is required for Windows development with the Flutter SDK. Download it at https://visualstudio.microsoft.com/downloads/ and install the "Desktop development with C++" workload, including all of its default components.
### Building libraries in WSL2
Set up Ubuntu 20.04 in WSL2. Follow the entire Linux host section to get set up and build windows `dll` libraries. Copy the resulting `dll`s to their respective positions on the Windows host:
Set up Ubuntu 20.04 in WSL2. Follow the entire Linux host section in the WSL2 Ubuntu 20.04 host to get set up to build. You will also need to install Rust and MXE dependencies on the WSL2 Ubuntu 20.04 host:
- [Install Rust](https://rustup.rs/)
```sh
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
- Install MXE by running `stack_wallet/scripts/windows/deps.sh`
```sh
./stack_wallet/scripts/windows/deps.sh
```
The WSL2 host may optionally be navigated to the `stack_wallet` repository on the Windows host in order to build the plugins in-place and skip the next section in which you copy the `dll`s from WSL2 to Windows. Then build windows `dll` libraries by running the following script on the WSL2 Ubuntu 20.04 host:
- `stack_wallet/scripts/windows/build_all.sh`
Copy the resulting `dll`s to their respective positions on the Windows host:
- `stack_wallet/crypto_plugins/flutter_libepiccash/scripts/windows/build/libepic_cash_wallet.dll`
- `stack_wallet/crypto_plugins/flutter_liblelantus/scripts/windows/build/libmobileliblelantus.dll`
<!--
- `stack_wallet/crypto_plugins/flutter_libmonero/scripts/windows/build/libcw_monero.dll`
- `stack_wallet/crypto_plugins/flutter_libmonero/scripts/windows/build/libcw_wownero.dll`
-->
<!-- TODO: script the copying or installation of libraries from WSL2 to the parent Windows host -->
### Install Flutter on Windows host

View file

@ -1,6 +1,4 @@
PODS:
- "app_settings (3.0.0+1)":
- Flutter
- barcode_scan2 (0.0.1):
- Flutter
- MTBBarcodeScanner
@ -112,7 +110,7 @@ PODS:
- Flutter
- flutter_native_splash (0.0.1):
- Flutter
- flutter_secure_storage (3.3.1):
- flutter_secure_storage (6.0.0):
- Flutter
- integration_test (0.0.1):
- Flutter
@ -149,7 +147,6 @@ PODS:
- Flutter
DEPENDENCIES:
- app_settings (from `.symlinks/plugins/app_settings/ios`)
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
- cw_monero (from `.symlinks/plugins/cw_monero/ios`)
@ -169,10 +166,10 @@ DEPENDENCIES:
- lelantus (from `.symlinks/plugins/lelantus/ios`)
- local_auth (from `.symlinks/plugins/local_auth/ios`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- stack_wallet_backup (from `.symlinks/plugins/stack_wallet_backup/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- wakelock (from `.symlinks/plugins/wakelock/ios`)
@ -188,8 +185,6 @@ SPEC REPOS:
- SwiftyGif
EXTERNAL SOURCES:
app_settings:
:path: ".symlinks/plugins/app_settings/ios"
barcode_scan2:
:path: ".symlinks/plugins/barcode_scan2/ios"
connectivity_plus:
@ -229,13 +224,13 @@ EXTERNAL SOURCES:
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
share_plus:
:path: ".symlinks/plugins/share_plus/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
stack_wallet_backup:
:path: ".symlinks/plugins/stack_wallet_backup/ios"
url_launcher_ios:
@ -244,13 +239,12 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/wakelock/ios"
SPEC CHECKSUMS:
app_settings: d103828c9f5d515c4df9ee754dabd443f7cedcf3
barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0
connectivity_plus: 413a8857dd5d9f1c399a39130850d02fe0feaf7e
connectivity_plus: 07c49e96d7fc92bc9920617b83238c4d178b446a
cw_monero: 9816991daff0e3ad0a8be140e31933b5526babd4
cw_shared_external: 2972d872b8917603478117c9957dfca611845a92
cw_wownero: ac53899fa5c6ff46b3fb490aa3b7ca36301fa832
device_info_plus: e5c5da33f982a436e103237c0c85f9031142abed
device_info_plus: 7545d84d8d1b896cb16a4ff98c19f07ec4b298ea
devicelocale: b22617f40038496deffba44747101255cee005b0
DKImagePickerController: b512c28220a2b8ac7419f21c491fc8534b7601ac
DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179
@ -260,23 +254,23 @@ SPEC CHECKSUMS:
flutter_libmonero: da68a616b73dd0374a8419c684fa6b6df2c44ffe
flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
integration_test: 13825b8a9334a850581300559b8839134b124670
isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073
lelantus: 417f0221260013dfc052cae9cf4b741b6479edba
local_auth: 1740f55d7af0a2e2a8684ce225fe79d8931e808c
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
SDWebImage: 72f86271a6f3139cc7e4a89220946489d4b9a866
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
share_plus: 599aa54e4ea31d4b4c0e9c911bcc26c55e791028
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
stack_wallet_backup: 5b8563aba5d8ffbf2ce1944331ff7294a0ec7c03
SwiftProtobuf: 6ef3f0e422ef90d6605ca20b21a94f6c1324d6b3
SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780
url_launcher_ios: fb12c43172927bb5cf75aeebd073f883801f1993
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
PODFILE CHECKSUM: 57c8aed26fba39d3ec9424816221f294a07c58eb

View file

@ -242,6 +242,7 @@
files = (
);
inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@ -301,7 +302,6 @@
"${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework",
"${BUILT_PRODUCTS_DIR}/SwiftProtobuf/SwiftProtobuf.framework",
"${BUILT_PRODUCTS_DIR}/SwiftyGif/SwiftyGif.framework",
"${BUILT_PRODUCTS_DIR}/app_settings/app_settings.framework",
"${BUILT_PRODUCTS_DIR}/barcode_scan2/barcode_scan2.framework",
"${BUILT_PRODUCTS_DIR}/connectivity_plus/connectivity_plus.framework",
"${BUILT_PRODUCTS_DIR}/cw_monero/cw_monero.framework",
@ -335,7 +335,6 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftProtobuf.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SwiftyGif.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/app_settings.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/barcode_scan2.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/connectivity_plus.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cw_monero.framework",
@ -505,7 +504,10 @@
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
@ -692,7 +694,10 @@
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
@ -771,7 +776,10 @@
);
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",

View file

@ -177,6 +177,9 @@ class DB {
}
Future<Box<dynamic>> getTxCacheBox({required Coin coin}) async {
if (_txCacheBoxes[coin]?.isOpen != true) {
_txCacheBoxes.remove(coin);
}
return _txCacheBoxes[coin] ??=
await Hive.openBox<dynamic>(_boxNameTxCache(coin: coin));
}
@ -186,6 +189,9 @@ class DB {
}
Future<Box<dynamic>> getAnonymitySetCacheBox({required Coin coin}) async {
if (_setCacheBoxes[coin]?.isOpen != true) {
_setCacheBoxes.remove(coin);
}
return _setCacheBoxes[coin] ??=
await Hive.openBox<dynamic>(_boxNameSetCache(coin: coin));
}
@ -195,6 +201,9 @@ class DB {
}
Future<Box<dynamic>> getUsedSerialsCacheBox({required Coin coin}) async {
if (_usedSerialsCacheBoxes[coin]?.isOpen != true) {
_usedSerialsCacheBoxes.remove(coin);
}
return _usedSerialsCacheBoxes[coin] ??=
await Hive.openBox<dynamic>(_boxNameUsedSerialsCache(coin: coin));
}

View file

@ -54,6 +54,7 @@ class MainDB {
TransactionBlockExplorerSchema,
StackThemeSchema,
ContactEntrySchema,
LelantusCoinSchema,
],
directory: (await StackFileSystem.applicationIsarDirectory()).path,
// inspector: kDebugMode,
@ -370,6 +371,8 @@ class MainDB {
final transactionCount = await getTransactions(walletId).count();
final addressCount = await getAddresses(walletId).count();
final utxoCount = await getUTXOs(walletId).count();
final lelantusCoinCount =
await isar.lelantusCoins.where().walletIdEqualTo(walletId).count();
await isar.writeTxn(() async {
const paginateLimit = 50;
@ -403,6 +406,18 @@ class MainDB {
.findAll();
await isar.utxos.deleteAll(utxoIds);
}
// lelantusCoins
for (int i = 0; i < lelantusCoinCount; i += paginateLimit) {
final lelantusCoinIds = await isar.lelantusCoins
.where()
.walletIdEqualTo(walletId)
.offset(i)
.limit(paginateLimit)
.idProperty()
.findAll();
await isar.lelantusCoins.deleteAll(lelantusCoinIds);
}
});
}
@ -497,4 +512,15 @@ class MainDB {
isar.writeTxn(() async {
await isar.ethContracts.putAll(contracts);
});
// ========== Lelantus =======================================================
Future<int?> getHighestUsedMintIndex({required String walletId}) async {
return await isar.lelantusCoins
.where()
.walletIdEqualTo(walletId)
.sortByMintIndexDesc()
.mintIndexProperty()
.findFirst();
}
}

View file

@ -46,7 +46,7 @@ class EthTokenTxExtraDTO {
),
gas: _amountFromJsonNum(map['gas']),
gasPrice: _amountFromJsonNum(map['gasPrice']),
nonce: map['nonce'] as int,
nonce: map['nonce'] as int?,
input: map['input'] as String,
gasCost: _amountFromJsonNum(map['gasCost']),
gasUsed: _amountFromJsonNum(map['gasUsed']),
@ -63,7 +63,7 @@ class EthTokenTxExtraDTO {
final Amount gas;
final Amount gasPrice;
final String input;
final int nonce;
final int? nonce;
final Amount gasCost;
final Amount gasUsed;

View file

@ -127,16 +127,16 @@ class EthTxDTO {
map['timestamp'] = timestamp;
map['from'] = from;
map['to'] = to;
map['value'] = value;
map['gas'] = gas;
map['gasPrice'] = gasPrice;
map['maxFeePerGas'] = maxFeePerGas;
map['maxPriorityFeePerGas'] = maxPriorityFeePerGas;
map['value'] = value.toString();
map['gas'] = gas.toString();
map['gasPrice'] = gasPrice.toString();
map['maxFeePerGas'] = maxFeePerGas.toString();
map['maxPriorityFeePerGas'] = maxPriorityFeePerGas.toString();
map['isError'] = isError;
map['hasToken'] = hasToken;
map['compressedTx'] = compressedTx;
map['gasCost'] = gasCost;
map['gasUsed'] = gasUsed;
map['gasCost'] = gasCost.toString();
map['gasUsed'] = gasUsed.toString();
return map;
}

View file

@ -164,14 +164,16 @@ class CachedElectrumX {
final _list = box.get("serials") as List?;
List<String> cachedSerials =
_list == null ? [] : List<String>.from(_list);
Set<String> cachedSerials =
_list == null ? {} : List<String>.from(_list).toSet();
final startNumber = cachedSerials.length;
// startNumber is broken currently
final startNumber = 0; // cachedSerials.length;
final serials =
await electrumXClient.getUsedCoinSerials(startNumber: startNumber);
List<String> newSerials = [];
final serials = await electrumXClient.getUsedCoinSerials(
startNumber: startNumber,
);
Set<String> newSerials = {};
for (final element in (serials["serials"] as List)) {
if (!isHexadecimal(element as String)) {
@ -182,12 +184,14 @@ class CachedElectrumX {
}
cachedSerials.addAll(newSerials);
final resultingList = cachedSerials.toList();
await box.put(
"serials",
cachedSerials,
resultingList,
);
return cachedSerials;
return resultingList;
} catch (e, s) {
Logging.instance.log(
"Failed to process CachedElectrumX.getTransaction(): $e\n$s",

View file

@ -159,8 +159,8 @@ class ElectrumX {
throw Exception(
"JSONRPC response\n"
" command: $command\n"
" args: $args\n"
" error: ${response.data}",
" error: ${response.data}"
" args: $args\n",
);
}

View file

@ -79,7 +79,7 @@ class JsonRPC {
// TODO different timeout length?
req.initiateTimeout(
const Duration(seconds: 10),
Duration(seconds: connectionTimeout.inSeconds ~/ 2),
onTimedOut: () {
_requestQueue.remove(req);
},

View file

@ -0,0 +1,81 @@
import 'package:isar/isar.dart';
part 'lelantus_coin.g.dart';
@collection
class LelantusCoin {
Id id = Isar.autoIncrement;
@Index()
final String walletId;
final String txid;
final String value; // can't use BigInt in isar :shrug:
@Index(
unique: true,
replace: false,
composite: [
CompositeIndex("walletId"),
],
)
final int mintIndex;
final int anonymitySetId;
final bool isUsed;
final bool isJMint;
final String? otherData;
LelantusCoin({
required this.walletId,
required this.txid,
required this.value,
required this.mintIndex,
required this.anonymitySetId,
required this.isUsed,
required this.isJMint,
required this.otherData,
});
LelantusCoin copyWith({
String? walletId,
String? publicCoin,
String? txid,
String? value,
int? mintIndex,
int? anonymitySetId,
bool? isUsed,
bool? isJMint,
String? otherData,
}) {
return LelantusCoin(
walletId: walletId ?? this.walletId,
txid: txid ?? this.txid,
value: value ?? this.value,
mintIndex: mintIndex ?? this.mintIndex,
anonymitySetId: anonymitySetId ?? this.anonymitySetId,
isUsed: isUsed ?? this.isUsed,
isJMint: isJMint ?? this.isJMint,
otherData: otherData ?? this.otherData,
);
}
@override
String toString() {
return 'LelantusCoin{'
'id: $id, '
'walletId: $walletId, '
'txid: $txid, '
'value: $value, '
'mintIndex: $mintIndex, '
'anonymitySetId: $anonymitySetId, '
'otherData: $otherData, '
'isJMint: $isJMint, '
'isUsed: $isUsed'
'}';
}
}

File diff suppressed because it is too large Load diff

View file

@ -15,5 +15,6 @@ export 'blockchain_data/output.dart';
export 'blockchain_data/transaction.dart';
export 'blockchain_data/utxo.dart';
export 'ethereum/eth_contract.dart';
export 'firo_specific/lelantus_coin.dart';
export 'log.dart';
export 'transaction_note.dart';

View file

@ -2341,8 +2341,6 @@ class ThemeAssetsV3 implements IThemeAssets {
// Added some future proof params in case we want to add anything else
// This should provide some buffer in stead of creating assetsV4 etc
@Name("otherStringParam1")
late final String? dummy1;
@Name("otherStringParam2")
late final String? dummy2;
@Name("otherStringParam3")
@ -2388,6 +2386,19 @@ class ThemeAssetsV3 implements IThemeAssets {
Map<Coin, String>? _coinCardImages;
late final String? coinCardImagesString;
@ignore
Map<Coin, String>? get coinCardFavoritesImages =>
_coinCardFavoritesImages ??= coinCardFavoritesImagesString == null
? null
: parseCoinAssetsString(
coinCardFavoritesImagesString!,
placeHolder: coinPlaceholder,
);
@ignore
Map<Coin, String>? _coinCardFavoritesImages;
@Name("otherStringParam1")
late final String? coinCardFavoritesImagesString;
ThemeAssetsV3();
factory ThemeAssetsV3.fromJson({
@ -2443,13 +2454,18 @@ class ThemeAssetsV3 implements IThemeAssets {
Map<String, dynamic>.from(json["coins"]["cards"] as Map),
)
: null
..coinCardFavoritesImagesString = json["coins"]["favoriteCards"] is Map
? createCoinAssetsString(
"$themeId/assets",
Map<String, dynamic>.from(json["coins"]["favoriteCards"] as Map),
)
: null
..loadingGifRelative = json["loading_gif"] is String
? "$themeId/assets/${json["loading_gif"] as String}"
: null
..backgroundRelative = json["background"] is String
? "$themeId/assets/${json["background"] as String}"
: null
..dummy1 = null
..dummy2 = null
..dummy3 = null;
}
@ -2528,6 +2544,7 @@ class ThemeAssetsV3 implements IThemeAssets {
'coinImages: $coinImages, '
'coinSecondaryImages: $coinSecondaryImages, '
'coinCardImages: $coinCardImages'
'coinCardFavoritesImages: $coinCardFavoritesImages'
')';
}
}

View file

@ -29626,7 +29626,7 @@ int _themeAssetsV3EstimateSize(
}
}
{
final value = object.dummy1;
final value = object.coinCardFavoritesImagesString;
if (value != null) {
bytesCount += 3 + value.length * 3;
}
@ -29677,7 +29677,7 @@ void _themeAssetsV3Serialize(
writer.writeString(offsets[7], object.coinSecondaryImagesString);
writer.writeString(offsets[8], object.exchangeRelative);
writer.writeString(offsets[9], object.loadingGifRelative);
writer.writeString(offsets[10], object.dummy1);
writer.writeString(offsets[10], object.coinCardFavoritesImagesString);
writer.writeString(offsets[11], object.dummy2);
writer.writeString(offsets[12], object.dummy3);
writer.writeString(offsets[13], object.personaEasyRelative);
@ -29714,7 +29714,7 @@ ThemeAssetsV3 _themeAssetsV3Deserialize(
object.coinSecondaryImagesString = reader.readString(offsets[7]);
object.exchangeRelative = reader.readString(offsets[8]);
object.loadingGifRelative = reader.readStringOrNull(offsets[9]);
object.dummy1 = reader.readStringOrNull(offsets[10]);
object.coinCardFavoritesImagesString = reader.readStringOrNull(offsets[10]);
object.dummy2 = reader.readStringOrNull(offsets[11]);
object.dummy3 = reader.readStringOrNull(offsets[12]);
object.personaEasyRelative = reader.readString(offsets[13]);
@ -31224,7 +31224,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1IsNull() {
coinCardFavoritesImagesStringIsNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNull(
property: r'otherStringParam1',
@ -31233,7 +31233,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1IsNotNull() {
coinCardFavoritesImagesStringIsNotNull() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(const FilterCondition.isNotNull(
property: r'otherStringParam1',
@ -31242,7 +31242,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1EqualTo(
coinCardFavoritesImagesStringEqualTo(
String? value, {
bool caseSensitive = true,
}) {
@ -31256,7 +31256,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1GreaterThan(
coinCardFavoritesImagesStringGreaterThan(
String? value, {
bool include = false,
bool caseSensitive = true,
@ -31272,7 +31272,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1LessThan(
coinCardFavoritesImagesStringLessThan(
String? value, {
bool include = false,
bool caseSensitive = true,
@ -31288,7 +31288,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1Between(
coinCardFavoritesImagesStringBetween(
String? lower,
String? upper, {
bool includeLower = true,
@ -31308,7 +31308,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1StartsWith(
coinCardFavoritesImagesStringStartsWith(
String value, {
bool caseSensitive = true,
}) {
@ -31322,7 +31322,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1EndsWith(
coinCardFavoritesImagesStringEndsWith(
String value, {
bool caseSensitive = true,
}) {
@ -31336,7 +31336,8 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1Contains(String value, {bool caseSensitive = true}) {
coinCardFavoritesImagesStringContains(String value,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.contains(
property: r'otherStringParam1',
@ -31347,7 +31348,8 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1Matches(String pattern, {bool caseSensitive = true}) {
coinCardFavoritesImagesStringMatches(String pattern,
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.matches(
property: r'otherStringParam1',
@ -31358,7 +31360,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1IsEmpty() {
coinCardFavoritesImagesStringIsEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.equalTo(
property: r'otherStringParam1',
@ -31368,7 +31370,7 @@ extension ThemeAssetsV3QueryFilter
}
QueryBuilder<ThemeAssetsV3, ThemeAssetsV3, QAfterFilterCondition>
dummy1IsNotEmpty() {
coinCardFavoritesImagesStringIsNotEmpty() {
return QueryBuilder.apply(this, (query) {
return query.addFilterCondition(FilterCondition.greaterThan(
property: r'otherStringParam1',

View file

@ -12,6 +12,7 @@ import 'package:hive/hive.dart';
part 'type_adaptors/lelantus_coin.g.dart';
@Deprecated("Use Isar object instead")
// @HiveType(typeId: 9)
class LelantusCoin {
// @HiveField(0)
@ -27,6 +28,7 @@ class LelantusCoin {
// @HiveField(5)
bool isUsed;
@Deprecated("Use Isar object instead")
LelantusCoin(
this.index,
this.value,

View file

@ -142,7 +142,7 @@ class _AddCustomTokenViewState extends ConsumerState<AddCustomTokenView> {
context: context,
message: "Looking up contract",
);
currentToken = response.value;
currentToken = response!.value;
if (currentToken != null) {
nameController.text = currentToken!.name;
symbolController.text = currentToken!.symbol;
@ -157,7 +157,7 @@ class _AddCustomTokenViewState extends ConsumerState<AddCustomTokenView> {
context: context,
builder: (context) => StackOkDialog(
title: "Failed to look up token",
message: response.exception?.message,
message: response!.exception?.message,
),
),
);

View file

@ -8,6 +8,8 @@
*
*/
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:stackwallet/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart';
import 'package:stackwallet/themes/stack_colors.dart';
@ -32,35 +34,37 @@ class CreateWalletButtonGroup extends StatelessWidget {
crossAxisAlignment:
isDesktop ? CrossAxisAlignment.center : CrossAxisAlignment.stretch,
children: [
ConstrainedBox(
constraints: BoxConstraints(
minHeight: isDesktop ? 70 : 0,
minWidth: isDesktop ? 480 : 0,
),
child: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonStyle(context),
onPressed: () {
Navigator.of(context).pushNamed(
NameYourWalletView.routeName,
arguments: Tuple2(
AddWalletType.New,
coin,
),
);
},
child: Text(
"Create new wallet",
style: isDesktop
? STextStyles.desktopButtonEnabled(context)
: STextStyles.button(context),
if (Platform.isAndroid || coin != Coin.wownero)
ConstrainedBox(
constraints: BoxConstraints(
minHeight: isDesktop ? 70 : 0,
minWidth: isDesktop ? 480 : 0,
),
child: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonStyle(context),
onPressed: () {
Navigator.of(context).pushNamed(
NameYourWalletView.routeName,
arguments: Tuple2(
AddWalletType.New,
coin,
),
);
},
child: Text(
"Create new wallet",
style: isDesktop
? STextStyles.desktopButtonEnabled(context)
: STextStyles.button(context),
),
),
),
),
SizedBox(
height: isDesktop ? 16 : 12,
),
if (Platform.isAndroid || coin != Coin.wownero)
SizedBox(
height: isDesktop ? 16 : 12,
),
ConstrainedBox(
constraints: BoxConstraints(
minHeight: isDesktop ? 70 : 0,

View file

@ -35,6 +35,7 @@ import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart
import 'package:stackwallet/services/exchange/majestic_bank/majestic_bank_exchange.dart';
import 'package:stackwallet/services/exchange/trocador/trocador_exchange.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount_unit.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -160,26 +161,15 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
if (value == null) {
return null;
}
try {
// wtf Dart?????
// This turns "99999999999999999999" into 100000000000000000000.0
// final numFromLocalised = NumberFormat.decimalPattern(
// ref.read(localeServiceChangeNotifierProvider).locale)
// .parse(value);
// return Decimal.tryParse(numFromLocalised.toString());
try {
return Decimal.parse(value);
} catch (_) {
try {
return Decimal.parse(value.replaceAll(",", "."));
} catch (_) {
rethrow;
}
}
} catch (_) {
return null;
}
return AmountUnit.normal
.tryParse(
value,
locale: ref.read(localeServiceChangeNotifierProvider).locale,
coin: Coin.bitcoin, // dummy value (not used due to override)
overrideWithDecimalPlacesFromString: true,
)
?.decimal;
}
Future<AggregateCurrency> _getAggregateCurrency(Currency currency) async {
@ -809,6 +799,14 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
// if (_swapLock) {
_sendController.text = ref.read(efSendAmountStringProvider);
// }
if (_sendFocusNode.hasFocus) {
_sendController.selection = TextSelection.fromPosition(
TextPosition(
offset: _sendController.text.length,
),
);
}
}
});
ref.listen(efSendAmountStringProvider, (previous, String next) {
@ -820,11 +818,19 @@ class _ExchangeFormState extends ConsumerState<ExchangeForm> {
? "-"
: ref.read(efReceiveAmountStringProvider);
// }
if (_receiveFocusNode.hasFocus) {
_receiveController.selection = TextSelection.fromPosition(
TextPosition(
offset: _receiveController.text.length,
),
);
}
}
});
ref.listen(efEstimateProvider.notifier, (previous, next) {
final estimate = (next as StateController<Estimate?>).state;
final estimate = (next).state;
if (ref.read(efReversedProvider)) {
updateSend(estimate);
} else {

View file

@ -493,51 +493,54 @@ class _ConfirmTransactionViewState
],
),
),
if (coin == Coin.epicCash)
if (coin == Coin.epicCash &&
(transactionInfo["onChainNote"] as String).isNotEmpty)
const SizedBox(
height: 12,
),
if (coin == Coin.epicCash)
if (coin == Coin.epicCash &&
(transactionInfo["onChainNote"] as String).isNotEmpty)
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"On chain note",
style: STextStyles.smallMed12(context),
),
const SizedBox(
height: 4,
),
Text(
transactionInfo["onChainNote"] as String,
style: STextStyles.itemSubtitle12(context),
),
],
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"On chain note",
style: STextStyles.smallMed12(context),
),
const SizedBox(
height: 4,
),
Text(
transactionInfo["onChainNote"] as String,
style: STextStyles.itemSubtitle12(context),
),
],
),
),
),
const SizedBox(
height: 12,
),
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
(coin == Coin.epicCash) ? "Local Note" :
"Note",
style: STextStyles.smallMed12(context),
),
const SizedBox(
height: 4,
),
Text(
transactionInfo["note"] as String,
style: STextStyles.itemSubtitle12(context),
),
],
if ((transactionInfo["note"] as String).isNotEmpty)
const SizedBox(
height: 12,
),
if ((transactionInfo["note"] as String).isNotEmpty)
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
(coin == Coin.epicCash) ? "Local Note" : "Note",
style: STextStyles.smallMed12(context),
),
const SizedBox(
height: 4,
),
Text(
transactionInfo["note"] as String,
style: STextStyles.itemSubtitle12(context),
),
],
),
),
),
],
),
if (isDesktop)

View file

@ -164,7 +164,7 @@ class _InstallThemeFromFileDialogState
);
if (mounted) {
Navigator.of(context).pop();
if (!result) {
if (!result!) {
unawaited(
showDialog(
context: context,

View file

@ -72,11 +72,11 @@ class _StackThemeCardState extends ConsumerState<StackThemeCard> {
}
Future<void> _downloadPressed() async {
final result = await showLoading(
final result = (await showLoading(
whileFuture: _downloadAndInstall(),
context: context,
message: "Downloading and installing theme...",
);
))!;
if (mounted) {
final message = result

View file

@ -20,11 +20,12 @@ import 'package:stackwallet/pages/home_view/home_view.dart';
import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/debug_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/xpub_view.dart';
import 'package:stackwallet/pages/settings_views/sub_widgets/settings_list_button.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
import 'package:stackwallet/route_generator.dart';
@ -231,7 +232,7 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
.mnemonic;
if (mounted) {
Navigator.push(
await Navigator.push(
context,
RouteGenerator.getRoute(
shouldUseMaterialRoute:
@ -305,6 +306,25 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
);
},
),
if (coin == Coin.nano || coin == Coin.banano)
const SizedBox(
height: 8,
),
if (coin == Coin.nano || coin == Coin.banano)
Consumer(
builder: (_, ref, __) {
return SettingsListButton(
iconAssetName: Assets.svg.eye,
title: "Change representative",
onPressed: () {
Navigator.of(context).pushNamed(
ChangeRepresentativeView.routeName,
arguments: widget.walletId,
);
},
);
},
),
const SizedBox(
height: 8,
),
@ -434,18 +454,20 @@ class _EpiBoxInfoFormState extends ConsumerState<EpicBoxInfoForm> {
TextButton(
onPressed: () async {
try {
wallet.updateEpicboxConfig(
await wallet.updateEpicboxConfig(
hostController.text,
int.parse(portController.text),
);
showFloatingFlushBar(
context: context,
message: "Epicbox info saved!",
type: FlushBarType.success,
);
wallet.refresh();
if (mounted) {
await showFloatingFlushBar(
context: context,
message: "Epicbox info saved!",
type: FlushBarType.success,
);
}
unawaited(wallet.refresh());
} catch (e) {
showFloatingFlushBar(
await showFloatingFlushBar(
context: context,
message: "Failed to save epicbox info: $e",
type: FlushBarType.warning,

View file

@ -0,0 +1,402 @@
/*
* This file is part of Stack Wallet.
*
* Copyright (c) 2023 Cypher Stack
* All Rights Reserved.
* The code is distributed under GPLv3 license, see LICENSE file for details.
* Generated by Cypher Stack on 2023-05-26
*
*/
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/services/coins/banano/banano_wallet.dart';
import 'package:stackwallet/services/coins/nano/nano_wallet.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
import 'package:stackwallet/widgets/loading_indicator.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:stackwallet/widgets/textfield_icon_button.dart';
class ChangeRepresentativeView extends ConsumerStatefulWidget {
const ChangeRepresentativeView({
Key? key,
required this.walletId,
this.clipboardInterface = const ClipboardWrapper(),
}) : super(key: key);
final String walletId;
final ClipboardInterface clipboardInterface;
static const String routeName = "/changeRepresentative";
@override
ConsumerState<ChangeRepresentativeView> createState() => _XPubViewState();
}
class _XPubViewState extends ConsumerState<ChangeRepresentativeView> {
final _textController = TextEditingController();
final _textFocusNode = FocusNode();
final bool isDesktop = Util.isDesktop;
late ClipboardInterface _clipboardInterface;
String? representative;
Future<String> loadRepresentative() async {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
if (manager.coin == Coin.nano) {
return (manager.wallet as NanoWallet).getCurrentRepresentative();
} else if (manager.coin == Coin.banano) {
return (manager.wallet as BananoWallet).getCurrentRepresentative();
}
throw Exception("Unsupported wallet attempted to show representative!");
}
Future<void> _save() async {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
final changeFuture = manager.coin == Coin.nano
? (manager.wallet as NanoWallet).changeRepresentative
: (manager.wallet as BananoWallet).changeRepresentative;
final result = await showLoading(
whileFuture: changeFuture(_textController.text),
context: context,
message: "Updating representative...",
isDesktop: Util.isDesktop,
onException: (ex) {
String msg = ex.toString();
while (msg.isNotEmpty && msg.startsWith("Exception:")) {
msg = msg.substring(10).trim();
}
showFloatingFlushBar(
type: FlushBarType.warning,
message: msg,
context: context,
);
});
if (mounted) {
if (result != null && result) {
setState(() {
representative = _textController.text;
_textController.text = "";
});
await showFloatingFlushBar(
type: FlushBarType.success,
message: "Representative changed",
context: context,
);
}
}
}
@override
void initState() {
_clipboardInterface = widget.clipboardInterface;
super.initState();
}
@override
void dispose() {
_textController.dispose();
_textFocusNode.dispose();
super.dispose();
}
Future<void> _copy() async {
await _clipboardInterface
.setData(ClipboardData(text: representative ?? ""));
if (mounted) {
unawaited(showFloatingFlushBar(
type: FlushBarType.info,
message: "Copied to clipboard",
iconAsset: Assets.svg.copy,
context: context,
));
}
}
@override
Widget build(BuildContext context) {
return ConditionalParent(
condition: !isDesktop,
builder: (child) => Background(
child: SafeArea(
child: Scaffold(
backgroundColor:
Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
Navigator.of(context).pop();
},
),
title: Text(
"Wallet representative",
style: STextStyles.navBarTitle(context),
),
actions: [
Padding(
padding: const EdgeInsets.all(10),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
color: Theme.of(context)
.extension<StackColors>()!
.background,
shadows: const [],
icon: SvgPicture.asset(
Assets.svg.copy,
width: 24,
height: 24,
color: Theme.of(context)
.extension<StackColors>()!
.topNavIconPrimary,
),
onPressed: () {
if (representative != null) {
_copy();
}
},
),
),
),
],
),
body: Padding(
padding: const EdgeInsets.only(
top: 12,
left: 16,
right: 16,
),
child: child,
),
),
),
),
child: ConditionalParent(
condition: isDesktop,
builder: (child) => DesktopDialog(
maxWidth: 600,
maxHeight: double.infinity,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(
left: 32,
),
child: Text(
"Change representative",
style: STextStyles.desktopH2(context),
),
),
DesktopDialogCloseButton(
onPressedOverride: Navigator.of(
context,
rootNavigator: true,
).pop,
),
],
),
AnimatedSize(
duration: const Duration(
milliseconds: 150,
),
child: Padding(
padding: const EdgeInsets.fromLTRB(32, 0, 32, 32),
child: child,
),
),
],
),
),
child: Column(
children: [
if (isDesktop) const SizedBox(height: 24),
ConditionalParent(
condition: !isDesktop,
builder: (child) => Expanded(
child: child,
),
child: FutureBuilder(
future: loadRepresentative(),
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
representative = snapshot.data!;
}
const height = 600.0;
Widget child;
if (representative == null) {
child = const SizedBox(
key: Key("loadingRepresentative"),
height: height,
child: Center(
child: LoadingIndicator(
width: 100,
),
),
);
} else {
child = Column(
children: [
ConditionalParent(
condition: !isDesktop,
builder: (child) => RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
child,
],
),
),
child: ConditionalParent(
condition: isDesktop,
builder: (child) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Current representative",
style: STextStyles.desktopTextExtraExtraSmall(
context),
),
const SizedBox(
height: 4,
),
Row(
children: [
child,
],
),
],
),
child: SelectableText(
representative!,
style: isDesktop
? STextStyles.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
)
: STextStyles.itemSubtitle12(context),
),
),
),
const SizedBox(
height: 24,
),
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
autocorrect: Util.isDesktop ? false : true,
enableSuggestions: Util.isDesktop ? false : true,
controller: _textController,
style: isDesktop
? STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveText,
height: 1.8,
)
: STextStyles.field(context),
focusNode: _textFocusNode,
decoration: standardInputDecoration(
"Enter new representative",
_textFocusNode,
context,
desktopMed: isDesktop,
).copyWith(
contentPadding: isDesktop
? const EdgeInsets.only(
left: 16,
top: 11,
bottom: 12,
right: 5,
)
: null,
suffixIcon: _textController.text.isNotEmpty
? Padding(
padding: const EdgeInsets.only(right: 0),
child: UnconstrainedBox(
child: Row(
children: [
TextFieldIconButton(
child: const XIcon(),
onTap: () async {
setState(() {
_textController.text = "";
});
},
),
],
),
),
)
: null,
),
),
),
if (isDesktop) const SizedBox(height: 60),
if (!isDesktop) const Spacer(),
PrimaryButton(
label: "Save",
onPressed: _save,
),
if (!isDesktop)
const SizedBox(
height: 16,
),
],
);
}
return AnimatedSwitcher(
duration: const Duration(
milliseconds: 200,
),
child: child,
);
},
),
),
],
),
),
);
}
}

View file

@ -100,7 +100,7 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
message: "Loading ${widget.token.name}",
);
if (!success) {
if (!success!) {
return;
}

View file

@ -52,6 +52,7 @@ class WalletSummary extends StatelessWidget {
walletId: walletId,
width: constraints.maxWidth,
height: constraints.maxHeight,
isFavorite: false,
),
Positioned.fill(
child: Padding(

View file

@ -358,7 +358,6 @@ class _TransactionDetailsViewState
final currentHeight = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId).currentHeight));
print("THIS TRANSACTION IS $_transaction");
return ConditionalParent(
@ -474,7 +473,9 @@ class _TransactionDetailsViewState
),
SelectableText(
_transaction.isCancelled
? "Cancelled"
? coin == Coin.ethereum
? "Failed"
: "Cancelled"
: whatIsIt(
_transaction,
currentHeight,
@ -585,7 +586,9 @@ class _TransactionDetailsViewState
// child:
SelectableText(
_transaction.isCancelled
? "Cancelled"
? coin == Coin.ethereum
? "Failed"
: "Cancelled"
: whatIsIt(
_transaction,
currentHeight,
@ -781,8 +784,8 @@ class _TransactionDetailsViewState
isDesktop
? const _Divider()
: const SizedBox(
height: 12,
),
height: 12,
),
if (coin == Coin.epicCash)
RoundedWhiteContainer(
padding: isDesktop
@ -790,22 +793,22 @@ class _TransactionDetailsViewState
: const EdgeInsets.all(12),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
CrossAxisAlignment.start,
children: [
Text(
"On chain note",
style: isDesktop
? STextStyles
.desktopTextExtraExtraSmall(
context)
.desktopTextExtraExtraSmall(
context)
: STextStyles.itemSubtitle(
context),
context),
),
const SizedBox(
height: 8,
@ -814,18 +817,16 @@ class _TransactionDetailsViewState
_transaction.otherData ?? "",
style: isDesktop
? STextStyles
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(
context)
.extension<
StackColors>()!
.textDark,
)
: STextStyles
.itemSubtitle12(
context),
.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<
StackColors>()!
.textDark,
)
: STextStyles.itemSubtitle12(
context),
),
],
),
@ -854,7 +855,9 @@ class _TransactionDetailsViewState
MainAxisAlignment.spaceBetween,
children: [
Text(
(coin == Coin.epicCash) ? "Local Note" : "Note ",
(coin == Coin.epicCash)
? "Local Note"
: "Note ",
style: isDesktop
? STextStyles
.desktopTextExtraExtraSmall(
@ -923,7 +926,9 @@ class _TransactionDetailsViewState
notesServiceChangeNotifierProvider(
walletId)
.select((value) => value.getNoteFor(
txid: (coin == Coin.epicCash)? _transaction.slateId! : _transaction.txid ))),
txid: (coin == Coin.epicCash)
? _transaction.slateId!
: _transaction.txid))),
builder: (builderContext,
AsyncSnapshot<String> snapshot) {
if (snapshot.connectionState ==

View file

@ -149,6 +149,7 @@ class _FavoriteCardState extends ConsumerState<FavoriteCard> {
walletId: widget.walletId,
width: widget.width,
height: widget.height,
isFavorite: true,
),
child: Padding(
padding: const EdgeInsets.all(12.0),

View file

@ -13,7 +13,8 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/xpub_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart';
import 'package:stackwallet/pages_desktop_specific/addresses/desktop_wallet_addresses_view.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_delete_wallet_dialog.dart';
import 'package:stackwallet/providers/providers.dart';
@ -21,11 +22,13 @@ import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
enum _WalletOptions {
addressList,
deleteWallet,
changeRepresentative,
showXpub;
String get prettyName {
@ -34,6 +37,8 @@ enum _WalletOptions {
return "Address list";
case _WalletOptions.deleteWallet:
return "Delete wallet";
case _WalletOptions.changeRepresentative:
return "Change representative";
case _WalletOptions.showXpub:
return "Show xPub";
}
@ -70,6 +75,9 @@ class WalletOptionsButton extends StatelessWidget {
onAddressListPressed: () async {
Navigator.of(context).pop(_WalletOptions.addressList);
},
onChangeRepPressed: () async {
Navigator.of(context).pop(_WalletOptions.changeRepresentative);
},
onShowXpubPressed: () async {
Navigator.of(context).pop(_WalletOptions.showXpub);
},
@ -134,6 +142,32 @@ class WalletOptionsButton extends StatelessWidget {
),
);
if (result == true) {
if (context.mounted) {
Navigator.of(context).pop();
}
}
break;
case _WalletOptions.changeRepresentative:
final result = await showDialog<bool?>(
context: context,
barrierDismissible: false,
builder: (context) => Navigator(
initialRoute: ChangeRepresentativeView.routeName,
onGenerateRoute: RouteGenerator.generateRoute,
onGenerateInitialRoutes: (_, __) {
return [
RouteGenerator.generateRoute(
RouteSettings(
name: ChangeRepresentativeView.routeName,
arguments: walletId,
),
),
];
},
),
);
if (result == true) {
if (context.mounted) {
Navigator.of(context).pop();
@ -171,18 +205,24 @@ class WalletOptionsPopupMenu extends ConsumerWidget {
required this.onDeletePressed,
required this.onAddressListPressed,
required this.onShowXpubPressed,
required this.onChangeRepPressed,
required this.walletId,
}) : super(key: key);
final VoidCallback onDeletePressed;
final VoidCallback onAddressListPressed;
final VoidCallback onShowXpubPressed;
final VoidCallback onChangeRepPressed;
final String walletId;
@override
Widget build(BuildContext context, WidgetRef ref) {
final bool xpubEnabled = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId).hasXPub));
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId)));
final bool xpubEnabled = manager.hasXPub;
final bool canChangeRep =
manager.coin == Coin.nano || manager.coin == Coin.banano;
return Stack(
children: [
@ -237,6 +277,43 @@ class WalletOptionsPopupMenu extends ConsumerWidget {
),
),
),
if (canChangeRep)
const SizedBox(
height: 8,
),
if (canChangeRep)
TransparentButton(
onPressed: onChangeRepPressed,
child: Padding(
padding: const EdgeInsets.all(8),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SvgPicture.asset(
Assets.svg.eye,
width: 20,
height: 20,
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconLeft,
),
const SizedBox(width: 14),
Expanded(
child: Text(
_WalletOptions.changeRepresentative.prettyName,
style: STextStyles.desktopTextExtraExtraSmall(
context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark,
),
),
),
],
),
),
),
if (xpubEnabled)
const SizedBox(
height: 8,

View file

@ -125,7 +125,7 @@ class _CreatePasswordViewState extends ConsumerState<CreatePasswordView> {
}
}
if (!widget.restoreFromSWB) {
if (!widget.restoreFromSWB && mounted) {
unawaited(showFloatingFlushBar(
type: FlushBarType.success,
message: "Your password is set up",

View file

@ -84,10 +84,10 @@ class _DesktopLoginViewState extends ConsumerState<DesktopLoginView> {
unawaited(
showDialog(
context: context,
builder: (context) => Column(
builder: (context) => const Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
children: [
LoadingIndicator(
width: 200,
height: 200,

View file

@ -13,8 +13,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/exchange/active_pair.dart';
import 'package:stackwallet/models/exchange/response_objects/estimate.dart';
import 'package:stackwallet/models/exchange/response_objects/range.dart';
import 'package:stackwallet/providers/global/locale_provider.dart';
import 'package:stackwallet/services/exchange/exchange.dart';
import 'package:stackwallet/services/exchange/exchange_response.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_unit.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/exchange_rate_type_enum.dart';
import 'package:tuple/tuple.dart';
@ -44,7 +48,22 @@ final efSendAmountStringProvider = StateProvider<String>((ref) {
if (refreshing && reversed) {
return "-";
} else {
return ref.watch(efSendAmountProvider)?.toString() ?? "";
final decimal = ref.watch(efSendAmountProvider);
String string = "";
if (decimal != null) {
final amount = Amount.fromDecimal(decimal, fractionDigits: decimal.scale);
final locale = ref.watch(localeServiceChangeNotifierProvider).locale;
string = AmountUnit.normal.displayAmount(
amount: amount,
locale: locale,
coin: Coin
.nano, // use nano just to ensure decimal.scale < Coin.value.decimals
withUnitName: false,
maxDecimalPlaces: decimal.scale,
);
}
return string;
}
});
final efReceiveAmountStringProvider = StateProvider<String>((ref) {
@ -54,7 +73,22 @@ final efReceiveAmountStringProvider = StateProvider<String>((ref) {
if (refreshing && reversed == false) {
return "-";
} else {
return ref.watch(efReceiveAmountProvider)?.toString() ?? "";
final decimal = ref.watch(efReceiveAmountProvider);
String string = "";
if (decimal != null) {
final amount = Amount.fromDecimal(decimal, fractionDigits: decimal.scale);
final locale = ref.watch(localeServiceChangeNotifierProvider).locale;
string = AmountUnit.normal.displayAmount(
amount: amount,
locale: locale,
coin: Coin
.nano, // use nano just to ensure decimal.scale < Coin.value.decimals
withUnitName: false,
maxDecimalPlaces: decimal.scale,
);
}
return string;
}
});

View file

@ -103,14 +103,15 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/support_vi
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/xpub_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart';
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart';
import 'package:stackwallet/pages/stack_privacy_calls.dart';
import 'package:stackwallet/pages/token_view/my_tokens_view.dart';
import 'package:stackwallet/pages/token_view/token_contract_details_view.dart';
@ -564,6 +565,20 @@ class RouteGenerator {
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
case ChangeRepresentativeView.routeName:
if (args is String) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => ChangeRepresentativeView(
walletId: args,
),
settings: RouteSettings(
name: settings.name,
),
);
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
case AppearanceSettingsView.routeName:
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,

View file

@ -14,9 +14,9 @@ import 'package:stackwallet/services/event_bus/events/global/node_connection_sta
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/coin_control_interface.dart';
import 'package:stackwallet/services/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/nano_api.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
@ -32,8 +32,7 @@ const int MINIMUM_CONFIRMATIONS = 1;
const String DEFAULT_REPRESENTATIVE =
"ban_1ka1ium4pfue3uxtntqsrib8mumxgazsjf58gidh1xeo5te3whsq8z476goo";
class BananoWallet extends CoinServiceAPI
with WalletCache, WalletDB, CoinControlInterface {
class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB {
BananoWallet({
required String walletId,
required String walletName,
@ -925,4 +924,51 @@ class BananoWallet extends CoinServiceAPI
);
await updateCachedChainHeight(height ?? 0);
}
Future<String> getCurrentRepresentative() async {
final serverURI = Uri.parse(getCurrentNode().host);
final address = await currentReceivingAddress;
final response = await NanoAPI.getAccountInfo(
server: serverURI,
representative: true,
account: address,
);
return response.accountInfo?.representative ?? DEFAULT_REPRESENTATIVE;
}
Future<bool> changeRepresentative(String newRepresentative) async {
try {
final serverURI = Uri.parse(getCurrentNode().host);
final balance = this.balance.spendable.raw.toString();
final String privateKey = await getPrivateKeyFromMnemonic();
final address = await currentReceivingAddress;
final response = await NanoAPI.getAccountInfo(
server: serverURI,
representative: true,
account: address,
);
if (response.accountInfo == null) {
throw response.exception ?? Exception("Failed to get account info");
}
final work = await requestWork(response.accountInfo!.frontier);
return await NanoAPI.changeRepresentative(
server: serverURI,
accountType: NanoAccountType.BANANO,
account: address,
newRepresentative: newRepresentative,
previousBlock: response.accountInfo!.frontier,
balance: balance,
privateKey: privateKey,
work: work!,
);
} catch (_) {
rethrow;
}
}
}

View file

@ -1023,6 +1023,7 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
final response = await EthereumAPI.getEthTransactions(
address: thisAddress,
firstBlock: isRescan ? 0 : firstBlock,
includeTokens: true,
);
if (response.value == null) {
@ -1057,8 +1058,10 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
txFailed = true;
}
isIncoming = false;
} else {
} else if (checksumEthereumAddress(element.to) == thisAddress) {
isIncoming = true;
} else {
continue;
}
//Calculate fees (GasLimit * gasPrice)

File diff suppressed because it is too large Load diff

View file

@ -24,9 +24,9 @@ import 'package:stackwallet/services/event_bus/events/global/node_connection_sta
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/coin_control_interface.dart';
import 'package:stackwallet/services/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/nano_api.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
@ -42,8 +42,7 @@ const int MINIMUM_CONFIRMATIONS = 1;
const String DEFAULT_REPRESENTATIVE =
"nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579";
class NanoWallet extends CoinServiceAPI
with WalletCache, WalletDB, CoinControlInterface {
class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB {
NanoWallet({
required String walletId,
required String walletName,
@ -937,4 +936,51 @@ class NanoWallet extends CoinServiceAPI
);
await updateCachedChainHeight(height ?? 0);
}
Future<String> getCurrentRepresentative() async {
final serverURI = Uri.parse(getCurrentNode().host);
final address = await currentReceivingAddress;
final response = await NanoAPI.getAccountInfo(
server: serverURI,
representative: true,
account: address,
);
return response.accountInfo?.representative ?? DEFAULT_REPRESENTATIVE;
}
Future<bool> changeRepresentative(String newRepresentative) async {
try {
final serverURI = Uri.parse(getCurrentNode().host);
final balance = this.balance.spendable.raw.toString();
final String privateKey = await getPrivateKeyFromMnemonic();
final address = await currentReceivingAddress;
final response = await NanoAPI.getAccountInfo(
server: serverURI,
representative: true,
account: address,
);
if (response.accountInfo == null) {
throw response.exception ?? Exception("Failed to get account info");
}
final work = await requestWork(response.accountInfo!.frontier);
return await NanoAPI.changeRepresentative(
server: serverURI,
accountType: NanoAccountType.NANO,
account: address,
newRepresentative: newRepresentative,
previousBlock: response.accountInfo!.frontier,
balance: balance,
privateKey: privateKey,
work: work!,
);
} catch (_) {
rethrow;
}
}
}

View file

@ -10,7 +10,6 @@
import 'dart:convert';
import 'package:decimal/decimal.dart';
import 'package:http/http.dart';
import 'package:stackwallet/dto/ethereum/eth_token_tx_dto.dart';
import 'package:stackwallet/dto/ethereum/eth_token_tx_extra_dto.dart';
@ -50,6 +49,7 @@ abstract class EthereumAPI {
static Future<EthereumResponse<List<EthTxDTO>>> getEthTransactions({
required String address,
int firstBlock = 0,
bool includeTokens = false,
}) async {
try {
final response = await get(
@ -67,7 +67,7 @@ abstract class EthereumAPI {
for (final map in list!) {
final txn = EthTxDTO.fromMap(Map<String, dynamic>.from(map as Map));
if (txn.hasToken == 0) {
if (txn.hasToken == 0 || includeTokens) {
txns.add(txn);
}
}
@ -76,9 +76,11 @@ abstract class EthereumAPI {
null,
);
} else {
throw EthApiException(
"getEthTransactions($address) response is empty but status code is "
"${response.statusCode}",
// nice that the api returns an empty body instead of being
// consistent and returning a json object with no transactions
return EthereumResponse(
[],
null,
);
}
} else {
@ -196,9 +198,11 @@ abstract class EthereumAPI {
null,
);
} else {
throw EthApiException(
"getEthTransactionNonces($txns) response is empty but status code is "
"${response.statusCode}",
// nice that the api returns an empty body instead of being
// consistent and returning a json object with no transactions
return EthereumResponse(
[],
null,
);
}
} else {
@ -252,13 +256,13 @@ abstract class EthereumAPI {
);
} else {
throw EthApiException(
"getEthTransaction($txids) response is empty but status code is "
"getEthTokenTransactionsByTxids($txids) response is empty but status code is "
"${response.statusCode}",
);
}
} else {
throw EthApiException(
"getEthTransaction($txids) failed with status code: "
"getEthTokenTransactionsByTxids($txids) failed with status code: "
"${response.statusCode}",
);
}
@ -269,7 +273,7 @@ abstract class EthereumAPI {
);
} catch (e, s) {
Logging.instance.log(
"getEthTransaction($txids): $e\n$s",
"getEthTokenTransactionsByTxids($txids): $e\n$s",
level: LogLevel.Error,
);
return EthereumResponse(
@ -307,9 +311,11 @@ abstract class EthereumAPI {
null,
);
} else {
throw EthApiException(
"getTokenTransactions($address, $tokenContractAddress) response is empty but status code is "
"${response.statusCode}",
// nice that the api returns an empty body instead of being
// consistent and returning a json object with no transactions
return EthereumResponse(
[],
null,
);
}
} else {
@ -424,10 +430,10 @@ abstract class EthereumAPI {
final map = json["data"].first as Map;
final balance =
Decimal.tryParse(map["balance"].toString()) ?? Decimal.zero;
BigInt.tryParse(map["units"].toString()) ?? BigInt.zero;
return EthereumResponse(
Amount.fromDecimal(balance, fractionDigits: map["decimals"] as int),
Amount(rawValue: balance, fractionDigits: map["decimals"] as int),
null,
);
} else {

View file

@ -135,6 +135,9 @@ class ExchangeDataLoadingService {
Future<void> loadAll() async {
if (!_locked) {
_locked = true;
if (_isar == null) {
await initDB();
}
Logging.instance.log(
"ExchangeDataLoadingService.loadAll starting...",
level: LogLevel.Info,

View file

@ -21,7 +21,7 @@ class LocaleService extends ChangeNotifier {
Future<void> loadLocale({bool notify = true}) async {
_locale = Platform.isWindows
? "en_US"
: await Devicelocale.currentLocale ?? "en_US";
: (await Devicelocale.currentAsLocale)?.toString() ?? "en_US";
if (notify) {
notifyListeners();
}

View file

@ -1,61 +0,0 @@
/*
* This file is part of Stack Wallet.
*
* Copyright (c) 2023 Cypher Stack
* All Rights Reserved.
* The code is distributed under GPLv3 license, see LICENSE file for details.
* Generated by Cypher Stack on 2023-05-26
*
*/
import 'package:stackwallet/db/hive/db.dart';
mixin FiroHive {
late final String _walletId;
void initFiroHive(String walletId) {
_walletId = walletId;
}
// jindex
List? firoGetJIndex() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "jindex") as List?;
}
Future<void> firoUpdateJIndex(List jIndex) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "jindex",
value: jIndex,
);
}
// _lelantus_coins
List? firoGetLelantusCoins() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "_lelantus_coins")
as List?;
}
Future<void> firoUpdateLelantusCoins(List lelantusCoins) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "_lelantus_coins",
value: lelantusCoins,
);
}
// mintIndex
int firoGetMintIndex() {
return DB.instance.get<dynamic>(boxName: _walletId, key: "mintIndex")
as int? ??
0;
}
Future<void> firoUpdateMintIndex(int mintIndex) async {
await DB.instance.put<dynamic>(
boxName: _walletId,
key: "mintIndex",
value: mintIndex,
);
}
}

130
lib/services/nano_api.dart Normal file
View file

@ -0,0 +1,130 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:nanodart/nanodart.dart';
class NanoAPI {
static Future<
({
NAccountInfo? accountInfo,
Exception? exception,
})> getAccountInfo({
required Uri server,
required bool representative,
required String account,
}) async {
NAccountInfo? accountInfo;
Exception? exception;
try {
final response = await http.post(
server,
headers: {
"Content-Type": "application/json",
},
body: jsonEncode({
"action": "account_info",
"representative": "true",
"account": account,
}),
);
final map = jsonDecode(response.body);
if (map is Map && map["error"] != null) {
throw Exception(map["error"].toString());
}
accountInfo = NAccountInfo(
frontier: map["frontier"] as String,
representative: map["representative"] as String,
);
} on Exception catch (e) {
exception = e;
} catch (e) {
exception = Exception(e.toString());
}
return (accountInfo: accountInfo, exception: exception);
}
static Future<bool> changeRepresentative({
required Uri server,
required int accountType,
required String account,
required String newRepresentative,
required String previousBlock,
required String balance,
required String privateKey,
required String work,
}) async {
Map<String, String> block = {
"type": "state",
"account": account,
"previous": previousBlock,
"representative": newRepresentative,
"balance": balance,
"link":
"0000000000000000000000000000000000000000000000000000000000000000",
"work": work,
};
final String hash;
try {
hash = NanoBlocks.computeStateHash(
accountType,
account,
previousBlock,
newRepresentative,
BigInt.parse(balance),
block["link"] as String,
);
} catch (e) {
if (e is RangeError) {
throw Exception("Invalid representative format");
}
rethrow;
}
final signature = NanoSignatures.signBlock(hash, privateKey);
block["signature"] = signature;
final map = await postBlock(server: server, block: block);
if (map is Map && map["error"] != null) {
throw Exception(map["error"].toString());
}
return map["error"] == null;
}
// TODO: GET RID OF DYNAMIC AND USED TYPED DATA
static Future<dynamic> postBlock({
required Uri server,
required Map<String, dynamic> block,
}) async {
final response = await http.post(
server,
headers: {
"Content-Type": "application/json",
},
body: jsonEncode({
"action": "process",
"json_block": "true",
"subtype": "change",
"block": block,
}),
);
return jsonDecode(response.body);
}
}
class NAccountInfo {
final String frontier;
final String representative;
NAccountInfo({required this.frontier, required this.representative});
}

View file

@ -26,6 +26,7 @@ class NotificationApi {
priority: Priority.high,
ticker: 'ticker'),
iOS: IOSNotificationDetails(),
macOS: MacOSNotificationDetails(),
);
}
@ -34,8 +35,13 @@ class NotificationApi {
const iOS = IOSInitializationSettings();
const linux = LinuxInitializationSettings(
defaultActionName: "temporary_stack_wallet");
const settings =
InitializationSettings(android: android, iOS: iOS, linux: linux);
const macOS = MacOSInitializationSettings();
const settings = InitializationSettings(
android: android,
iOS: iOS,
linux: linux,
macOS: macOS,
);
await _notifications.initialize(
settings,
onSelectNotification: (payload) async {
@ -71,8 +77,10 @@ class NotificationApi {
final id = prefs.currentNotificationId;
String confirms = "";
if (txid != null) {
confirms = " (${confirmations!}/${requiredConfirmations!})";
if (txid != null &&
confirmations != null &&
requiredConfirmations != null) {
confirms = " ($confirmations/$requiredConfirmations)";
}
final NotificationModel model = NotificationModel(

View file

@ -22,3 +22,14 @@ final coinCardProvider = Provider.family<String?, Coin>((ref, coin) {
return null;
}
});
final coinCardFavoritesProvider = Provider.family<String?, Coin>((ref, coin) {
final assets = ref.watch(themeAssetsProvider);
if (assets is ThemeAssetsV3) {
return assets.coinCardFavoritesImages?[coin.mainNetVersion] ??
assets.coinCardImages?[coin.mainNetVersion];
} else {
return null;
}
});

View file

@ -10,11 +10,11 @@
import 'dart:convert';
import 'package:bitbox/bitbox.dart' as bitbox;
import 'package:bitcoindart/bitcoindart.dart';
import 'package:crypto/crypto.dart';
import 'package:flutter_libepiccash/epic_cash.dart';
import 'package:nanodart/nanodart.dart';
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/coins/ecash/ecash_wallet.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
@ -64,7 +64,27 @@ class AddressUtils {
case Coin.litecoin:
return Address.validateAddress(address, litecoin);
case Coin.bitcoincash:
return Address.validateAddress(address, bitcoincash);
try {
// 0 for bitcoincash: address scheme, 1 for legacy address
final format = bitbox.Address.detectFormat(address);
if (coin == Coin.bitcoincashTestnet) {
return true;
}
if (format == bitbox.Address.formatCashAddr) {
String addr = address;
if (addr.contains(":")) {
addr = addr.split(":").last;
}
return addr.startsWith("q");
} else {
return address.startsWith("1");
}
} catch (e) {
return false;
}
case Coin.dogecoin:
return Address.validateAddress(address, dogecoin);
case Coin.epicCash:
@ -94,7 +114,27 @@ class AddressUtils {
case Coin.litecoinTestNet:
return Address.validateAddress(address, litecointestnet);
case Coin.bitcoincashTestnet:
return Address.validateAddress(address, bitcoincashtestnet);
try {
// 0 for bitcoincash: address scheme, 1 for legacy address
final format = bitbox.Address.detectFormat(address);
if (coin == Coin.bitcoincashTestnet) {
return true;
}
if (format == bitbox.Address.formatCashAddr) {
String addr = address;
if (addr.contains(":")) {
addr = addr.split(":").last;
}
return addr.startsWith("q");
} else {
return address.startsWith("1");
}
} catch (e) {
return false;
}
case Coin.firoTestNet:
return Address.validateAddress(address, firoTestNetwork);
case Coin.dogecoinTestNet:

View file

@ -11,8 +11,7 @@
import 'dart:convert';
import 'package:decimal/decimal.dart';
import 'package:intl/number_symbols.dart';
import 'package:intl/number_symbols_data.dart';
import 'package:stackwallet/utilities/util.dart';
class Amount {
Amount({
@ -52,8 +51,7 @@ class Amount {
}
// get number symbols for decimal place and group separator
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
final numberSymbols = Util.getSymbolsFor(locale: locale);
final groupSeparator = numberSymbols?.GROUP_SEP ?? ",";
final decimalSeparator = numberSymbols?.DECIMAL_SEP ?? ".";
@ -101,8 +99,7 @@ class Amount {
final wholeNumber = decimal.truncate();
// get number symbols for decimal place and group separator
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
final numberSymbols = Util.getSymbolsFor(locale: locale);
final String separator = numberSymbols?.DECIMAL_SEP ?? ".";

View file

@ -22,11 +22,13 @@ final pMaxDecimals = Provider.family<int, Coin>(
);
final pAmountFormatter = Provider.family<AmountFormatter, Coin>((ref, coin) {
final locale = ref.watch(
localeServiceChangeNotifierProvider.select((value) => value.locale),
);
return AmountFormatter(
unit: ref.watch(pAmountUnit(coin)),
locale: ref.watch(
localeServiceChangeNotifierProvider.select((value) => value.locale),
),
locale: locale,
coin: coin,
maxDecimals: ref.watch(pMaxDecimals(coin)),
);
@ -68,6 +70,11 @@ class AmountFormatter {
String string, {
EthContract? ethContract,
}) {
return unit.tryParse(string, locale: locale, coin: coin);
return unit.tryParse(
string,
locale: locale,
coin: coin,
tokenContract: ethContract,
);
}
}

View file

@ -1,9 +1,8 @@
import 'dart:math';
import 'package:flutter/services.dart';
import 'package:intl/number_symbols.dart';
import 'package:intl/number_symbols_data.dart';
import 'package:stackwallet/utilities/amount/amount_unit.dart';
import 'package:stackwallet/utilities/util.dart';
class AmountInputFormatter extends TextInputFormatter {
final int decimals;
@ -20,8 +19,7 @@ class AmountInputFormatter extends TextInputFormatter {
TextEditingValue formatEditUpdate(
TextEditingValue oldValue, TextEditingValue newValue) {
// get number symbols for decimal place and group separator
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
final numberSymbols = Util.getSymbolsFor(locale: locale);
final decimalSeparator = numberSymbols?.DECIMAL_SEP ?? ".";
final groupSeparator = numberSymbols?.GROUP_SEP ?? ",";

View file

@ -11,11 +11,10 @@
import 'dart:math' as math;
import 'package:decimal/decimal.dart';
import 'package:intl/number_symbols.dart';
import 'package:intl/number_symbols_data.dart';
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/util.dart';
// preserve index order as index is used to store value in preferences
enum AmountUnit {
@ -169,6 +168,7 @@ extension AmountUnitExt on AmountUnit {
required String locale,
required Coin coin,
EthContract? tokenContract,
bool overrideWithDecimalPlacesFromString = false,
}) {
final precisionLost = value.startsWith("~");
@ -188,8 +188,7 @@ extension AmountUnitExt on AmountUnit {
}
// get number symbols for decimal place and group separator
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
final numberSymbols = Util.getSymbolsFor(locale: locale);
final groupSeparator = numberSymbols?.GROUP_SEP ?? ",";
final decimalSeparator = numberSymbols?.DECIMAL_SEP ?? ".";
@ -203,7 +202,9 @@ extension AmountUnitExt on AmountUnit {
return null;
}
final decimalPlaces = tokenContract?.decimals ?? coin.decimals;
final decimalPlaces = overrideWithDecimalPlacesFromString
? decimal.scale
: tokenContract?.decimals ?? coin.decimals;
final realShift = math.min(shift, decimalPlaces);
return decimal.shift(0 - realShift).toAmount(fractionDigits: decimalPlaces);
@ -237,8 +238,7 @@ extension AmountUnitExt on AmountUnit {
String returnValue = wholeNumber.toString();
// get number symbols for decimal place and group separator
final numberSymbols = numberFormatSymbols[locale] as NumberSymbols? ??
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
final numberSymbols = Util.getSymbolsFor(locale: locale);
// insert group separator
final regex = RegExp(r'\B(?=(\d{3})+(?!\d))');

View file

@ -58,7 +58,7 @@ abstract class Constants {
// Enable Logger.print statements
static const bool disableLogger = false;
static const int currentDataVersion = 10;
static const int currentDataVersion = 11;
static const int rescanV1 = 1;

View file

@ -180,7 +180,6 @@ class DbVersionMigrator with WalletDB {
// clear possible broken firo cache
await DB.instance.clearSharedTransactionCache(coin: Coin.firo);
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 4);
@ -343,12 +342,85 @@ class DbVersionMigrator with WalletDB {
// try to continue migrating
return await migrate(10, secureStore: secureStore);
case 10:
// migrate
await _v10(secureStore);
// update version
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 11);
// try to continue migrating
return await migrate(11, secureStore: secureStore);
default:
// finally return
return;
}
}
Future<void> _v10(SecureStorageInterface secureStore) async {
await Hive.openBox<dynamic>(DB.boxNameAllWalletsData);
await Hive.openBox<dynamic>(DB.boxNamePrefs);
final walletsService = WalletsService(secureStorageInterface: secureStore);
final prefs = Prefs.instance;
final walletInfoList = await walletsService.walletNames;
await prefs.init();
await MainDB.instance.initMainDB();
for (final walletId in walletInfoList.keys) {
final info = walletInfoList[walletId]!;
assert(info.walletId == walletId);
if (info.coin == Coin.firo &&
MainDB.instance.isar.lelantusCoins
.where()
.walletIdEqualTo(walletId)
.countSync() ==
0) {
final walletBox = await Hive.openBox<dynamic>(walletId);
final hiveLCoins = DB.instance.get<dynamic>(
boxName: walletId,
key: "_lelantus_coins",
) as List? ??
[];
final jindexes = (DB.instance
.get<dynamic>(boxName: walletId, key: "jindex") as List? ??
[])
.cast<int>();
final List<isar_models.LelantusCoin> coins = [];
for (final e in hiveLCoins) {
final map = e as Map;
final lcoin = map.values.first as LelantusCoin;
final isJMint = jindexes.contains(lcoin.index);
final coin = isar_models.LelantusCoin(
walletId: walletId,
txid: lcoin.txId,
value: lcoin.value.toString(),
mintIndex: lcoin.index,
anonymitySetId: lcoin.anonymitySetId,
isUsed: lcoin.isUsed,
isJMint: isJMint,
otherData: null,
);
coins.add(coin);
}
if (coins.isNotEmpty) {
await MainDB.instance.isar.writeTxn(() async {
await MainDB.instance.isar.lelantusCoins.putAll(coins);
});
}
}
}
}
Future<void> _v4(SecureStorageInterface secureStore) async {
await Hive.openBox<dynamic>(DB.boxNameAllWalletsData);
await Hive.openBox<dynamic>(DB.boxNamePrefs);

View file

@ -12,15 +12,17 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
Future<T> showLoading<T>({
Future<T?> showLoading<T>({
required Future<T> whileFuture,
required BuildContext context,
required String message,
String? subMessage,
bool isDesktop = false,
bool opaqueBG = false,
void Function(Exception)? onException,
}) async {
unawaited(
showDialog<void>(
@ -43,10 +45,24 @@ Future<T> showLoading<T>({
),
);
final result = await whileFuture;
Exception? ex;
T? result;
try {
result = await whileFuture;
} catch (e, s) {
Logging.instance.log(
"showLoading caught: $e\n$s",
level: LogLevel.Warning,
);
ex = e is Exception ? e : Exception(e.toString());
}
if (context.mounted) {
Navigator.of(context, rootNavigator: isDesktop).pop();
if (ex != null) {
onException?.call(ex);
}
}
return result;

View file

@ -27,8 +27,8 @@ abstract class StackFileSystem {
} else if (Platform.isWindows) {
appDirectory = await getApplicationSupportDirectory();
} else if (Platform.isMacOS) {
// currently run in ipad mode??
throw Exception("Unsupported platform");
appDirectory = await getLibraryDirectory();
appDirectory = Directory("${appDirectory.path}/stackwallet");
} else if (Platform.isIOS) {
// todo: check if we need different behaviour here
if (Util.isDesktop) {

View file

@ -14,11 +14,21 @@ import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/material.dart';
import 'package:intl/number_symbols.dart';
import 'package:intl/number_symbols_data.dart';
abstract class Util {
static Directory? libraryPath;
static double? screenWidth;
static NumberSymbols? getSymbolsFor({required String locale}) {
return numberFormatSymbols[locale] as NumberSymbols? ??
numberFormatSymbols[locale.replaceAll("-", "_")] as NumberSymbols? ??
numberFormatSymbols[locale.substring(3).toLowerCase()]
as NumberSymbols? ??
numberFormatSymbols[locale.substring(0, 2)] as NumberSymbols?;
}
static bool get isDesktop {
// special check for running on linux based phones
if (Platform.isLinux && screenWidth != null && screenWidth! < 800) {

View file

@ -25,11 +25,13 @@ class CoinCard extends ConsumerWidget {
required this.walletId,
required this.width,
required this.height,
required this.isFavorite,
});
final String walletId;
final double width;
final double height;
final bool isFavorite;
@override
Widget build(BuildContext context, WidgetRef ref) {
@ -38,7 +40,7 @@ class CoinCard extends ConsumerWidget {
.select((value) => value.getManager(walletId).coin),
);
final bool hasCardImageBg = ref.watch(coinCardProvider(coin)) != null;
final bool hasCardImageBg = (isFavorite) ? ref.watch(coinCardFavoritesProvider(coin)) != null : ref.watch(coinCardProvider(coin)) != null;
return Stack(
children: [
@ -54,7 +56,9 @@ class CoinCard extends ConsumerWidget {
fit: BoxFit.cover,
image: FileImage(
File(
ref.watch(coinCardProvider(coin))!,
(isFavorite)
? ref.watch(coinCardFavoritesProvider(coin))!
: ref.watch(coinCardProvider(coin))!,
),
),
),

View file

@ -13,6 +13,7 @@ import 'dart:async';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/notifications_api.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -84,6 +85,8 @@ class _CryptoNotificationsState extends ConsumerState<CryptoNotifications> {
@override
void initState() {
NotificationApi.prefs = ref.read(prefsChangeNotifierProvider);
NotificationApi.notificationsService = ref.read(notificationsProvider);
_streamSubscription = CryptoNotificationsEventBus.instance
.on<CryptoNotificationEvent>()
.listen(

View file

@ -230,7 +230,9 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
fit: BoxFit.scaleDown,
child: Text(
_transaction.isCancelled
? "Cancelled"
? coin == Coin.ethereum
? "Failed"
: "Cancelled"
: whatIsIt(
_transaction.type,
coin,

View file

@ -140,7 +140,7 @@ class SimpleWalletCard extends ConsumerWidget {
isDesktop: Util.isDesktop,
);
if (!success) {
if (!success!) {
// TODO: show error dialog here?
Logging.instance.log(
"Failed to load token wallet for $contract",

View file

@ -6,6 +6,9 @@ import FlutterMacOS
import Foundation
import connectivity_plus
import cw_monero
import cw_shared_external
import cw_wownero
import desktop_drop
import device_info_plus
import devicelocale
@ -13,10 +16,10 @@ import flutter_libepiccash
import flutter_local_notifications
import flutter_secure_storage_macos
import isar_flutter_libs
import lelantus
import package_info_plus
import path_provider_foundation
import share_plus
import shared_preferences_foundation
import stack_wallet_backup
import url_launcher_macos
import wakelock_macos
@ -24,6 +27,9 @@ import window_size
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin"))
CwSharedExternalPlugin.register(with: registry.registrar(forPlugin: "CwSharedExternalPlugin"))
CwWowneroPlugin.register(with: registry.registrar(forPlugin: "CwWowneroPlugin"))
DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
@ -31,10 +37,10 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin"))
LelantusPlugin.register(with: registry.registrar(forPlugin: "LelantusPlugin"))
FLTPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlusPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
StackWalletBackupPlugin.register(with: registry.registrar(forPlugin: "StackWalletBackupPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
WakelockMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockMacosPlugin"))

View file

@ -1,4 +1,4 @@
platform :osx, '10.11'
platform :osx, '10.14'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@ -31,6 +31,9 @@ target 'Runner' do
use_modular_headers!
flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|

View file

@ -1,24 +1,76 @@
PODS:
- connectivity_plus_macos (0.0.1):
- connectivity_plus (0.0.1):
- FlutterMacOS
- ReachabilitySwift
- cw_monero (0.0.1):
- cw_monero/Boost (= 0.0.1)
- cw_monero/Monero (= 0.0.1)
- cw_monero/OpenSSL (= 0.0.1)
- cw_monero/Sodium (= 0.0.1)
- cw_monero/Unbound (= 0.0.1)
- FlutterMacOS
- cw_monero/Boost (0.0.1):
- FlutterMacOS
- cw_monero/Monero (0.0.1):
- FlutterMacOS
- cw_monero/OpenSSL (0.0.1):
- FlutterMacOS
- cw_monero/Sodium (0.0.1):
- FlutterMacOS
- cw_monero/Unbound (0.0.1):
- FlutterMacOS
- cw_shared_external (0.0.1):
- cw_shared_external/Boost (= 0.0.1)
- cw_shared_external/OpenSSL (= 0.0.1)
- cw_shared_external/Sodium (= 0.0.1)
- FlutterMacOS
- cw_shared_external/Boost (0.0.1):
- FlutterMacOS
- cw_shared_external/OpenSSL (0.0.1):
- FlutterMacOS
- cw_shared_external/Sodium (0.0.1):
- FlutterMacOS
- cw_wownero (0.0.1):
- cw_wownero/Boost (= 0.0.1)
- cw_wownero/OpenSSL (= 0.0.1)
- cw_wownero/Sodium (= 0.0.1)
- cw_wownero/Unbound (= 0.0.1)
- cw_wownero/Wownero (= 0.0.1)
- FlutterMacOS
- cw_wownero/Boost (0.0.1):
- FlutterMacOS
- cw_wownero/OpenSSL (0.0.1):
- FlutterMacOS
- cw_wownero/Sodium (0.0.1):
- FlutterMacOS
- cw_wownero/Unbound (0.0.1):
- FlutterMacOS
- cw_wownero/Wownero (0.0.1):
- FlutterMacOS
- desktop_drop (0.0.1):
- FlutterMacOS
- device_info_plus (0.0.1):
- FlutterMacOS
- devicelocale (0.0.1):
- FlutterMacOS
- flutter_libepiccash (0.0.1):
- FlutterMacOS
- flutter_local_notifications (0.0.1):
- FlutterMacOS
- flutter_secure_storage_macos (3.3.1):
- flutter_secure_storage_macos (6.1.1):
- FlutterMacOS
- FlutterMacOS (1.0.0)
- isar_flutter_libs (1.0.0):
- FlutterMacOS
- package_info_plus_macos (0.0.1):
- lelantus (0.0.1):
- FlutterMacOS
- path_provider_macos (0.0.1):
- package_info_plus (0.0.1):
- FlutterMacOS
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- ReachabilitySwift (5.0.0)
- share_plus_macos (0.0.1):
- FlutterMacOS
- shared_preferences_macos (0.0.1):
- share_plus (0.0.1):
- FlutterMacOS
- stack_wallet_backup (0.0.1):
- FlutterMacOS
@ -30,16 +82,22 @@ PODS:
- FlutterMacOS
DEPENDENCIES:
- connectivity_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos`)
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
- cw_monero (from `Flutter/ephemeral/.symlinks/plugins/cw_monero/macos`)
- cw_shared_external (from `Flutter/ephemeral/.symlinks/plugins/cw_shared_external/macos`)
- cw_wownero (from `Flutter/ephemeral/.symlinks/plugins/cw_wownero/macos`)
- desktop_drop (from `Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos`)
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
- devicelocale (from `Flutter/ephemeral/.symlinks/plugins/devicelocale/macos`)
- flutter_libepiccash (from `Flutter/ephemeral/.symlinks/plugins/flutter_libepiccash/macos`)
- flutter_local_notifications (from `Flutter/ephemeral/.symlinks/plugins/flutter_local_notifications/macos`)
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`)
- isar_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/isar_flutter_libs/macos`)
- package_info_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos`)
- path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`)
- share_plus_macos (from `Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos`)
- shared_preferences_macos (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos`)
- lelantus (from `Flutter/ephemeral/.symlinks/plugins/lelantus/macos`)
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
- stack_wallet_backup (from `Flutter/ephemeral/.symlinks/plugins/stack_wallet_backup/macos`)
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
- wakelock_macos (from `Flutter/ephemeral/.symlinks/plugins/wakelock_macos/macos`)
@ -50,8 +108,20 @@ SPEC REPOS:
- ReachabilitySwift
EXTERNAL SOURCES:
connectivity_plus_macos:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus_macos/macos
connectivity_plus:
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
cw_monero:
:path: Flutter/ephemeral/.symlinks/plugins/cw_monero/macos
cw_shared_external:
:path: Flutter/ephemeral/.symlinks/plugins/cw_shared_external/macos
cw_wownero:
:path: Flutter/ephemeral/.symlinks/plugins/cw_wownero/macos
desktop_drop:
:path: Flutter/ephemeral/.symlinks/plugins/desktop_drop/macos
device_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
devicelocale:
:path: Flutter/ephemeral/.symlinks/plugins/devicelocale/macos
flutter_libepiccash:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_libepiccash/macos
flutter_local_notifications:
@ -62,14 +132,14 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral
isar_flutter_libs:
:path: Flutter/ephemeral/.symlinks/plugins/isar_flutter_libs/macos
package_info_plus_macos:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus_macos/macos
path_provider_macos:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos
share_plus_macos:
:path: Flutter/ephemeral/.symlinks/plugins/share_plus_macos/macos
shared_preferences_macos:
:path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_macos/macos
lelantus:
:path: Flutter/ephemeral/.symlinks/plugins/lelantus/macos
package_info_plus:
:path: Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos
path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
share_plus:
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
stack_wallet_backup:
:path: Flutter/ephemeral/.symlinks/plugins/stack_wallet_backup/macos
url_launcher_macos:
@ -80,22 +150,28 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral/.symlinks/plugins/window_size/macos
SPEC CHECKSUMS:
connectivity_plus_macos: f6e86fd000e971d361e54b5afcadc8c8fa773308
flutter_libepiccash: b33f7396504712b513b8ff019a3f6f3bdae54cfb
connectivity_plus: 18d3c32514c886e046de60e9c13895109866c747
cw_monero: a3442556ad3c06365c912735e4a23942a28692b1
cw_shared_external: 1f631d1132521baac5f4caed43176fa10d4e0d8b
cw_wownero: b4adb1e701fc363de27fa222fcaf4eff6f5fa63a
desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
flutter_libepiccash: 9113ac75dd325f8bcf00bc3ab583c7fc2780cf3c
flutter_local_notifications: 3805ca215b2fb7f397d78b66db91f6a747af52e4
flutter_secure_storage_macos: 6ceee8fbc7f484553ad17f79361b556259df89aa
FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811
isar_flutter_libs: 1948109973b6c2e46d6196b1537688a36a6edeac
package_info_plus_macos: f010621b07802a241d96d01876d6705f15e77c1c
path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
isar_flutter_libs: 43385c99864c168fadba7c9adeddc5d38838ca6a
lelantus: 3dfbf92b1e66b3573494dfe3d6a21c4988b5361b
package_info_plus: 02d7a575e80f194102bef286361c6c326e4c29ce
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
shared_preferences_macos: a64dc611287ed6cbe28fd1297898db1336975727
share_plus: 76dd39142738f7a68dd57b05093b5e8193f220f7
stack_wallet_backup: 6ebc60b1bdcf11cf1f1cbad9aa78332e1e15778c
url_launcher_macos: 597e05b8e514239626bcf4a850fcf9ef5c856ec3
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9
window_size: 339dafa0b27a95a62a843042038fa6c3c48de195
PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c
PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
COCOAPODS: 1.11.3

View file

@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 54;
objects = {
/* Begin PBXAggregateTarget section */
@ -21,15 +21,27 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
36299DF6FDF6725B2B9C51D5 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6BB87EF657A3ADFB1CE3E959 /* Pods_Runner.framework */; };
B98151812A674022009D013C /* mobileliblelantus.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B98151802A674022009D013C /* mobileliblelantus.framework */; };
B98151822A67402A009D013C /* mobileliblelantus.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = B98151802A674022009D013C /* mobileliblelantus.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B98151842A674143009D013C /* libsqlite3.0.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B98151832A674143009D013C /* libsqlite3.0.tbd */; };
BFD0376C00E1FFD46376BB9D /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9206484E84CB0AD93E3E68CA /* Pods_RunnerTests.framework */; };
F653CA022D33E8B60E11A9F3 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6036BF01BF05EA773C76D22 /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 33CC10EC2044A3C60003C045;
remoteInfo = Runner;
};
33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 33CC10E52044A3C60003C045 /* Project object */;
@ -46,6 +58,7 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
B98151822A67402A009D013C /* mobileliblelantus.framework in Bundle Framework */,
);
name = "Bundle Framework";
runOnlyForDeploymentPostprocessing = 0;
@ -53,9 +66,14 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0FA914E59929120BA65E8403 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
174539D042E7AC2AB25A83EB /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
27CB73AACA5743180CC6CD50 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* Stack Wallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Stack Wallet.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10ED2044A3C60003C045 /* Stack Wallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Stack Wallet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@ -67,26 +85,47 @@
33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = "<group>"; };
33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = "<group>"; };
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = "<group>"; };
6BB87EF657A3ADFB1CE3E959 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
41EE721BF40B8DE895352A2C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
937DF254AD7EDA15AFE96BD9 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
9206484E84CB0AD93E3E68CA /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
BC4589C48A71C3A1A477DD76 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
EA2D897BC13EBFB1DE697D5C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
ACB8E553D75AA4AC9A7656CE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
B98151802A674022009D013C /* mobileliblelantus.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mobileliblelantus.framework; path = ../crypto_plugins/flutter_liblelantus/scripts/macos/mobileliblelantus/mobileliblelantus.framework; sourceTree = "<group>"; };
B98151832A674143009D013C /* libsqlite3.0.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; };
BF5E76865ACB46314AC27D8F /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
E6036BF01BF05EA773C76D22 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
331C80D2294CF70F00263BE5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
BFD0376C00E1FFD46376BB9D /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10EA2044A3C60003C045 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
36299DF6FDF6725B2B9C51D5 /* Pods_Runner.framework in Frameworks */,
B98151842A674143009D013C /* libsqlite3.0.tbd in Frameworks */,
B98151812A674022009D013C /* mobileliblelantus.framework in Frameworks */,
F653CA022D33E8B60E11A9F3 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
331C80D6294CF71000263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
331C80D7294CF71000263BE5 /* RunnerTests.swift */,
);
path = RunnerTests;
sourceTree = "<group>";
};
33BA886A226E78AF003329D5 /* Configs */ = {
isa = PBXGroup;
children = (
@ -103,9 +142,10 @@
children = (
33FAB671232836740065AC1E /* Runner */,
33CEB47122A05771004F2AC0 /* Flutter */,
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
9000119722579F22067B9BC0 /* Pods */,
F0D4A0626F78BE1EF2A1E0D6 /* Pods */,
);
sourceTree = "<group>";
};
@ -113,6 +153,7 @@
isa = PBXGroup;
children = (
33CC10ED2044A3C60003C045 /* Stack Wallet.app */,
331C80D5294CF71000263BE5 /* RunnerTests.xctest */,
);
name = Products;
sourceTree = "<group>";
@ -152,39 +193,63 @@
path = Runner;
sourceTree = "<group>";
};
9000119722579F22067B9BC0 /* Pods */ = {
isa = PBXGroup;
children = (
EA2D897BC13EBFB1DE697D5C /* Pods-Runner.debug.xcconfig */,
937DF254AD7EDA15AFE96BD9 /* Pods-Runner.release.xcconfig */,
BC4589C48A71C3A1A477DD76 /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
6BB87EF657A3ADFB1CE3E959 /* Pods_Runner.framework */,
B98151832A674143009D013C /* libsqlite3.0.tbd */,
B98151802A674022009D013C /* mobileliblelantus.framework */,
E6036BF01BF05EA773C76D22 /* Pods_Runner.framework */,
9206484E84CB0AD93E3E68CA /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
F0D4A0626F78BE1EF2A1E0D6 /* Pods */ = {
isa = PBXGroup;
children = (
41EE721BF40B8DE895352A2C /* Pods-Runner.debug.xcconfig */,
0FA914E59929120BA65E8403 /* Pods-Runner.release.xcconfig */,
ACB8E553D75AA4AC9A7656CE /* Pods-Runner.profile.xcconfig */,
BF5E76865ACB46314AC27D8F /* Pods-RunnerTests.debug.xcconfig */,
174539D042E7AC2AB25A83EB /* Pods-RunnerTests.release.xcconfig */,
27CB73AACA5743180CC6CD50 /* Pods-RunnerTests.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
331C80D4294CF70F00263BE5 /* RunnerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
FF8CC09C83E12FC1C6EE6A8F /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
);
buildRules = (
);
dependencies = (
331C80DA294CF71000263BE5 /* PBXTargetDependency */,
);
name = RunnerTests;
productName = RunnerTests;
productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
33CC10EC2044A3C60003C045 /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
DF80A3E256A63BF2D2008937 /* [CP] Check Pods Manifest.lock */,
AAFD86C9DC38B4393BC9D8E0 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
8D7CC24E5AE846869656D4D1 /* [CP] Embed Pods Frameworks */,
529691D83C3BADE14E2EAC03 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@ -206,6 +271,10 @@
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C80D4294CF70F00263BE5 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 33CC10EC2044A3C60003C045;
};
33CC10EC2044A3C60003C045 = {
CreatedOnToolsVersion = 9.2;
LastSwiftMigration = 1100;
@ -236,12 +305,20 @@
projectRoot = "";
targets = (
33CC10EC2044A3C60003C045 /* Runner */,
331C80D4294CF70F00263BE5 /* RunnerTests */,
33CC111A2044C6BA0003C045 /* Flutter Assemble */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
331C80D3294CF70F00263BE5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10EB2044A3C60003C045 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -256,6 +333,7 @@
/* Begin PBXShellScriptBuildPhase section */
3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@ -291,7 +369,7 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
8D7CC24E5AE846869656D4D1 /* [CP] Embed Pods Frameworks */ = {
529691D83C3BADE14E2EAC03 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -308,7 +386,7 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
DF80A3E256A63BF2D2008937 /* [CP] Check Pods Manifest.lock */ = {
AAFD86C9DC38B4393BC9D8E0 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@ -330,9 +408,39 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
FF8CC09C83E12FC1C6EE6A8F /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
331C80D1294CF70F00263BE5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
33CC10E92044A3C60003C045 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -346,6 +454,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
331C80DA294CF71000263BE5 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 33CC10EC2044A3C60003C045 /* Runner */;
targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */;
};
33CC11202044C79F0003C045 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */;
@ -366,6 +479,51 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = BF5E76865ACB46314AC27D8F /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackWallet.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Stack Wallet.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/stack_wallet";
};
name = Debug;
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 174539D042E7AC2AB25A83EB /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackWallet.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Stack Wallet.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/stack_wallet";
};
name = Release;
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 27CB73AACA5743180CC6CD50 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stackWallet.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Stack Wallet.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/stack_wallet";
};
name = Profile;
};
338D0CE9231458BD00FA5F75 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
@ -404,9 +562,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
@ -421,6 +581,30 @@
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/connectivity_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cw_monero\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cw_shared_external\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cw_wownero\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/desktop_drop\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/device_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/devicelocale\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_libepiccash\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_local_notifications\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_secure_storage_macos\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/isar_flutter_libs\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/lelantus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/stack_wallet_backup\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_macos\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/wakelock_macos\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/window_size\"",
"\"${PROJECT_DIR}/../crypto_plugins/flutter_liblelantus/scripts/macos/mobileliblelantus\"",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -483,10 +667,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
@ -530,9 +715,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.11;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
@ -547,6 +734,30 @@
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/connectivity_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cw_monero\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cw_shared_external\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cw_wownero\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/desktop_drop\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/device_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/devicelocale\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_libepiccash\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_local_notifications\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_secure_storage_macos\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/isar_flutter_libs\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/lelantus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/stack_wallet_backup\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_macos\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/wakelock_macos\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/window_size\"",
"\"${PROJECT_DIR}/../crypto_plugins/flutter_liblelantus/scripts/macos/mobileliblelantus\"",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -567,6 +778,30 @@
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"\"${PODS_CONFIGURATION_BUILD_DIR}/ReachabilitySwift\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/connectivity_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cw_monero\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cw_shared_external\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/cw_wownero\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/desktop_drop\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/device_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/devicelocale\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_libepiccash\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_local_notifications\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/flutter_secure_storage_macos\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/isar_flutter_libs\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/lelantus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/package_info_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/share_plus\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/stack_wallet_backup\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/url_launcher_macos\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/wakelock_macos\"",
"\"${PODS_CONFIGURATION_BUILD_DIR}/window_size\"",
"\"${PROJECT_DIR}/../crypto_plugins/flutter_liblelantus/scripts/macos/mobileliblelantus\"",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@ -596,6 +831,16 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
331C80DB294CF71000263BE5 /* Debug */,
331C80DC294CF71000263BE5 /* Release */,
331C80DD294CF71000263BE5 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View file

@ -37,6 +37,17 @@
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "331C80D4294CF70F00263BE5"
BuildableName = "RunnerTests.xctest"
BlueprintName = "RunnerTests"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 926 B

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -11,4 +11,4 @@ PRODUCT_NAME = Stack Wallet
PRODUCT_BUNDLE_IDENTIFIER = com.cypherstack.stack_wallet
// The copyright displayed in application information
PRODUCT_COPYRIGHT = Copyright © 2022 com.cypherstack. All rights reserved.
PRODUCT_COPYRIGHT = Copyright © 2023 com.cypherstack. All rights reserved.

View file

@ -8,5 +8,7 @@
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

View file

@ -3,7 +3,7 @@ import FlutterMacOS
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
let flutterViewController = FlutterViewController.init()
let flutterViewController = FlutterViewController()
let windowFrame = self.frame
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)

View file

@ -4,5 +4,7 @@
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,12 @@
import FlutterMacOS
import Cocoa
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}

View file

@ -226,10 +226,10 @@ packages:
dependency: transitive
description:
name: cli_util
sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c"
sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7
url: "https://pub.dev"
source: hosted
version: "0.3.5"
version: "0.4.0"
clock:
dependency: transitive
description:
@ -584,10 +584,10 @@ packages:
dependency: "direct dev"
description:
name: flutter_launcher_icons
sha256: ce0e501cfc258907842238e4ca605e74b7fd1cdf04b3b43e86c43f3e40a1592c
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
url: "https://pub.dev"
source: hosted
version: "0.11.0"
version: "0.13.1"
flutter_libepiccash:
dependency: "direct main"
description:
@ -646,10 +646,10 @@ packages:
dependency: "direct main"
description:
name: flutter_native_splash
sha256: "6777a3abb974021a39b5fdd2d46a03ca390e03903b6351f21d10e7ecc969f12d"
sha256: ba45d8cfbd778478a74696b012f33ffb6b1760c9bc531b21e2964444a4870dae
url: "https://pub.dev"
source: hosted
version: "2.2.16"
version: "2.3.1"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
@ -853,10 +853,10 @@ packages:
dependency: transitive
description:
name: image
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf
url: "https://pub.dev"
source: hosted
version: "3.3.0"
version: "4.0.17"
import_sorter:
dependency: "direct dev"
description:
@ -948,7 +948,7 @@ packages:
path: "crypto_plugins/flutter_liblelantus"
relative: true
source: path
version: "0.0.1"
version: "0.0.2"
lints:
dependency: transitive
description:
@ -1349,62 +1349,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.2.1"
shared_preferences:
dependency: transitive
description:
name: shared_preferences
sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb
url: "https://pub.dev"
source: hosted
version: "2.2.2"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d
url: "https://pub.dev"
source: hosted
version: "2.2.0"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
shelf:
dependency: transitive
description:
@ -1631,10 +1575,10 @@ packages:
dependency: transitive
description:
name: universal_io
sha256: "06866290206d196064fd61df4c7aea1ffe9a4e7c4ccaa8fcded42dd41948005d"
sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
version: "2.2.2"
url_launcher:
dependency: "direct main"
description:
@ -1887,4 +1831,4 @@ packages:
version: "1.0.0"
sdks:
dart: ">=3.0.2 <4.0.0"
flutter: ">=3.10.0"
flutter: ">=3.10.3"

View file

@ -11,7 +11,7 @@ description: Stack Wallet
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.7.15+181
version: 1.7.16+182
environment:
sdk: ">=3.0.2 <4.0.0"
@ -145,7 +145,7 @@ dev_dependencies:
integration_test:
sdk: flutter
build_runner: ^2.1.7
flutter_launcher_icons: ^0.11.0
flutter_launcher_icons: ^0.13.1
hive_generator: ^2.0.0
dependency_validator: ^3.1.2
hive_test: ^1.0.1
@ -157,7 +157,7 @@ dev_dependencies:
flutter_lints: ^2.0.1
isar_generator: 3.0.5
flutter_icons:
flutter_launcher_icons:
android: true
ios: true
image_path: assets/icon/icon.png
@ -170,7 +170,7 @@ flutter_icons:
icon_size: 48 # min:48, max:256, default: 48
macos:
generate: true
image_path: assets/icon/icon.png
image_path: assets/icon/macos-icon.png
flutter_native_splash:
image: assets/images/splash.png

8
scripts/macos/build_all.sh Executable file
View file

@ -0,0 +1,8 @@
#!/bin/bash
(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh ) &
(cd ../../crypto_plugins/flutter_libepiccash/scripts/macos && ./build_all.sh ) &
(cd ../../crypto_plugins/flutter_libmonero/scripts/macos/ && ./build_all.sh ) &
wait
echo "Done building"

View file

@ -11,9 +11,7 @@ import 'package:mockito/mockito.dart';
import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
import 'package:stackwallet/models/lelantus_coin.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/lelantus_fee_data.dart';
import 'package:stackwallet/models/paymint/transactions_model.dart' as old;
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
@ -72,6 +70,7 @@ void main() {
setData,
List<String>.from(usedSerials),
firoNetwork,
"walletId",
);
const currentHeight = 100000000000;
@ -113,10 +112,7 @@ void main() {
final result = await staticProcessRestore(txData, message, currentHeight);
expect(result, isA<Map<String, dynamic>>());
expect(result["mintIndex"], 8);
expect(result["jindex"], [2, 4, 6]);
expect(
result["_lelantus_coins"], isA<List<Map<dynamic, LelantusCoin>>>());
expect(result["_lelantus_coins"], isA<List<LelantusCoin>>());
expect(result["newTxMap"], isA<Map<String, Transaction>>());
});
@ -133,6 +129,7 @@ void main() {
setData,
List<String>.from(usedSerials),
firoNetwork,
"walletId",
),
throwsA(isA<Error>()));
});
@ -530,18 +527,10 @@ void main() {
group("FiroWallet service class functions that depend on shared storage", () {
const testWalletId = "testWalletID";
const testWalletName = "Test Wallet";
bool hiveAdaptersRegistered = false;
setUp(() async {
await setUpTestHive();
if (!hiveAdaptersRegistered) {
hiveAdaptersRegistered = true;
// Registering Lelantus Model Adapters
Hive.registerAdapter(LelantusCoinAdapter());
}
final wallets = await Hive.openBox<dynamic>('wallets');
await wallets.put('currentWalletName', testWalletName);
});
@ -1202,13 +1191,33 @@ void main() {
txHash: BuildMintTxTestParams.utxoInfo["txid"] as String,
coin: Coin.firo,
)).thenAnswer((_) async => BuildMintTxTestParams.cachedClientResponse);
when(cachedClient.getAnonymitySet(
groupId: "1",
coin: Coin.firo,
)).thenAnswer(
(_) async => GetAnonymitySetSampleData.data,
);
when(cachedClient.getAnonymitySet(
groupId: "2",
coin: Coin.firo,
)).thenAnswer(
(_) async => GetAnonymitySetSampleData.data,
);
when(client.getBlockHeadTip()).thenAnswer(
(_) async => {"height": 455873, "hex": "this value not used here"});
when(client.getLatestCoinId()).thenAnswer((_) async => 2);
when(mainDB.getAddress("${testWalletId}buildMintTransaction", any))
.thenAnswer((realInvocation) async => null);
when(mainDB.getHighestUsedMintIndex(
walletId: "${testWalletId}submitHexToNetwork"))
.thenAnswer((_) async => null);
when(mainDB.getHighestUsedMintIndex(
walletId: "testWalletIDbuildMintTransaction"))
.thenAnswer((_) async => null);
final firo = FiroWallet(
walletName: testWalletName,
walletId: "${testWalletId}buildMintTransaction",

View file

@ -1151,4 +1151,14 @@ class MockMainDB extends _i1.Mock implements _i9.MainDB {
returnValue: _i5.Future<void>.value(),
returnValueForMissingStub: _i5.Future<void>.value(),
) as _i5.Future<void>);
@override
_i5.Future<int?> getHighestUsedMintIndex({required String? walletId}) =>
(super.noSuchMethod(
Invocation.method(
#getHighestUsedMintIndex,
[],
{#walletId: walletId},
),
returnValue: _i5.Future<int?>.value(),
) as _i5.Future<int?>);
}

View file

@ -14,7 +14,6 @@ import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i5;
import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i4;
import 'package:stackwallet/models/balance.dart' as _i6;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i13;
import 'package:stackwallet/models/lelantus_coin.dart' as _i15;
import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i3;
import 'package:stackwallet/models/signing_data.dart' as _i14;
import 'package:stackwallet/services/coins/firo/firo_wallet.dart' as _i10;
@ -589,15 +588,6 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet {
returnValueForMissingStub: _i11.Future<void>.value(),
) as _i11.Future<void>);
@override
List<Map<dynamic, _i15.LelantusCoin>> getLelantusCoinMap() =>
(super.noSuchMethod(
Invocation.method(
#getLelantusCoinMap,
[],
),
returnValue: <Map<dynamic, _i15.LelantusCoin>>[],
) as List<Map<dynamic, _i15.LelantusCoin>>);
@override
_i11.Future<void> anonymizeAllPublicFunds() => (super.noSuchMethod(
Invocation.method(
#anonymizeAllPublicFunds,
@ -755,15 +745,6 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet {
returnValueForMissingStub: _i11.Future<void>.value(),
) as _i11.Future<void>);
@override
_i11.Future<dynamic> getCoinsToJoinSplit(int? required) =>
(super.noSuchMethod(
Invocation.method(
#getCoinsToJoinSplit,
[required],
),
returnValue: _i11.Future<dynamic>.value(),
) as _i11.Future<dynamic>);
@override
_i11.Future<int> estimateJoinSplitFee(int? spendAmount) =>
(super.noSuchMethod(
Invocation.method(
@ -1061,51 +1042,6 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet {
),
returnValueForMissingStub: null,
);
@override
void initFiroHive(String? walletId) => super.noSuchMethod(
Invocation.method(
#initFiroHive,
[walletId],
),
returnValueForMissingStub: null,
);
@override
_i11.Future<void> firoUpdateJIndex(List<dynamic>? jIndex) =>
(super.noSuchMethod(
Invocation.method(
#firoUpdateJIndex,
[jIndex],
),
returnValue: _i11.Future<void>.value(),
returnValueForMissingStub: _i11.Future<void>.value(),
) as _i11.Future<void>);
@override
_i11.Future<void> firoUpdateLelantusCoins(List<dynamic>? lelantusCoins) =>
(super.noSuchMethod(
Invocation.method(
#firoUpdateLelantusCoins,
[lelantusCoins],
),
returnValue: _i11.Future<void>.value(),
returnValueForMissingStub: _i11.Future<void>.value(),
) as _i11.Future<void>);
@override
int firoGetMintIndex() => (super.noSuchMethod(
Invocation.method(
#firoGetMintIndex,
[],
),
returnValue: 0,
) as int);
@override
_i11.Future<void> firoUpdateMintIndex(int? mintIndex) => (super.noSuchMethod(
Invocation.method(
#firoUpdateMintIndex,
[mintIndex],
),
returnValue: _i11.Future<void>.value(),
returnValueForMissingStub: _i11.Future<void>.value(),
) as _i11.Future<void>);
}
/// A class which mocks [ElectrumX].

View file

@ -1602,15 +1602,6 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet {
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
@override
List<Map<dynamic, _i8.LelantusCoin>> getLelantusCoinMap() =>
(super.noSuchMethod(
Invocation.method(
#getLelantusCoinMap,
[],
),
returnValue: <Map<dynamic, _i8.LelantusCoin>>[],
) as List<Map<dynamic, _i8.LelantusCoin>>);
@override
_i19.Future<void> anonymizeAllPublicFunds() => (super.noSuchMethod(
Invocation.method(
#anonymizeAllPublicFunds,
@ -1768,15 +1759,6 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet {
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
@override
_i19.Future<dynamic> getCoinsToJoinSplit(int? required) =>
(super.noSuchMethod(
Invocation.method(
#getCoinsToJoinSplit,
[required],
),
returnValue: _i19.Future<dynamic>.value(),
) as _i19.Future<dynamic>);
@override
_i19.Future<int> estimateJoinSplitFee(int? spendAmount) =>
(super.noSuchMethod(
Invocation.method(
@ -2075,51 +2057,6 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet {
),
returnValueForMissingStub: null,
);
@override
void initFiroHive(String? walletId) => super.noSuchMethod(
Invocation.method(
#initFiroHive,
[walletId],
),
returnValueForMissingStub: null,
);
@override
_i19.Future<void> firoUpdateJIndex(List<dynamic>? jIndex) =>
(super.noSuchMethod(
Invocation.method(
#firoUpdateJIndex,
[jIndex],
),
returnValue: _i19.Future<void>.value(),
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
@override
_i19.Future<void> firoUpdateLelantusCoins(List<dynamic>? lelantusCoins) =>
(super.noSuchMethod(
Invocation.method(
#firoUpdateLelantusCoins,
[lelantusCoins],
),
returnValue: _i19.Future<void>.value(),
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
@override
int firoGetMintIndex() => (super.noSuchMethod(
Invocation.method(
#firoGetMintIndex,
[],
),
returnValue: 0,
) as int);
@override
_i19.Future<void> firoUpdateMintIndex(int? mintIndex) => (super.noSuchMethod(
Invocation.method(
#firoUpdateMintIndex,
[mintIndex],
),
returnValue: _i19.Future<void>.value(),
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
}
/// A class which mocks [LocaleService].
@ -3559,4 +3496,14 @@ class MockMainDB extends _i1.Mock implements _i14.MainDB {
returnValue: _i19.Future<void>.value(),
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
@override
_i19.Future<int?> getHighestUsedMintIndex({required String? walletId}) =>
(super.noSuchMethod(
Invocation.method(
#getHighestUsedMintIndex,
[],
{#walletId: walletId},
),
returnValue: _i19.Future<int?>.value(),
) as _i19.Future<int?>);
}