mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-18 02:07:43 +00:00
Merge pull request #714 from cypherstack/wallets_refactor
Wallets refactor
This commit is contained in:
commit
783c42b63b
415 changed files with 61623 additions and 96802 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -56,4 +56,6 @@ libcw_wownero.dll
|
|||
libepic_cash_wallet.dll
|
||||
libmobileliblelantus.dll
|
||||
libtor_ffi.dll
|
||||
flutter_libsparkmobile.dll
|
||||
secp256k1.dll
|
||||
/libisar.so
|
||||
|
|
1
assets/svg/spark.svg
Normal file
1
assets/svg/spark.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg"><path d="m24.5 31.9-4.9 16.2h12.5l-4.2 13.9 16.5-20.2h-11.9l2.9-9.9z" fill="#ffce31" transform="matrix(1.25 0 0 2 -6 -62)"/></svg>
|
After Width: | Height: | Size: 190 B |
|
@ -1 +1 @@
|
|||
Subproject commit f677dec0b34d3f9fe8fce2bc8ff5c508c3f3bb9a
|
||||
Subproject commit 8ce7c3ab9b602c1f7f4e856380023b86002857ce
|
|
@ -12,7 +12,8 @@ import 'package:hive/hive.dart';
|
|||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
|
||||
import 'package:stackwallet/db/migrate_wallets_to_isar.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx_client.dart';
|
||||
import 'package:stackwallet/models/contact.dart';
|
||||
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
|
||||
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
||||
|
@ -54,7 +55,7 @@ class DbVersionMigrator with WalletDB {
|
|||
final walletInfoList = await walletsService.walletNames;
|
||||
await prefs.init();
|
||||
|
||||
ElectrumX? client;
|
||||
ElectrumXClient? client;
|
||||
int? latestSetId;
|
||||
|
||||
// only instantiate client if there are firo wallets
|
||||
|
@ -76,7 +77,7 @@ class DbVersionMigrator with WalletDB {
|
|||
)
|
||||
.toList();
|
||||
|
||||
client = ElectrumX.from(
|
||||
client = ElectrumXClient.from(
|
||||
node: ElectrumXNode(
|
||||
address: node.host,
|
||||
port: node.port,
|
||||
|
@ -88,7 +89,7 @@ class DbVersionMigrator with WalletDB {
|
|||
);
|
||||
|
||||
try {
|
||||
latestSetId = await client.getLatestCoinId();
|
||||
latestSetId = await client.getLelantusLatestCoinId();
|
||||
} catch (e) {
|
||||
// default to 2 for now
|
||||
latestSetId = 2;
|
||||
|
@ -353,74 +354,23 @@ class DbVersionMigrator with WalletDB {
|
|||
// try to continue migrating
|
||||
return await migrate(11, secureStore: secureStore);
|
||||
|
||||
case 11:
|
||||
// migrate
|
||||
await _v11(secureStore);
|
||||
|
||||
// update version
|
||||
await DB.instance.put<dynamic>(
|
||||
boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 12);
|
||||
|
||||
// try to continue migrating
|
||||
return await migrate(12, 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);
|
||||
|
@ -619,4 +569,70 @@ class DbVersionMigrator with WalletDB {
|
|||
|
||||
await addressBookBox.deleteFromDisk();
|
||||
}
|
||||
|
||||
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> _v11(SecureStorageInterface secureStore) async {
|
||||
await migrateWalletsToIsar(secureStore: secureStore);
|
||||
}
|
||||
}
|
|
@ -26,12 +26,13 @@ class DB {
|
|||
@Deprecated("Left over for migration from old versions of Stack Wallet")
|
||||
static const String boxNameAddressBook = "addressBook";
|
||||
static const String boxNameTrades = "exchangeTransactionsBox";
|
||||
static const String boxNameAllWalletsData = "wallets";
|
||||
static const String boxNameFavoriteWallets = "favoriteWallets";
|
||||
|
||||
// in use
|
||||
// TODO: migrate
|
||||
static const String boxNameNodeModels = "nodeModels";
|
||||
static const String boxNamePrimaryNodes = "primaryNodes";
|
||||
static const String boxNameAllWalletsData = "wallets";
|
||||
static const String boxNameNotifications = "notificationModels";
|
||||
static const String boxNameWatchedTransactions =
|
||||
"watchedTxNotificationModels";
|
||||
|
@ -39,7 +40,6 @@ class DB {
|
|||
static const String boxNameTradesV2 = "exchangeTradesBox";
|
||||
static const String boxNameTradeNotes = "tradeNotesBox";
|
||||
static const String boxNameTradeLookup = "tradeToTxidLookUpBox";
|
||||
static const String boxNameFavoriteWallets = "favoriteWallets";
|
||||
static const String boxNameWalletsToDeleteOnStart = "walletsToDeleteOnStart";
|
||||
static const String boxNamePriceCache = "priceAPIPrice24hCache";
|
||||
|
||||
|
@ -53,8 +53,12 @@ class DB {
|
|||
// firo only
|
||||
String _boxNameSetCache({required Coin coin}) =>
|
||||
"${coin.name}_anonymitySetCache";
|
||||
String _boxNameSetSparkCache({required Coin coin}) =>
|
||||
"${coin.name}_anonymitySetSparkCache";
|
||||
String _boxNameUsedSerialsCache({required Coin coin}) =>
|
||||
"${coin.name}_usedSerialsCache";
|
||||
String _boxNameSparkUsedCoinsTagsCache({required Coin coin}) =>
|
||||
"${coin.name}_sparkUsedCoinsTagsCache";
|
||||
|
||||
Box<NodeModel>? _boxNodeModels;
|
||||
Box<NodeModel>? _boxPrimaryNodes;
|
||||
|
@ -75,7 +79,9 @@ class DB {
|
|||
|
||||
final Map<Coin, Box<dynamic>> _txCacheBoxes = {};
|
||||
final Map<Coin, Box<dynamic>> _setCacheBoxes = {};
|
||||
final Map<Coin, Box<dynamic>> _setSparkCacheBoxes = {};
|
||||
final Map<Coin, Box<dynamic>> _usedSerialsCacheBoxes = {};
|
||||
final Map<Coin, Box<dynamic>> _getSparkUsedCoinsTagsCacheBoxes = {};
|
||||
|
||||
// exposed for monero
|
||||
Box<xmr.WalletInfo> get moneroWalletInfoBox => _walletInfoSource!;
|
||||
|
@ -197,6 +203,15 @@ class DB {
|
|||
await Hive.openBox<dynamic>(_boxNameSetCache(coin: coin));
|
||||
}
|
||||
|
||||
Future<Box<dynamic>> getSparkAnonymitySetCacheBox(
|
||||
{required Coin coin}) async {
|
||||
if (_setSparkCacheBoxes[coin]?.isOpen != true) {
|
||||
_setSparkCacheBoxes.remove(coin);
|
||||
}
|
||||
return _setSparkCacheBoxes[coin] ??=
|
||||
await Hive.openBox<dynamic>(_boxNameSetSparkCache(coin: coin));
|
||||
}
|
||||
|
||||
Future<void> closeAnonymitySetCacheBox({required Coin coin}) async {
|
||||
await _setCacheBoxes[coin]?.close();
|
||||
}
|
||||
|
@ -209,6 +224,16 @@ class DB {
|
|||
await Hive.openBox<dynamic>(_boxNameUsedSerialsCache(coin: coin));
|
||||
}
|
||||
|
||||
Future<Box<dynamic>> getSparkUsedCoinsTagsCacheBox(
|
||||
{required Coin coin}) async {
|
||||
if (_getSparkUsedCoinsTagsCacheBoxes[coin]?.isOpen != true) {
|
||||
_getSparkUsedCoinsTagsCacheBoxes.remove(coin);
|
||||
}
|
||||
return _getSparkUsedCoinsTagsCacheBoxes[coin] ??=
|
||||
await Hive.openBox<dynamic>(
|
||||
_boxNameSparkUsedCoinsTagsCache(coin: coin));
|
||||
}
|
||||
|
||||
Future<void> closeUsedSerialsCacheBox({required Coin coin}) async {
|
||||
await _usedSerialsCacheBoxes[coin]?.close();
|
||||
}
|
||||
|
@ -216,9 +241,12 @@ class DB {
|
|||
/// Clear all cached transactions for the specified coin
|
||||
Future<void> clearSharedTransactionCache({required Coin coin}) async {
|
||||
await deleteAll<dynamic>(boxName: _boxNameTxCache(coin: coin));
|
||||
if (coin == Coin.firo) {
|
||||
if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
||||
await deleteAll<dynamic>(boxName: _boxNameSetCache(coin: coin));
|
||||
await deleteAll<dynamic>(boxName: _boxNameSetSparkCache(coin: coin));
|
||||
await deleteAll<dynamic>(boxName: _boxNameUsedSerialsCache(coin: coin));
|
||||
await deleteAll<dynamic>(
|
||||
boxName: _boxNameSparkUsedCoinsTagsCache(coin: coin));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,5 +350,4 @@ abstract class DBKeys {
|
|||
static const String isFavorite = "isFavorite";
|
||||
static const String id = "id";
|
||||
static const String storedChainHeight = "storedChainHeight";
|
||||
static const String ethTokenContracts = "ethTokenContracts";
|
||||
}
|
||||
|
|
|
@ -21,6 +21,10 @@ import 'package:stackwallet/models/isar/stack_theme.dart';
|
|||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/stack_file_system.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/spark_coin.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/wallet_info_meta.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
part '../queries/queries.dart';
|
||||
|
@ -58,7 +62,11 @@ class MainDB {
|
|||
ContactEntrySchema,
|
||||
OrdinalSchema,
|
||||
LelantusCoinSchema,
|
||||
WalletInfoSchema,
|
||||
TransactionV2Schema,
|
||||
SparkCoinSchema,
|
||||
WalletInfoMetaSchema,
|
||||
TokenWalletInfoSchema,
|
||||
],
|
||||
directory: (await StackFileSystem.applicationIsarDirectory()).path,
|
||||
// inspector: kDebugMode,
|
||||
|
@ -69,6 +77,36 @@ class MainDB {
|
|||
return true;
|
||||
}
|
||||
|
||||
Future<void> putWalletInfo(WalletInfo walletInfo) async {
|
||||
try {
|
||||
await isar.writeTxn(() async {
|
||||
await isar.walletInfo.put(walletInfo);
|
||||
});
|
||||
} catch (e) {
|
||||
throw MainDBException("failed putWalletInfo()", e);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateWalletInfo(WalletInfo walletInfo) async {
|
||||
try {
|
||||
await isar.writeTxn(() async {
|
||||
final info = await isar.walletInfo
|
||||
.where()
|
||||
.walletIdEqualTo(walletInfo.walletId)
|
||||
.findFirst();
|
||||
if (info == null) {
|
||||
throw Exception("updateWalletInfo() called with new WalletInfo."
|
||||
" Use putWalletInfo()");
|
||||
}
|
||||
|
||||
await isar.walletInfo.deleteByWalletId(walletInfo.walletId);
|
||||
await isar.walletInfo.put(walletInfo);
|
||||
});
|
||||
} catch (e) {
|
||||
throw MainDBException("failed updateWalletInfo()", e);
|
||||
}
|
||||
}
|
||||
|
||||
// contact entries
|
||||
List<ContactEntry> getContactEntries() {
|
||||
return isar.contactEntrys.where().sortByName().findAllSync();
|
||||
|
@ -390,8 +428,8 @@ class MainDB {
|
|||
await isar.transactionV2s.where().walletIdEqualTo(walletId).count();
|
||||
final addressCount = await getAddresses(walletId).count();
|
||||
final utxoCount = await getUTXOs(walletId).count();
|
||||
final lelantusCoinCount =
|
||||
await isar.lelantusCoins.where().walletIdEqualTo(walletId).count();
|
||||
// final lelantusCoinCount =
|
||||
// await isar.lelantusCoins.where().walletIdEqualTo(walletId).count();
|
||||
|
||||
await isar.writeTxn(() async {
|
||||
const paginateLimit = 50;
|
||||
|
@ -439,16 +477,23 @@ class MainDB {
|
|||
}
|
||||
|
||||
// lelantusCoins
|
||||
for (int i = 0; i < lelantusCoinCount; i += paginateLimit) {
|
||||
final lelantusCoinIds = await isar.lelantusCoins
|
||||
await isar.lelantusCoins.where().walletIdEqualTo(walletId).deleteAll();
|
||||
// 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);
|
||||
// }
|
||||
|
||||
// spark coins
|
||||
await isar.sparkCoins
|
||||
.where()
|
||||
.walletIdEqualTo(walletId)
|
||||
.offset(i)
|
||||
.limit(paginateLimit)
|
||||
.idProperty()
|
||||
.findAll();
|
||||
await isar.lelantusCoins.deleteAll(lelantusCoinIds);
|
||||
}
|
||||
.walletIdEqualToAnyLTagHash(walletId)
|
||||
.deleteAll();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
214
lib/db/migrate_wallets_to_isar.dart
Normal file
214
lib/db/migrate_wallets_to_isar.dart
Normal file
|
@ -0,0 +1,214 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/wallet_info_meta.dart';
|
||||
import 'package:stackwallet/wallets/wallet/supporting/epiccash_wallet_info_extension.dart';
|
||||
|
||||
Future<void> migrateWalletsToIsar({
|
||||
required SecureStorageInterface secureStore,
|
||||
}) async {
|
||||
await MainDB.instance.initMainDB();
|
||||
|
||||
// ensure fresh
|
||||
await MainDB.instance.isar
|
||||
.writeTxn(() async => await MainDB.instance.isar.transactionV2s.clear());
|
||||
|
||||
final allWalletsBox = await Hive.openBox<dynamic>(DB.boxNameAllWalletsData);
|
||||
|
||||
final names = DB.instance
|
||||
.get<dynamic>(boxName: DB.boxNameAllWalletsData, key: 'names') as Map?;
|
||||
|
||||
if (names == null) {
|
||||
// no wallets to migrate
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse the old data from the Hive map into a nice list
|
||||
//
|
||||
final List<
|
||||
({
|
||||
Coin coin,
|
||||
String name,
|
||||
String walletId,
|
||||
})> oldInfo = Map<String, dynamic>.from(names).values.map((e) {
|
||||
final map = e as Map;
|
||||
return (
|
||||
coin: Coin.values.byName(map["coin"] as String),
|
||||
walletId: map["id"] as String,
|
||||
name: map["name"] as String,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
//
|
||||
// Get current ordered list of favourite wallet Ids
|
||||
//
|
||||
final List<String> favourites =
|
||||
(await Hive.openBox<String>(DB.boxNameFavoriteWallets)).values.toList();
|
||||
|
||||
final List<(WalletInfo, WalletInfoMeta)> newInfo = [];
|
||||
final List<TokenWalletInfo> tokenInfo = [];
|
||||
final List<TransactionNote> migratedNotes = [];
|
||||
|
||||
//
|
||||
// Convert each old info into the new Isar WalletInfo
|
||||
//
|
||||
for (final old in oldInfo) {
|
||||
final walletBox = await Hive.openBox<dynamic>(old.walletId);
|
||||
|
||||
//
|
||||
// First handle transaction notes
|
||||
//
|
||||
final newNoteCount = await MainDB.instance.isar.transactionNotes
|
||||
.where()
|
||||
.walletIdEqualTo(old.walletId)
|
||||
.count();
|
||||
if (newNoteCount == 0) {
|
||||
final map = walletBox.get('notes') as Map?;
|
||||
|
||||
if (map != null) {
|
||||
final notes = Map<String, String>.from(map);
|
||||
|
||||
for (final txid in notes.keys) {
|
||||
final note = notes[txid];
|
||||
if (note != null && note.isNotEmpty) {
|
||||
final newNote = TransactionNote(
|
||||
walletId: old.walletId,
|
||||
txid: txid,
|
||||
value: note,
|
||||
);
|
||||
migratedNotes.add(newNote);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reset stellar + tezos address type
|
||||
if (old.coin == Coin.stellar ||
|
||||
old.coin == Coin.stellarTestnet ||
|
||||
old.coin == Coin.tezos) {
|
||||
await MainDB.instance.deleteWalletBlockchainData(old.walletId);
|
||||
}
|
||||
|
||||
//
|
||||
// Set other data values
|
||||
//
|
||||
Map<String, dynamic> otherData = {};
|
||||
|
||||
final List<String>? tokenContractAddresses = walletBox.get(
|
||||
"ethTokenContracts",
|
||||
) as List<String>?;
|
||||
|
||||
if (tokenContractAddresses?.isNotEmpty == true) {
|
||||
otherData[WalletInfoKeys.tokenContractAddresses] = tokenContractAddresses;
|
||||
|
||||
for (final address in tokenContractAddresses!) {
|
||||
final contract = await MainDB.instance.isar.ethContracts
|
||||
.where()
|
||||
.addressEqualTo(address)
|
||||
.findFirst();
|
||||
if (contract != null) {
|
||||
tokenInfo.add(
|
||||
TokenWalletInfo(
|
||||
walletId: old.walletId,
|
||||
tokenAddress: address,
|
||||
tokenFractionDigits: contract.decimals,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// epiccash specifics
|
||||
if (old.coin == Coin.epicCash) {
|
||||
final epicWalletInfo = ExtraEpiccashWalletInfo.fromMap({
|
||||
"receivingIndex": walletBox.get("receivingIndex") as int? ?? 0,
|
||||
"changeIndex": walletBox.get("changeIndex") as int? ?? 0,
|
||||
"slatesToAddresses": walletBox.get("slate_to_address") as Map? ?? {},
|
||||
"slatesToCommits": walletBox.get("slatesToCommits") as Map? ?? {},
|
||||
"lastScannedBlock": walletBox.get("lastScannedBlock") as int? ?? 0,
|
||||
"restoreHeight": walletBox.get("restoreHeight") as int? ?? 0,
|
||||
"creationHeight": walletBox.get("creationHeight") as int? ?? 0,
|
||||
});
|
||||
otherData[WalletInfoKeys.epiccashData] = jsonEncode(
|
||||
epicWalletInfo.toMap(),
|
||||
);
|
||||
} else if (old.coin == Coin.firo || old.coin == Coin.firoTestNet) {
|
||||
otherData[WalletInfoKeys.lelantusCoinIsarRescanRequired] = walletBox
|
||||
.get(WalletInfoKeys.lelantusCoinIsarRescanRequired) as bool? ??
|
||||
true;
|
||||
}
|
||||
|
||||
//
|
||||
// Clear out any keys with null values as they are not needed
|
||||
//
|
||||
otherData.removeWhere((key, value) => value == null);
|
||||
|
||||
final infoMeta = WalletInfoMeta(
|
||||
walletId: old.walletId,
|
||||
isMnemonicVerified: allWalletsBox
|
||||
.get("${old.walletId}_mnemonicHasBeenVerified") as bool? ??
|
||||
false,
|
||||
);
|
||||
|
||||
final info = WalletInfo(
|
||||
coinName: old.coin.name,
|
||||
walletId: old.walletId,
|
||||
name: old.name,
|
||||
mainAddressType: old.coin.primaryAddressType,
|
||||
favouriteOrderIndex: favourites.indexOf(old.walletId),
|
||||
cachedChainHeight: walletBox.get(
|
||||
DBKeys.storedChainHeight,
|
||||
) as int? ??
|
||||
0,
|
||||
cachedBalanceString: walletBox.get(
|
||||
DBKeys.cachedBalance,
|
||||
) as String?,
|
||||
cachedBalanceSecondaryString: walletBox.get(
|
||||
DBKeys.cachedBalanceSecondary,
|
||||
) as String?,
|
||||
otherDataJsonString: jsonEncode(otherData),
|
||||
);
|
||||
|
||||
newInfo.add((info, infoMeta));
|
||||
}
|
||||
|
||||
if (migratedNotes.isNotEmpty) {
|
||||
await MainDB.instance.isar.writeTxn(() async {
|
||||
await MainDB.instance.isar.transactionNotes.putAll(migratedNotes);
|
||||
});
|
||||
}
|
||||
|
||||
if (newInfo.isNotEmpty) {
|
||||
await MainDB.instance.isar.writeTxn(() async {
|
||||
await MainDB.instance.isar.walletInfo
|
||||
.putAll(newInfo.map((e) => e.$1).toList());
|
||||
await MainDB.instance.isar.walletInfoMeta
|
||||
.putAll(newInfo.map((e) => e.$2).toList());
|
||||
|
||||
if (tokenInfo.isNotEmpty) {
|
||||
await MainDB.instance.isar.tokenWalletInfo.putAll(tokenInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await _cleanupOnSuccess(
|
||||
walletIds: newInfo.map((e) => e.$1.walletId).toList());
|
||||
}
|
||||
|
||||
Future<void> _cleanupOnSuccess({required List<String> walletIds}) async {
|
||||
await Hive.deleteBoxFromDisk(DB.boxNameFavoriteWallets);
|
||||
await Hive.deleteBoxFromDisk(DB.boxNameAllWalletsData);
|
||||
for (final walletId in walletIds) {
|
||||
await Hive.deleteBoxFromDisk(walletId);
|
||||
}
|
||||
}
|
|
@ -12,24 +12,24 @@ import 'dart:convert';
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx_client.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:string_validator/string_validator.dart';
|
||||
|
||||
class CachedElectrumX {
|
||||
final ElectrumX electrumXClient;
|
||||
class CachedElectrumXClient {
|
||||
final ElectrumXClient electrumXClient;
|
||||
|
||||
static const minCacheConfirms = 30;
|
||||
|
||||
const CachedElectrumX({
|
||||
const CachedElectrumXClient({
|
||||
required this.electrumXClient,
|
||||
});
|
||||
|
||||
factory CachedElectrumX.from({
|
||||
required ElectrumX electrumXClient,
|
||||
factory CachedElectrumXClient.from({
|
||||
required ElectrumXClient electrumXClient,
|
||||
}) =>
|
||||
CachedElectrumX(
|
||||
CachedElectrumXClient(
|
||||
electrumXClient: electrumXClient,
|
||||
);
|
||||
|
||||
|
@ -56,7 +56,7 @@ class CachedElectrumX {
|
|||
set = Map<String, dynamic>.from(cachedSet);
|
||||
}
|
||||
|
||||
final newSet = await electrumXClient.getAnonymitySet(
|
||||
final newSet = await electrumXClient.getLelantusAnonymitySet(
|
||||
groupId: groupId,
|
||||
blockhash: set["blockHash"] as String,
|
||||
);
|
||||
|
@ -107,6 +107,63 @@ class CachedElectrumX {
|
|||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getSparkAnonymitySet({
|
||||
required String groupId,
|
||||
String blockhash = "",
|
||||
required Coin coin,
|
||||
}) async {
|
||||
try {
|
||||
final box = await DB.instance.getSparkAnonymitySetCacheBox(coin: coin);
|
||||
final cachedSet = box.get(groupId) as Map?;
|
||||
|
||||
Map<String, dynamic> set;
|
||||
|
||||
// null check to see if there is a cached set
|
||||
if (cachedSet == null) {
|
||||
set = {
|
||||
"coinGroupID": int.parse(groupId),
|
||||
"blockHash": blockhash,
|
||||
"setHash": "",
|
||||
"coins": <dynamic>[],
|
||||
};
|
||||
} else {
|
||||
set = Map<String, dynamic>.from(cachedSet);
|
||||
}
|
||||
|
||||
final newSet = await electrumXClient.getSparkAnonymitySet(
|
||||
coinGroupId: groupId,
|
||||
startBlockHash: set["blockHash"] as String,
|
||||
);
|
||||
|
||||
// update set with new data
|
||||
if (newSet["setHash"] != "" && set["setHash"] != newSet["setHash"]) {
|
||||
set["setHash"] = newSet["setHash"];
|
||||
set["blockHash"] = newSet["blockHash"];
|
||||
for (int i = (newSet["coins"] as List).length - 1; i >= 0; i--) {
|
||||
// TODO verify this is correct (or append?)
|
||||
if ((set["coins"] as List)
|
||||
.where((e) => e[0] == newSet["coins"][i][0])
|
||||
.isEmpty) {
|
||||
set["coins"].insert(0, newSet["coins"][i]);
|
||||
}
|
||||
}
|
||||
// save set to db
|
||||
await box.put(groupId, set);
|
||||
Logging.instance.log(
|
||||
"Updated current anonymity set for ${coin.name} with group ID $groupId",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
}
|
||||
|
||||
return set;
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Failed to process CachedElectrumX.getSparkAnonymitySet(): $e\n$s",
|
||||
level: LogLevel.Error);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
String base64ToHex(String source) =>
|
||||
base64Decode(LineSplitter.split(source).join())
|
||||
.map((e) => e.toRadixString(16).padLeft(2, '0'))
|
||||
|
@ -136,6 +193,7 @@ class CachedElectrumX {
|
|||
|
||||
result.remove("hex");
|
||||
result.remove("lelantusData");
|
||||
result.remove("sparkData");
|
||||
|
||||
if (result["confirmations"] != null &&
|
||||
result["confirmations"] as int > minCacheConfirms) {
|
||||
|
@ -173,18 +231,19 @@ class CachedElectrumX {
|
|||
cachedSerials.length - 100, // 100 being some arbitrary buffer
|
||||
);
|
||||
|
||||
final serials = await electrumXClient.getUsedCoinSerials(
|
||||
final serials = await electrumXClient.getLelantusUsedCoinSerials(
|
||||
startNumber: startNumber,
|
||||
);
|
||||
Set<String> newSerials = {};
|
||||
|
||||
for (final element in (serials["serials"] as List)) {
|
||||
if (!isHexadecimal(element as String)) {
|
||||
newSerials.add(base64ToHex(element));
|
||||
} else {
|
||||
newSerials.add(element);
|
||||
}
|
||||
final newSerials = List<String>.from(serials["serials"] as List)
|
||||
.map((e) => !isHexadecimal(e) ? base64ToHex(e) : e)
|
||||
.toSet();
|
||||
|
||||
// ensure we are getting some overlap so we know we are not missing any
|
||||
if (cachedSerials.isNotEmpty && newSerials.isNotEmpty) {
|
||||
assert(cachedSerials.intersection(newSerials).isNotEmpty);
|
||||
}
|
||||
|
||||
cachedSerials.addAll(newSerials);
|
||||
|
||||
final resultingList = cachedSerials.toList();
|
||||
|
@ -197,14 +256,62 @@ class CachedElectrumX {
|
|||
return resultingList;
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Failed to process CachedElectrumX.getTransaction(): $e\n$s",
|
||||
level: LogLevel.Error);
|
||||
"Failed to process CachedElectrumX.getUsedCoinSerials(): $e\n$s",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Set<String>> getSparkUsedCoinsTags({
|
||||
required Coin coin,
|
||||
}) async {
|
||||
try {
|
||||
final box = await DB.instance.getSparkUsedCoinsTagsCacheBox(coin: coin);
|
||||
|
||||
final _list = box.get("tags") as List?;
|
||||
|
||||
Set<String> cachedTags =
|
||||
_list == null ? {} : List<String>.from(_list).toSet();
|
||||
|
||||
final startNumber = max(
|
||||
0,
|
||||
cachedTags.length - 100, // 100 being some arbitrary buffer
|
||||
);
|
||||
|
||||
final tags = await electrumXClient.getSparkUsedCoinsTags(
|
||||
startNumber: startNumber,
|
||||
);
|
||||
|
||||
// final newSerials = List<String>.from(serials["serials"] as List)
|
||||
// .map((e) => !isHexadecimal(e) ? base64ToHex(e) : e)
|
||||
// .toSet();
|
||||
|
||||
// ensure we are getting some overlap so we know we are not missing any
|
||||
if (cachedTags.isNotEmpty && tags.isNotEmpty) {
|
||||
assert(cachedTags.intersection(tags).isNotEmpty);
|
||||
}
|
||||
|
||||
cachedTags.addAll(tags);
|
||||
|
||||
await box.put(
|
||||
"tags",
|
||||
cachedTags.toList(),
|
||||
);
|
||||
|
||||
return cachedTags;
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Failed to process CachedElectrumX.getSparkUsedCoinsTags(): $e\n$s",
|
||||
level: LogLevel.Error,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear all cached transactions for the specified coin
|
||||
Future<void> clearSharedTransactionCache({required Coin coin}) async {
|
||||
await DB.instance.clearSharedTransactionCache(coin: coin);
|
||||
await DB.instance.closeAnonymitySetCacheBox(coin: coin);
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@ import 'dart:io';
|
|||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:decimal/decimal.dart';
|
||||
import 'package:event_bus/event_bus.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart';
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/rpc.dart';
|
||||
import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart';
|
||||
|
@ -58,7 +60,7 @@ class ElectrumXNode {
|
|||
}
|
||||
}
|
||||
|
||||
class ElectrumX {
|
||||
class ElectrumXClient {
|
||||
String get host => _host;
|
||||
late String _host;
|
||||
|
||||
|
@ -81,7 +83,7 @@ class ElectrumX {
|
|||
|
||||
// add finalizer to cancel stream subscription when all references to an
|
||||
// instance of ElectrumX becomes inaccessible
|
||||
static final Finalizer<ElectrumX> _finalizer = Finalizer(
|
||||
static final Finalizer<ElectrumXClient> _finalizer = Finalizer(
|
||||
(p0) {
|
||||
p0._torPreferenceListener?.cancel();
|
||||
p0._torStatusListener?.cancel();
|
||||
|
@ -93,7 +95,7 @@ class ElectrumX {
|
|||
final Mutex _torConnectingLock = Mutex();
|
||||
bool _requireMutex = false;
|
||||
|
||||
ElectrumX({
|
||||
ElectrumXClient({
|
||||
required String host,
|
||||
required int port,
|
||||
required bool useSSL,
|
||||
|
@ -158,14 +160,14 @@ class ElectrumX {
|
|||
);
|
||||
}
|
||||
|
||||
factory ElectrumX.from({
|
||||
factory ElectrumXClient.from({
|
||||
required ElectrumXNode node,
|
||||
required Prefs prefs,
|
||||
required List<ElectrumXNode> failovers,
|
||||
TorService? torService,
|
||||
EventBus? globalEventBusForTesting,
|
||||
}) {
|
||||
return ElectrumX(
|
||||
return ElectrumXClient(
|
||||
host: node.address,
|
||||
port: node.port,
|
||||
useSSL: node.useSSL,
|
||||
|
@ -467,9 +469,9 @@ class ElectrumX {
|
|||
/// and the binary header as a hexadecimal string.
|
||||
/// Ex:
|
||||
/// {
|
||||
// "height": 520481,
|
||||
// "hex": "00000020890208a0ae3a3892aa047c5468725846577cfcd9b512b50000000000000000005dc2b02f2d297a9064ee103036c14d678f9afc7e3d9409cf53fd58b82e938e8ecbeca05a2d2103188ce804c4"
|
||||
// }
|
||||
/// "height": 520481,
|
||||
/// "hex": "00000020890208a0ae3a3892aa047c5468725846577cfcd9b512b50000000000000000005dc2b02f2d297a9064ee103036c14d678f9afc7e3d9409cf53fd58b82e938e8ecbeca05a2d2103188ce804c4"
|
||||
/// }
|
||||
Future<Map<String, dynamic>> getBlockHeadTip({String? requestID}) async {
|
||||
try {
|
||||
final response = await request(
|
||||
|
@ -493,15 +495,15 @@ class ElectrumX {
|
|||
///
|
||||
/// Returns a map with server information
|
||||
/// Ex:
|
||||
// {
|
||||
// "genesis_hash": "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
|
||||
// "hosts": {"14.3.140.101": {"tcp_port": 51001, "ssl_port": 51002}},
|
||||
// "protocol_max": "1.0",
|
||||
// "protocol_min": "1.0",
|
||||
// "pruning": null,
|
||||
// "server_version": "ElectrumX 1.0.17",
|
||||
// "hash_function": "sha256"
|
||||
// }
|
||||
/// {
|
||||
/// "genesis_hash": "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
|
||||
/// "hosts": {"14.3.140.101": {"tcp_port": 51001, "ssl_port": 51002}},
|
||||
/// "protocol_max": "1.0",
|
||||
/// "protocol_min": "1.0",
|
||||
/// "pruning": null,
|
||||
/// "server_version": "ElectrumX 1.0.17",
|
||||
/// "hash_function": "sha256"
|
||||
/// }
|
||||
Future<Map<String, dynamic>> getServerFeatures({String? requestID}) async {
|
||||
try {
|
||||
final response = await request(
|
||||
|
@ -567,20 +569,24 @@ class ElectrumX {
|
|||
/// Returns a list of maps that contain the tx_hash and height of the tx.
|
||||
/// Ex:
|
||||
/// [
|
||||
// {
|
||||
// "height": 200004,
|
||||
// "tx_hash": "acc3758bd2a26f869fcc67d48ff30b96464d476bca82c1cd6656e7d506816412"
|
||||
// },
|
||||
// {
|
||||
// "height": 215008,
|
||||
// "tx_hash": "f3e1bf48975b8d6060a9de8884296abb80be618dc00ae3cb2f6cee3085e09403"
|
||||
// }
|
||||
// ]
|
||||
/// {
|
||||
/// "height": 200004,
|
||||
/// "tx_hash": "acc3758bd2a26f869fcc67d48ff30b96464d476bca82c1cd6656e7d506816412"
|
||||
/// },
|
||||
/// {
|
||||
/// "height": 215008,
|
||||
/// "tx_hash": "f3e1bf48975b8d6060a9de8884296abb80be618dc00ae3cb2f6cee3085e09403"
|
||||
/// }
|
||||
/// ]
|
||||
Future<List<Map<String, dynamic>>> getHistory({
|
||||
required String scripthash,
|
||||
String? requestID,
|
||||
}) async {
|
||||
try {
|
||||
int retryCount = 3;
|
||||
dynamic result;
|
||||
|
||||
while (retryCount > 0 && result is! List) {
|
||||
final response = await request(
|
||||
requestID: requestID,
|
||||
command: 'blockchain.scripthash.get_history',
|
||||
|
@ -589,7 +595,12 @@ class ElectrumX {
|
|||
scripthash,
|
||||
],
|
||||
);
|
||||
return List<Map<String, dynamic>>.from(response["result"] as List);
|
||||
|
||||
result = response["result"];
|
||||
retryCount--;
|
||||
}
|
||||
|
||||
return List<Map<String, dynamic>>.from(result as List);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
|
@ -618,19 +629,19 @@ class ElectrumX {
|
|||
/// Returns a list of maps.
|
||||
/// Ex:
|
||||
/// [
|
||||
// {
|
||||
// "tx_pos": 0,
|
||||
// "value": 45318048,
|
||||
// "tx_hash": "9f2c45a12db0144909b5db269415f7319179105982ac70ed80d76ea79d923ebf",
|
||||
// "height": 437146
|
||||
// },
|
||||
// {
|
||||
// "tx_pos": 0,
|
||||
// "value": 919195,
|
||||
// "tx_hash": "3d2290c93436a3e964cfc2f0950174d8847b1fbe3946432c4784e168da0f019f",
|
||||
// "height": 441696
|
||||
// }
|
||||
// ]
|
||||
/// {
|
||||
/// "tx_pos": 0,
|
||||
/// "value": 45318048,
|
||||
/// "tx_hash": "9f2c45a12db0144909b5db269415f7319179105982ac70ed80d76ea79d923ebf",
|
||||
/// "height": 437146
|
||||
/// },
|
||||
/// {
|
||||
/// "tx_pos": 0,
|
||||
/// "value": 919195,
|
||||
/// "tx_hash": "3d2290c93436a3e964cfc2f0950174d8847b1fbe3946432c4784e168da0f019f",
|
||||
/// "height": 441696
|
||||
/// }
|
||||
/// ]
|
||||
Future<List<Map<String, dynamic>>> getUTXOs({
|
||||
required String scripthash,
|
||||
String? requestID,
|
||||
|
@ -751,7 +762,7 @@ class ElectrumX {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the whole anonymity set for denomination in the groupId.
|
||||
/// Returns the whole Lelantus anonymity set for denomination in the groupId.
|
||||
///
|
||||
/// ex:
|
||||
/// {
|
||||
|
@ -765,7 +776,7 @@ class ElectrumX {
|
|||
/// [dynamic list of length 4],
|
||||
/// ]
|
||||
/// }
|
||||
Future<Map<String, dynamic>> getAnonymitySet({
|
||||
Future<Map<String, dynamic>> getLelantusAnonymitySet({
|
||||
String groupId = "1",
|
||||
String blockhash = "",
|
||||
String? requestID,
|
||||
|
@ -792,8 +803,11 @@ class ElectrumX {
|
|||
//TODO add example to docs
|
||||
///
|
||||
///
|
||||
/// Returns the block height and groupId of pubcoin.
|
||||
Future<dynamic> getMintData({dynamic mints, String? requestID}) async {
|
||||
/// Returns the block height and groupId of a Lelantus pubcoin.
|
||||
Future<dynamic> getLelantusMintData({
|
||||
dynamic mints,
|
||||
String? requestID,
|
||||
}) async {
|
||||
try {
|
||||
final response = await request(
|
||||
requestID: requestID,
|
||||
|
@ -809,12 +823,16 @@ class ElectrumX {
|
|||
}
|
||||
|
||||
//TODO add example to docs
|
||||
/// Returns the whole set of the used coin serials.
|
||||
Future<Map<String, dynamic>> getUsedCoinSerials({
|
||||
/// Returns the whole set of the used Lelantus coin serials.
|
||||
Future<Map<String, dynamic>> getLelantusUsedCoinSerials({
|
||||
String? requestID,
|
||||
required int startNumber,
|
||||
}) async {
|
||||
try {
|
||||
int retryCount = 3;
|
||||
dynamic result;
|
||||
|
||||
while (retryCount > 0 && result is! List) {
|
||||
final response = await request(
|
||||
requestID: requestID,
|
||||
command: 'lelantus.getusedcoinserials',
|
||||
|
@ -823,17 +841,22 @@ class ElectrumX {
|
|||
],
|
||||
requestTimeout: const Duration(minutes: 2),
|
||||
);
|
||||
return Map<String, dynamic>.from(response["result"] as Map);
|
||||
|
||||
result = response["result"];
|
||||
retryCount--;
|
||||
}
|
||||
|
||||
return Map<String, dynamic>.from(result as Map);
|
||||
} catch (e) {
|
||||
Logging.instance.log(e, level: LogLevel.Error);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the latest set id
|
||||
/// Returns the latest Lelantus set id
|
||||
///
|
||||
/// ex: 1
|
||||
Future<int> getLatestCoinId({String? requestID}) async {
|
||||
Future<int> getLelantusLatestCoinId({String? requestID}) async {
|
||||
try {
|
||||
final response = await request(
|
||||
requestID: requestID,
|
||||
|
@ -846,31 +869,127 @@ class ElectrumX {
|
|||
}
|
||||
}
|
||||
|
||||
// /// Returns about 13 megabytes of json data as of march 2, 2022
|
||||
// Future<Map<String, dynamic>> getCoinsForRecovery(
|
||||
// {dynamic setId, String requestID}) async {
|
||||
// try {
|
||||
// final response = await request(
|
||||
// requestID: requestID,
|
||||
// command: 'lelantus.getcoinsforrecovery',
|
||||
// args: [
|
||||
// setId ?? 1,
|
||||
// ],
|
||||
// );
|
||||
// return response["result"];
|
||||
// } catch (e) {
|
||||
// Logging.instance.log(e);
|
||||
// throw e;
|
||||
// }
|
||||
// }
|
||||
// ============== Spark ======================================================
|
||||
|
||||
// New Spark ElectrumX methods:
|
||||
// > Functions provided by ElectrumX servers
|
||||
// > // >
|
||||
|
||||
/// Returns the whole Spark anonymity set for denomination in the groupId.
|
||||
///
|
||||
/// Takes [coinGroupId] and [startBlockHash], if the last is empty it returns full set,
|
||||
/// otherwise returns mint after that block, we need to call this to keep our
|
||||
/// anonymity set data up to date.
|
||||
///
|
||||
/// Returns blockHash (last block hash),
|
||||
/// setHash (hash of current set)
|
||||
/// and coins (the list of pairs serialized coin and tx hash)
|
||||
Future<Map<String, dynamic>> getSparkAnonymitySet({
|
||||
String coinGroupId = "1",
|
||||
String startBlockHash = "",
|
||||
String? requestID,
|
||||
}) async {
|
||||
try {
|
||||
Logging.instance.log("attempting to fetch spark.getsparkanonymityset...",
|
||||
level: LogLevel.Info);
|
||||
final response = await request(
|
||||
requestID: requestID,
|
||||
command: 'spark.getsparkanonymityset',
|
||||
args: [
|
||||
coinGroupId,
|
||||
startBlockHash,
|
||||
],
|
||||
);
|
||||
Logging.instance.log("Fetching spark.getsparkanonymityset finished",
|
||||
level: LogLevel.Info);
|
||||
return Map<String, dynamic>.from(response["result"] as Map);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes [startNumber], if it is 0, we get the full set,
|
||||
/// otherwise the used tags after that number
|
||||
Future<Set<String>> getSparkUsedCoinsTags({
|
||||
String? requestID,
|
||||
required int startNumber,
|
||||
}) async {
|
||||
try {
|
||||
final response = await request(
|
||||
requestID: requestID,
|
||||
command: 'spark.getusedcoinstags',
|
||||
args: [
|
||||
"$startNumber",
|
||||
],
|
||||
requestTimeout: const Duration(minutes: 2),
|
||||
);
|
||||
final map = Map<String, dynamic>.from(response["result"] as Map);
|
||||
final set = Set<String>.from(map["tags"] as List);
|
||||
return await compute(_ffiHashTagsComputeWrapper, set);
|
||||
} catch (e) {
|
||||
Logging.instance.log(e, level: LogLevel.Error);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a list of [sparkCoinHashes] and returns the set id and block height
|
||||
/// for each coin
|
||||
///
|
||||
/// arg:
|
||||
/// {
|
||||
/// "coinHashes": [
|
||||
/// "b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390",
|
||||
/// "b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390",
|
||||
/// ]
|
||||
/// }
|
||||
Future<List<Map<String, dynamic>>> getSparkMintMetaData({
|
||||
String? requestID,
|
||||
required List<String> sparkCoinHashes,
|
||||
}) async {
|
||||
try {
|
||||
final response = await request(
|
||||
requestID: requestID,
|
||||
command: 'spark.getsparkmintmetadata',
|
||||
args: [
|
||||
{
|
||||
"coinHashes": sparkCoinHashes,
|
||||
},
|
||||
],
|
||||
);
|
||||
return List<Map<String, dynamic>>.from(response["result"] as List);
|
||||
} catch (e) {
|
||||
Logging.instance.log(e, level: LogLevel.Error);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the latest Spark set id
|
||||
///
|
||||
/// ex: 1
|
||||
Future<int> getSparkLatestCoinId({
|
||||
String? requestID,
|
||||
}) async {
|
||||
try {
|
||||
final response = await request(
|
||||
requestID: requestID,
|
||||
command: 'spark.getsparklatestcoinid',
|
||||
);
|
||||
return response["result"] as int;
|
||||
} catch (e) {
|
||||
Logging.instance.log(e, level: LogLevel.Error);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
|
||||
/// Get the current fee rate.
|
||||
///
|
||||
/// Returns a map with the kay "rate" that corresponds to the free rate in satoshis
|
||||
/// Ex:
|
||||
/// {
|
||||
// "rate": 1000,
|
||||
// }
|
||||
/// "rate": 1000,
|
||||
/// }
|
||||
Future<Map<String, dynamic>> getFeeRate({String? requestID}) async {
|
||||
try {
|
||||
final response = await request(
|
||||
|
@ -920,3 +1039,7 @@ class ElectrumX {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> _ffiHashTagsComputeWrapper(Set<String> base64Tags) {
|
||||
return LibSpark.hashTags(base64Tags: base64Tags);
|
||||
}
|
|
@ -109,7 +109,9 @@ class JsonRPC {
|
|||
"JsonRPC request: opening socket $host:$port",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
await connect();
|
||||
await connect().timeout(requestTimeout, onTimeout: () {
|
||||
throw Exception("Request timeout: $jsonRpcRequest");
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (_socksSocket == null) {
|
||||
|
@ -117,7 +119,9 @@ class JsonRPC {
|
|||
"JsonRPC request: opening SOCKS socket to $host:$port",
|
||||
level: LogLevel.Info,
|
||||
);
|
||||
await connect();
|
||||
await connect().timeout(requestTimeout, onTimeout: () {
|
||||
throw Exception("Request timeout: $jsonRpcRequest");
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'dart:async';
|
|||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:coinlib_flutter/coinlib_flutter.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cw_core/unspent_coins_info.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
|
@ -27,6 +28,7 @@ import 'package:hive_flutter/hive_flutter.dart';
|
|||
import 'package:isar/isar.dart';
|
||||
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:stackwallet/db/db_version_migration.dart';
|
||||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
|
||||
|
@ -44,6 +46,7 @@ import 'package:stackwallet/pages/pinpad_views/create_pin_view.dart';
|
|||
import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
|
||||
import 'package:stackwallet/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/password/desktop_login_view.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/desktop/storage_crypto_handler_provider.dart';
|
||||
import 'package:stackwallet/providers/global/auto_swb_service_provider.dart';
|
||||
import 'package:stackwallet/providers/global/base_currencies_provider.dart';
|
||||
|
@ -63,13 +66,13 @@ import 'package:stackwallet/services/trade_service.dart';
|
|||
import 'package:stackwallet/themes/theme_providers.dart';
|
||||
import 'package:stackwallet/themes/theme_service.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/db_version_migration.dart';
|
||||
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
|
||||
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/prefs.dart';
|
||||
import 'package:stackwallet/utilities/stack_file_system.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/all_wallets_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/crypto_notifications.dart';
|
||||
import 'package:window_size/window_size.dart';
|
||||
|
||||
|
@ -79,8 +82,15 @@ final openedFromSWBFileStringStateProvider =
|
|||
// main() is the entry point to the app. It initializes Hive (local database),
|
||||
// runs the MyApp widget and checks for new users, caching the value in the
|
||||
// miscellaneous box for later use
|
||||
void main() async {
|
||||
void main(List<String> args) async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
if (Util.isDesktop && args.length == 2 && args.first == "-d") {
|
||||
StackFileSystem.overrideDir = args.last;
|
||||
}
|
||||
|
||||
final loadCoinlibFuture = loadCoinlib();
|
||||
|
||||
GoogleFonts.config.allowRuntimeFetching = false;
|
||||
if (Platform.isIOS) {
|
||||
Util.libraryPath = await getLibraryDirectory();
|
||||
|
@ -213,6 +223,8 @@ void main() async {
|
|||
// overlays: [SystemUiOverlay.bottom]);
|
||||
await NotificationApi.init();
|
||||
|
||||
await loadCoinlibFuture;
|
||||
|
||||
await MainDB.instance.initMainDB();
|
||||
ThemeService.instance.init(MainDB.instance);
|
||||
|
||||
|
@ -344,9 +356,10 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
|||
prefs: ref.read(prefsChangeNotifierProvider),
|
||||
);
|
||||
ref.read(priceAnd24hChangeNotifierProvider).start(true);
|
||||
await ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.load(ref.read(prefsChangeNotifierProvider));
|
||||
await ref.read(pWallets).load(
|
||||
ref.read(prefsChangeNotifierProvider),
|
||||
ref.read(mainDBProvider),
|
||||
);
|
||||
loadingCompleter.complete();
|
||||
// TODO: this should probably run unawaited. Keep commented out for now as proper community nodes ui hasn't been implemented yet
|
||||
// unawaited(_nodeService.updateCommunityNodes());
|
||||
|
@ -735,7 +748,7 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
|
|||
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
// FlutterNativeSplash.remove();
|
||||
if (ref.read(walletsChangeNotifierProvider).hasWallets ||
|
||||
if (ref.read(pAllWalletsInfo).isNotEmpty ||
|
||||
ref.read(prefsChangeNotifierProvider).hasPin) {
|
||||
// return HomeView();
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
||||
class Balance {
|
||||
final Amount total;
|
||||
|
@ -25,6 +26,20 @@ class Balance {
|
|||
required this.pendingSpendable,
|
||||
});
|
||||
|
||||
factory Balance.zeroForCoin({required Coin coin}) {
|
||||
final amount = Amount(
|
||||
rawValue: BigInt.zero,
|
||||
fractionDigits: coin.decimals,
|
||||
);
|
||||
|
||||
return Balance(
|
||||
total: amount,
|
||||
spendable: amount,
|
||||
blockedTotal: amount,
|
||||
pendingSpendable: amount,
|
||||
);
|
||||
}
|
||||
|
||||
String toJsonIgnoreCoin() => jsonEncode({
|
||||
"total": total.toJsonString(),
|
||||
"spendable": spendable.toJsonString(),
|
||||
|
|
|
@ -148,7 +148,7 @@ class Address extends CryptoCurrencyAddress {
|
|||
}
|
||||
}
|
||||
|
||||
// do not modify
|
||||
// do not modify unless you know what the consequences are
|
||||
enum AddressType {
|
||||
p2pkh,
|
||||
p2sh,
|
||||
|
@ -159,7 +159,11 @@ enum AddressType {
|
|||
nonWallet,
|
||||
ethereum,
|
||||
nano,
|
||||
banano;
|
||||
banano,
|
||||
spark,
|
||||
stellar,
|
||||
tezos,
|
||||
;
|
||||
|
||||
String get readableName {
|
||||
switch (this) {
|
||||
|
@ -183,6 +187,12 @@ enum AddressType {
|
|||
return "Nano";
|
||||
case AddressType.banano:
|
||||
return "Banano";
|
||||
case AddressType.spark:
|
||||
return "Spark";
|
||||
case AddressType.stellar:
|
||||
return "Stellar";
|
||||
case AddressType.tezos:
|
||||
return "Tezos";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -263,6 +263,9 @@ const _AddresstypeEnumValueMap = {
|
|||
'ethereum': 7,
|
||||
'nano': 8,
|
||||
'banano': 9,
|
||||
'spark': 10,
|
||||
'stellar': 11,
|
||||
'tezos': 12,
|
||||
};
|
||||
const _AddresstypeValueEnumMap = {
|
||||
0: AddressType.p2pkh,
|
||||
|
@ -275,6 +278,9 @@ const _AddresstypeValueEnumMap = {
|
|||
7: AddressType.ethereum,
|
||||
8: AddressType.nano,
|
||||
9: AddressType.banano,
|
||||
10: AddressType.spark,
|
||||
11: AddressType.stellar,
|
||||
12: AddressType.tezos,
|
||||
};
|
||||
|
||||
Id _addressGetId(Address object) {
|
||||
|
|
|
@ -252,5 +252,8 @@ enum TransactionSubType {
|
|||
mint, // firo specific
|
||||
join, // firo specific
|
||||
ethToken, // eth token
|
||||
cashFusion;
|
||||
cashFusion,
|
||||
sparkMint, // firo specific
|
||||
sparkSpend, // firo specific
|
||||
ordinal;
|
||||
}
|
||||
|
|
|
@ -365,6 +365,9 @@ const _TransactionsubTypeEnumValueMap = {
|
|||
'join': 3,
|
||||
'ethToken': 4,
|
||||
'cashFusion': 5,
|
||||
'sparkMint': 6,
|
||||
'sparkSpend': 7,
|
||||
'ordinal': 8,
|
||||
};
|
||||
const _TransactionsubTypeValueEnumMap = {
|
||||
0: TransactionSubType.none,
|
||||
|
@ -373,6 +376,9 @@ const _TransactionsubTypeValueEnumMap = {
|
|||
3: TransactionSubType.join,
|
||||
4: TransactionSubType.ethToken,
|
||||
5: TransactionSubType.cashFusion,
|
||||
6: TransactionSubType.sparkMint,
|
||||
7: TransactionSubType.sparkSpend,
|
||||
8: TransactionSubType.ordinal,
|
||||
};
|
||||
const _TransactiontypeEnumValueMap = {
|
||||
'outgoing': 0,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
part 'input_v2.g.dart';
|
||||
|
@ -44,6 +46,7 @@ class OutpointV2 {
|
|||
@Embedded()
|
||||
class InputV2 {
|
||||
late final String? scriptSigHex;
|
||||
late final String? scriptSigAsm;
|
||||
late final int? sequence;
|
||||
late final OutpointV2? outpoint;
|
||||
late final List<String> addresses;
|
||||
|
@ -63,6 +66,7 @@ class InputV2 {
|
|||
|
||||
static InputV2 isarCantDoRequiredInDefaultConstructor({
|
||||
required String? scriptSigHex,
|
||||
required String? scriptSigAsm,
|
||||
required int? sequence,
|
||||
required OutpointV2? outpoint,
|
||||
required List<String> addresses,
|
||||
|
@ -74,6 +78,7 @@ class InputV2 {
|
|||
}) =>
|
||||
InputV2()
|
||||
..scriptSigHex = scriptSigHex
|
||||
..scriptSigAsm = scriptSigAsm
|
||||
..sequence = sequence
|
||||
..outpoint = outpoint
|
||||
..addresses = List.unmodifiable(addresses)
|
||||
|
@ -83,8 +88,41 @@ class InputV2 {
|
|||
..coinbase = coinbase
|
||||
..walletOwns = walletOwns;
|
||||
|
||||
static InputV2 fromElectrumxJson({
|
||||
required Map<String, dynamic> json,
|
||||
required OutpointV2? outpoint,
|
||||
required List<String> addresses,
|
||||
required String valueStringSats,
|
||||
required String? coinbase,
|
||||
required bool walletOwns,
|
||||
}) {
|
||||
final dynamicWitness = json["witness"] ?? json["txinwitness"];
|
||||
|
||||
final String? witness;
|
||||
if (dynamicWitness is Map || dynamicWitness is List) {
|
||||
witness = jsonEncode(dynamicWitness);
|
||||
} else if (dynamicWitness is String) {
|
||||
witness = dynamicWitness;
|
||||
} else {
|
||||
witness = null;
|
||||
}
|
||||
|
||||
return InputV2()
|
||||
..scriptSigHex = json["scriptSig"]?["hex"] as String?
|
||||
..scriptSigAsm = json["scriptSig"]?["asm"] as String?
|
||||
..sequence = json["sequence"] as int?
|
||||
..outpoint = outpoint
|
||||
..addresses = List.unmodifiable(addresses)
|
||||
..valueStringSats = valueStringSats
|
||||
..witness = witness
|
||||
..innerRedeemScriptAsm = json["innerRedeemscriptAsm"] as String?
|
||||
..coinbase = coinbase
|
||||
..walletOwns = walletOwns;
|
||||
}
|
||||
|
||||
InputV2 copyWith({
|
||||
String? scriptSigHex,
|
||||
String? scriptSigAsm,
|
||||
int? sequence,
|
||||
OutpointV2? outpoint,
|
||||
List<String>? addresses,
|
||||
|
@ -96,6 +134,7 @@ class InputV2 {
|
|||
}) {
|
||||
return InputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptSigHex: scriptSigHex ?? this.scriptSigHex,
|
||||
scriptSigAsm: scriptSigAsm ?? this.scriptSigAsm,
|
||||
sequence: sequence ?? this.sequence,
|
||||
outpoint: outpoint ?? this.outpoint,
|
||||
addresses: addresses ?? this.addresses,
|
||||
|
@ -111,6 +150,7 @@ class InputV2 {
|
|||
String toString() {
|
||||
return 'InputV2(\n'
|
||||
' scriptSigHex: $scriptSigHex,\n'
|
||||
' scriptSigAsm: $scriptSigAsm,\n'
|
||||
' sequence: $sequence,\n'
|
||||
' outpoint: $outpoint,\n'
|
||||
' addresses: $addresses,\n'
|
||||
|
|
|
@ -357,28 +357,33 @@ const InputV2Schema = Schema(
|
|||
type: IsarType.object,
|
||||
target: r'OutpointV2',
|
||||
),
|
||||
r'scriptSigHex': PropertySchema(
|
||||
r'scriptSigAsm': PropertySchema(
|
||||
id: 4,
|
||||
name: r'scriptSigAsm',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'scriptSigHex': PropertySchema(
|
||||
id: 5,
|
||||
name: r'scriptSigHex',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'sequence': PropertySchema(
|
||||
id: 5,
|
||||
id: 6,
|
||||
name: r'sequence',
|
||||
type: IsarType.long,
|
||||
),
|
||||
r'valueStringSats': PropertySchema(
|
||||
id: 6,
|
||||
id: 7,
|
||||
name: r'valueStringSats',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'walletOwns': PropertySchema(
|
||||
id: 7,
|
||||
id: 8,
|
||||
name: r'walletOwns',
|
||||
type: IsarType.bool,
|
||||
),
|
||||
r'witness': PropertySchema(
|
||||
id: 8,
|
||||
id: 9,
|
||||
name: r'witness',
|
||||
type: IsarType.string,
|
||||
)
|
||||
|
@ -422,6 +427,12 @@ int _inputV2EstimateSize(
|
|||
value, allOffsets[OutpointV2]!, allOffsets);
|
||||
}
|
||||
}
|
||||
{
|
||||
final value = object.scriptSigAsm;
|
||||
if (value != null) {
|
||||
bytesCount += 3 + value.length * 3;
|
||||
}
|
||||
}
|
||||
{
|
||||
final value = object.scriptSigHex;
|
||||
if (value != null) {
|
||||
|
@ -453,11 +464,12 @@ void _inputV2Serialize(
|
|||
OutpointV2Schema.serialize,
|
||||
object.outpoint,
|
||||
);
|
||||
writer.writeString(offsets[4], object.scriptSigHex);
|
||||
writer.writeLong(offsets[5], object.sequence);
|
||||
writer.writeString(offsets[6], object.valueStringSats);
|
||||
writer.writeBool(offsets[7], object.walletOwns);
|
||||
writer.writeString(offsets[8], object.witness);
|
||||
writer.writeString(offsets[4], object.scriptSigAsm);
|
||||
writer.writeString(offsets[5], object.scriptSigHex);
|
||||
writer.writeLong(offsets[6], object.sequence);
|
||||
writer.writeString(offsets[7], object.valueStringSats);
|
||||
writer.writeBool(offsets[8], object.walletOwns);
|
||||
writer.writeString(offsets[9], object.witness);
|
||||
}
|
||||
|
||||
InputV2 _inputV2Deserialize(
|
||||
|
@ -475,11 +487,12 @@ InputV2 _inputV2Deserialize(
|
|||
OutpointV2Schema.deserialize,
|
||||
allOffsets,
|
||||
);
|
||||
object.scriptSigHex = reader.readStringOrNull(offsets[4]);
|
||||
object.sequence = reader.readLongOrNull(offsets[5]);
|
||||
object.valueStringSats = reader.readString(offsets[6]);
|
||||
object.walletOwns = reader.readBool(offsets[7]);
|
||||
object.witness = reader.readStringOrNull(offsets[8]);
|
||||
object.scriptSigAsm = reader.readStringOrNull(offsets[4]);
|
||||
object.scriptSigHex = reader.readStringOrNull(offsets[5]);
|
||||
object.sequence = reader.readLongOrNull(offsets[6]);
|
||||
object.valueStringSats = reader.readString(offsets[7]);
|
||||
object.walletOwns = reader.readBool(offsets[8]);
|
||||
object.witness = reader.readStringOrNull(offsets[9]);
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -505,12 +518,14 @@ P _inputV2DeserializeProp<P>(
|
|||
case 4:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 5:
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 6:
|
||||
return (reader.readString(offset)) as P;
|
||||
return (reader.readLongOrNull(offset)) as P;
|
||||
case 7:
|
||||
return (reader.readBool(offset)) as P;
|
||||
return (reader.readString(offset)) as P;
|
||||
case 8:
|
||||
return (reader.readBool(offset)) as P;
|
||||
case 9:
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
|
@ -1055,6 +1070,154 @@ extension InputV2QueryFilter
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'scriptSigAsm',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition>
|
||||
scriptSigAsmIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'scriptSigAsm',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmEqualTo(
|
||||
String? value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'scriptSigAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmGreaterThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'scriptSigAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmLessThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'scriptSigAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmBetween(
|
||||
String? lower,
|
||||
String? upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'scriptSigAsm',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'scriptSigAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'scriptSigAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmContains(
|
||||
String value,
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'scriptSigAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmMatches(
|
||||
String pattern,
|
||||
{bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'scriptSigAsm',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigAsmIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'scriptSigAsm',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition>
|
||||
scriptSigAsmIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'scriptSigAsm',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<InputV2, InputV2, QAfterFilterCondition> scriptSigHexIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
|
|
|
@ -6,6 +6,7 @@ part 'output_v2.g.dart';
|
|||
@Embedded()
|
||||
class OutputV2 {
|
||||
late final String scriptPubKeyHex;
|
||||
late final String? scriptPubKeyAsm;
|
||||
late final String valueStringSats;
|
||||
late final List<String> addresses;
|
||||
|
||||
|
@ -18,24 +19,28 @@ class OutputV2 {
|
|||
|
||||
static OutputV2 isarCantDoRequiredInDefaultConstructor({
|
||||
required String scriptPubKeyHex,
|
||||
String? scriptPubKeyAsm,
|
||||
required String valueStringSats,
|
||||
required List<String> addresses,
|
||||
required bool walletOwns,
|
||||
}) =>
|
||||
OutputV2()
|
||||
..scriptPubKeyHex = scriptPubKeyHex
|
||||
..scriptPubKeyAsm = scriptPubKeyAsm
|
||||
..valueStringSats = valueStringSats
|
||||
..walletOwns = walletOwns
|
||||
..addresses = List.unmodifiable(addresses);
|
||||
|
||||
OutputV2 copyWith({
|
||||
String? scriptPubKeyHex,
|
||||
String? scriptPubKeyAsm,
|
||||
String? valueStringSats,
|
||||
List<String>? addresses,
|
||||
bool? walletOwns,
|
||||
}) {
|
||||
return OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptPubKeyHex: scriptPubKeyHex ?? this.scriptPubKeyHex,
|
||||
scriptPubKeyAsm: scriptPubKeyAsm ?? this.scriptPubKeyAsm,
|
||||
valueStringSats: valueStringSats ?? this.valueStringSats,
|
||||
addresses: addresses ?? this.addresses,
|
||||
walletOwns: walletOwns ?? this.walletOwns,
|
||||
|
@ -46,6 +51,7 @@ class OutputV2 {
|
|||
Map<String, dynamic> json, {
|
||||
required bool walletOwns,
|
||||
required int decimalPlaces,
|
||||
bool isFullAmountNotSats = false,
|
||||
}) {
|
||||
try {
|
||||
List<String> addresses = [];
|
||||
|
@ -60,9 +66,11 @@ class OutputV2 {
|
|||
|
||||
return OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptPubKeyHex: json["scriptPubKey"]["hex"] as String,
|
||||
scriptPubKeyAsm: json["scriptPubKey"]["asm"] as String?,
|
||||
valueStringSats: parseOutputAmountString(
|
||||
json["value"].toString(),
|
||||
decimalPlaces: decimalPlaces,
|
||||
isFullAmountNotSats: isFullAmountNotSats,
|
||||
),
|
||||
addresses: addresses,
|
||||
walletOwns: walletOwns,
|
||||
|
@ -75,6 +83,7 @@ class OutputV2 {
|
|||
static String parseOutputAmountString(
|
||||
String amount, {
|
||||
required int decimalPlaces,
|
||||
bool isFullAmountNotSats = false,
|
||||
}) {
|
||||
final temp = Decimal.parse(amount);
|
||||
if (temp < Decimal.zero) {
|
||||
|
@ -82,7 +91,9 @@ class OutputV2 {
|
|||
}
|
||||
|
||||
final String valueStringSats;
|
||||
if (temp.isInteger) {
|
||||
if (isFullAmountNotSats) {
|
||||
valueStringSats = temp.shift(decimalPlaces).toBigInt().toString();
|
||||
} else if (temp.isInteger) {
|
||||
valueStringSats = temp.toString();
|
||||
} else {
|
||||
valueStringSats = temp.shift(decimalPlaces).toBigInt().toString();
|
||||
|
@ -95,27 +106,10 @@ class OutputV2 {
|
|||
String toString() {
|
||||
return 'OutputV2(\n'
|
||||
' scriptPubKeyHex: $scriptPubKeyHex,\n'
|
||||
' scriptPubKeyAsm: $scriptPubKeyAsm,\n'
|
||||
' value: $value,\n'
|
||||
' walletOwns: $walletOwns,\n'
|
||||
' addresses: $addresses,\n'
|
||||
')';
|
||||
}
|
||||
}
|
||||
|
||||
bool _listEquals<T, U>(List<T> a, List<U> b) {
|
||||
if (T != U) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.length != b.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
if (a[i] != b[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -18,18 +18,23 @@ const OutputV2Schema = Schema(
|
|||
name: r'addresses',
|
||||
type: IsarType.stringList,
|
||||
),
|
||||
r'scriptPubKeyHex': PropertySchema(
|
||||
r'scriptPubKeyAsm': PropertySchema(
|
||||
id: 1,
|
||||
name: r'scriptPubKeyAsm',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'scriptPubKeyHex': PropertySchema(
|
||||
id: 2,
|
||||
name: r'scriptPubKeyHex',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'valueStringSats': PropertySchema(
|
||||
id: 2,
|
||||
id: 3,
|
||||
name: r'valueStringSats',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'walletOwns': PropertySchema(
|
||||
id: 3,
|
||||
id: 4,
|
||||
name: r'walletOwns',
|
||||
type: IsarType.bool,
|
||||
)
|
||||
|
@ -53,6 +58,12 @@ int _outputV2EstimateSize(
|
|||
bytesCount += value.length * 3;
|
||||
}
|
||||
}
|
||||
{
|
||||
final value = object.scriptPubKeyAsm;
|
||||
if (value != null) {
|
||||
bytesCount += 3 + value.length * 3;
|
||||
}
|
||||
}
|
||||
bytesCount += 3 + object.scriptPubKeyHex.length * 3;
|
||||
bytesCount += 3 + object.valueStringSats.length * 3;
|
||||
return bytesCount;
|
||||
|
@ -65,9 +76,10 @@ void _outputV2Serialize(
|
|||
Map<Type, List<int>> allOffsets,
|
||||
) {
|
||||
writer.writeStringList(offsets[0], object.addresses);
|
||||
writer.writeString(offsets[1], object.scriptPubKeyHex);
|
||||
writer.writeString(offsets[2], object.valueStringSats);
|
||||
writer.writeBool(offsets[3], object.walletOwns);
|
||||
writer.writeString(offsets[1], object.scriptPubKeyAsm);
|
||||
writer.writeString(offsets[2], object.scriptPubKeyHex);
|
||||
writer.writeString(offsets[3], object.valueStringSats);
|
||||
writer.writeBool(offsets[4], object.walletOwns);
|
||||
}
|
||||
|
||||
OutputV2 _outputV2Deserialize(
|
||||
|
@ -78,9 +90,10 @@ OutputV2 _outputV2Deserialize(
|
|||
) {
|
||||
final object = OutputV2();
|
||||
object.addresses = reader.readStringList(offsets[0]) ?? [];
|
||||
object.scriptPubKeyHex = reader.readString(offsets[1]);
|
||||
object.valueStringSats = reader.readString(offsets[2]);
|
||||
object.walletOwns = reader.readBool(offsets[3]);
|
||||
object.scriptPubKeyAsm = reader.readStringOrNull(offsets[1]);
|
||||
object.scriptPubKeyHex = reader.readString(offsets[2]);
|
||||
object.valueStringSats = reader.readString(offsets[3]);
|
||||
object.walletOwns = reader.readBool(offsets[4]);
|
||||
return object;
|
||||
}
|
||||
|
||||
|
@ -94,10 +107,12 @@ P _outputV2DeserializeProp<P>(
|
|||
case 0:
|
||||
return (reader.readStringList(offset) ?? []) as P;
|
||||
case 1:
|
||||
return (reader.readString(offset)) as P;
|
||||
return (reader.readStringOrNull(offset)) as P;
|
||||
case 2:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 3:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 4:
|
||||
return (reader.readBool(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
|
@ -330,6 +345,160 @@ extension OutputV2QueryFilter
|
|||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'scriptPubKeyAsm',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'scriptPubKeyAsm',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmEqualTo(
|
||||
String? value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'scriptPubKeyAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmGreaterThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
include: include,
|
||||
property: r'scriptPubKeyAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmLessThan(
|
||||
String? value, {
|
||||
bool include = false,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.lessThan(
|
||||
include: include,
|
||||
property: r'scriptPubKeyAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmBetween(
|
||||
String? lower,
|
||||
String? upper, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.between(
|
||||
property: r'scriptPubKeyAsm',
|
||||
lower: lower,
|
||||
includeLower: includeLower,
|
||||
upper: upper,
|
||||
includeUpper: includeUpper,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmStartsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.startsWith(
|
||||
property: r'scriptPubKeyAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmEndsWith(
|
||||
String value, {
|
||||
bool caseSensitive = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.endsWith(
|
||||
property: r'scriptPubKeyAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmContains(String value, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.contains(
|
||||
property: r'scriptPubKeyAsm',
|
||||
value: value,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmMatches(String pattern, {bool caseSensitive = true}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.matches(
|
||||
property: r'scriptPubKeyAsm',
|
||||
wildcard: pattern,
|
||||
caseSensitive: caseSensitive,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmIsEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'scriptPubKeyAsm',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyAsmIsNotEmpty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||
property: r'scriptPubKeyAsm',
|
||||
value: '',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<OutputV2, OutputV2, QAfterFilterCondition>
|
||||
scriptPubKeyHexEqualTo(
|
||||
String value, {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
|
@ -5,7 +6,8 @@ import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart'
|
|||
import 'package:stackwallet/models/isar/models/blockchain_data/v2/input_v2.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/extensions/extensions.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
|
||||
|
||||
part 'transaction_v2.g.dart';
|
||||
|
||||
|
@ -37,6 +39,8 @@ class TransactionV2 {
|
|||
@enumerated
|
||||
final TransactionSubType subType;
|
||||
|
||||
final String? otherData;
|
||||
|
||||
TransactionV2({
|
||||
required this.walletId,
|
||||
required this.blockHash,
|
||||
|
@ -49,8 +53,21 @@ class TransactionV2 {
|
|||
required this.version,
|
||||
required this.type,
|
||||
required this.subType,
|
||||
required this.otherData,
|
||||
});
|
||||
|
||||
bool get isEpiccashTransaction =>
|
||||
_getFromOtherData(key: "isEpiccashTransaction") == true;
|
||||
int? get numberOfMessages =>
|
||||
_getFromOtherData(key: "numberOfMessages") as int?;
|
||||
String? get slateId => _getFromOtherData(key: "slateId") as String?;
|
||||
String? get onChainNote => _getFromOtherData(key: "onChainNote") as String?;
|
||||
bool get isCancelled => _getFromOtherData(key: "isCancelled") == true;
|
||||
|
||||
String? get contractAddress =>
|
||||
_getFromOtherData(key: "contractAddress") as String?;
|
||||
int? get nonce => _getFromOtherData(key: "nonce") as int?;
|
||||
|
||||
int getConfirmations(int currentChainHeight) {
|
||||
if (height == null || height! <= 0) return 0;
|
||||
return max(0, currentChainHeight - (height! - 1));
|
||||
|
@ -61,37 +78,63 @@ class TransactionV2 {
|
|||
return confirmations >= minimumConfirms;
|
||||
}
|
||||
|
||||
Amount getFee({required Coin coin}) {
|
||||
Amount getFee({required int fractionDigits}) {
|
||||
// check for override fee
|
||||
final fee = _getOverrideFee();
|
||||
if (fee != null) {
|
||||
return fee;
|
||||
}
|
||||
|
||||
final inSum =
|
||||
inputs.map((e) => e.value).reduce((value, element) => value += element);
|
||||
final outSum = outputs
|
||||
.map((e) => e.value)
|
||||
.reduce((value, element) => value += element);
|
||||
|
||||
return Amount(rawValue: inSum - outSum, fractionDigits: coin.decimals);
|
||||
return Amount(rawValue: inSum - outSum, fractionDigits: fractionDigits);
|
||||
}
|
||||
|
||||
Amount getAmountReceivedThisWallet({required Coin coin}) {
|
||||
Amount getAmountReceivedInThisWallet({required int fractionDigits}) {
|
||||
final outSum = outputs
|
||||
.where((e) => e.walletOwns)
|
||||
.fold(BigInt.zero, (p, e) => p + e.value);
|
||||
|
||||
return Amount(rawValue: outSum, fractionDigits: coin.decimals);
|
||||
return Amount(rawValue: outSum, fractionDigits: fractionDigits);
|
||||
}
|
||||
|
||||
Amount getAmountSentFromThisWallet({required Coin coin}) {
|
||||
Amount getAmountSparkSelfMinted({required int fractionDigits}) {
|
||||
final outSum = outputs.where((e) {
|
||||
final op = e.scriptPubKeyHex.substring(0, 2).toUint8ListFromHex.first;
|
||||
return e.walletOwns && (op == OP_SPARKMINT);
|
||||
}).fold(BigInt.zero, (p, e) => p + e.value);
|
||||
|
||||
return Amount(rawValue: outSum, fractionDigits: fractionDigits);
|
||||
}
|
||||
|
||||
Amount getAmountSentFromThisWallet({required int fractionDigits}) {
|
||||
final inSum = inputs
|
||||
.where((e) => e.walletOwns)
|
||||
.fold(BigInt.zero, (p, e) => p + e.value);
|
||||
|
||||
return Amount(
|
||||
Amount amount = Amount(
|
||||
rawValue: inSum,
|
||||
fractionDigits: coin.decimals,
|
||||
fractionDigits: fractionDigits,
|
||||
) -
|
||||
getAmountReceivedThisWallet(
|
||||
coin: coin,
|
||||
) -
|
||||
getFee(coin: coin);
|
||||
getAmountReceivedInThisWallet(
|
||||
fractionDigits: fractionDigits,
|
||||
);
|
||||
|
||||
if (subType != TransactionSubType.ethToken) {
|
||||
amount = amount - getFee(fractionDigits: fractionDigits);
|
||||
}
|
||||
|
||||
// negative amounts are likely an error or can happen with coins such as eth
|
||||
// that don't use the btc style inputs/outputs
|
||||
if (amount.raw < BigInt.zero) {
|
||||
return Amount.zeroWith(fractionDigits: fractionDigits);
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
Set<String> associatedAddresses() => {
|
||||
|
@ -99,6 +142,95 @@ class TransactionV2 {
|
|||
...outputs.map((e) => e.addresses).expand((e) => e),
|
||||
};
|
||||
|
||||
Amount? _getOverrideFee() {
|
||||
try {
|
||||
return Amount.fromSerializedJsonString(
|
||||
_getFromOtherData(key: "overrideFee") as String,
|
||||
);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String statusLabel({
|
||||
required int currentChainHeight,
|
||||
required int minConfirms,
|
||||
}) {
|
||||
if (subType == TransactionSubType.cashFusion ||
|
||||
subType == TransactionSubType.mint ||
|
||||
(subType == TransactionSubType.sparkMint &&
|
||||
type == TransactionType.sentToSelf)) {
|
||||
if (isConfirmed(currentChainHeight, minConfirms)) {
|
||||
return "Anonymized";
|
||||
} else {
|
||||
return "Anonymizing";
|
||||
}
|
||||
}
|
||||
|
||||
if (isEpiccashTransaction) {
|
||||
if (slateId == null) {
|
||||
return "Restored Funds";
|
||||
}
|
||||
|
||||
if (isCancelled) {
|
||||
return "Cancelled";
|
||||
} else if (type == TransactionType.incoming) {
|
||||
if (isConfirmed(currentChainHeight, minConfirms)) {
|
||||
return "Received";
|
||||
} else {
|
||||
if (numberOfMessages == 1) {
|
||||
return "Receiving (waiting for sender)";
|
||||
} else if ((numberOfMessages ?? 0) > 1) {
|
||||
return "Receiving (waiting for confirmations)"; // TODO test if the sender still has to open again after the receiver has 2 messages present, ie. sender->receiver->sender->node (yes) vs. sender->receiver->node (no)
|
||||
} else {
|
||||
return "Receiving";
|
||||
}
|
||||
}
|
||||
} else if (type == TransactionType.outgoing) {
|
||||
if (isConfirmed(currentChainHeight, minConfirms)) {
|
||||
return "Sent (confirmed)";
|
||||
} else {
|
||||
if (numberOfMessages == 1) {
|
||||
return "Sending (waiting for receiver)";
|
||||
} else if ((numberOfMessages ?? 0) > 1) {
|
||||
return "Sending (waiting for confirmations)";
|
||||
} else {
|
||||
return "Sending";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type == TransactionType.incoming) {
|
||||
// if (_transaction.isMinting) {
|
||||
// return "Minting";
|
||||
// } else
|
||||
if (isConfirmed(currentChainHeight, minConfirms)) {
|
||||
return "Received";
|
||||
} else {
|
||||
return "Receiving";
|
||||
}
|
||||
} else if (type == TransactionType.outgoing) {
|
||||
if (isConfirmed(currentChainHeight, minConfirms)) {
|
||||
return "Sent";
|
||||
} else {
|
||||
return "Sending";
|
||||
}
|
||||
} else if (type == TransactionType.sentToSelf) {
|
||||
return "Sent to self";
|
||||
} else {
|
||||
return type.name;
|
||||
}
|
||||
}
|
||||
|
||||
dynamic _getFromOtherData({required dynamic key}) {
|
||||
if (otherData == null) {
|
||||
return null;
|
||||
}
|
||||
final map = jsonDecode(otherData!);
|
||||
return map[key];
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TransactionV2(\n'
|
||||
|
@ -113,15 +245,7 @@ class TransactionV2 {
|
|||
' version: $version,\n'
|
||||
' inputs: $inputs,\n'
|
||||
' outputs: $outputs,\n'
|
||||
' otherData: $otherData,\n'
|
||||
')';
|
||||
}
|
||||
}
|
||||
|
||||
enum TxDirection {
|
||||
outgoing,
|
||||
incoming;
|
||||
}
|
||||
|
||||
enum TxType {
|
||||
normal,
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,8 +25,22 @@ class TransactionNote {
|
|||
@Index()
|
||||
late String walletId;
|
||||
|
||||
@Index(unique: true, composite: [CompositeIndex("walletId")])
|
||||
@Index(
|
||||
unique: true,
|
||||
replace: true,
|
||||
composite: [CompositeIndex("walletId")],
|
||||
)
|
||||
late String txid;
|
||||
|
||||
late String value;
|
||||
|
||||
TransactionNote copyWith({
|
||||
String? value,
|
||||
}) {
|
||||
return TransactionNote(
|
||||
walletId: walletId,
|
||||
txid: txid,
|
||||
value: value ?? this.value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ const TransactionNoteSchema = CollectionSchema(
|
|||
id: -2771771174176035985,
|
||||
name: r'txid_walletId',
|
||||
unique: true,
|
||||
replace: false,
|
||||
replace: true,
|
||||
properties: [
|
||||
IndexPropertySchema(
|
||||
name: r'txid',
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/models/wallet_restore_state.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/utilities/enums/stack_restoring_status.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.dart';
|
||||
|
||||
class StackRestoringUIState extends ChangeNotifier {
|
||||
bool _walletsWasSet = false;
|
||||
|
@ -93,14 +93,14 @@ class StackRestoringUIState extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
List<Manager> get managers {
|
||||
List<Manager> _managers = [];
|
||||
List<Wallet> get wallets {
|
||||
List<Wallet> _wallets = [];
|
||||
for (final item in _walletStates.values) {
|
||||
if (item.manager != null) {
|
||||
_managers.add(item.manager!);
|
||||
if (item.wallet != null) {
|
||||
_wallets.add(item.wallet!);
|
||||
}
|
||||
}
|
||||
return _managers;
|
||||
return _wallets;
|
||||
}
|
||||
|
||||
Map<String, WalletRestoreState> _walletStates = {};
|
||||
|
@ -132,15 +132,14 @@ class StackRestoringUIState extends ChangeNotifier {
|
|||
void update({
|
||||
required String walletId,
|
||||
required StackRestoringStatus restoringStatus,
|
||||
Manager? manager,
|
||||
Wallet? wallet,
|
||||
String? address,
|
||||
String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
int? height,
|
||||
}) {
|
||||
_walletStates[walletId]!.restoringState = restoringStatus;
|
||||
_walletStates[walletId]!.manager =
|
||||
manager ?? _walletStates[walletId]!.manager;
|
||||
_walletStates[walletId]!.wallet = wallet ?? _walletStates[walletId]!.wallet;
|
||||
_walletStates[walletId]!.address =
|
||||
address ?? _walletStates[walletId]!.address;
|
||||
_walletStates[walletId]!.mnemonic =
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/utxo.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/wallets/models/tx_recipient.dart';
|
||||
|
||||
// TODO use something like this instead of Map<String, dynamic> transactionObject
|
||||
|
||||
|
@ -43,13 +44,3 @@ class TxInfo {
|
|||
recipients: recipients ?? this.recipients,
|
||||
);
|
||||
}
|
||||
|
||||
class TxRecipient {
|
||||
final String address;
|
||||
final Amount amount;
|
||||
|
||||
TxRecipient({
|
||||
required this.address,
|
||||
required this.amount,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,17 +8,17 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/stack_restoring_status.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.dart';
|
||||
|
||||
class WalletRestoreState extends ChangeNotifier {
|
||||
final String walletId;
|
||||
final String walletName;
|
||||
final Coin coin;
|
||||
late StackRestoringStatus _restoringStatus;
|
||||
Manager? manager;
|
||||
Wallet? wallet;
|
||||
String? address;
|
||||
String? mnemonic;
|
||||
String? mnemonicPassphrase;
|
||||
|
@ -35,7 +35,7 @@ class WalletRestoreState extends ChangeNotifier {
|
|||
required this.walletName,
|
||||
required this.coin,
|
||||
required StackRestoringStatus restoringStatus,
|
||||
this.manager,
|
||||
this.wallet,
|
||||
this.address,
|
||||
this.mnemonic,
|
||||
this.mnemonicPassphrase,
|
||||
|
@ -54,7 +54,7 @@ class WalletRestoreState extends ChangeNotifier {
|
|||
walletName: walletName,
|
||||
coin: coin,
|
||||
restoringStatus: restoringStatus ?? _restoringStatus,
|
||||
manager: manager,
|
||||
wallet: wallet,
|
||||
address: this.address,
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
|
|
|
@ -24,13 +24,14 @@ import 'package:stackwallet/pages/add_wallet_views/add_token_view/sub_widgets/ad
|
|||
import 'package:stackwallet/pages/home_view/home_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/default_eth_tokens.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.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';
|
||||
|
@ -98,10 +99,8 @@ class _EditWalletTokensViewState extends ConsumerState<EditWalletTokensView> {
|
|||
.map((e) => e.token.address)
|
||||
.toList();
|
||||
|
||||
final ethWallet = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as EthereumWallet;
|
||||
final ethWallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet;
|
||||
|
||||
await ethWallet.updateTokenContracts(selectedTokens);
|
||||
if (mounted) {
|
||||
|
@ -122,7 +121,7 @@ class _EditWalletTokensViewState extends ConsumerState<EditWalletTokensView> {
|
|||
unawaited(
|
||||
showFloatingFlushBar(
|
||||
type: FlushBarType.success,
|
||||
message: "${ethWallet.walletName} tokens saved",
|
||||
message: "${ethWallet.info.name} tokens saved",
|
||||
context: context,
|
||||
),
|
||||
);
|
||||
|
@ -181,11 +180,7 @@ class _EditWalletTokensViewState extends ConsumerState<EditWalletTokensView> {
|
|||
|
||||
tokenEntities.addAll(contracts.map((e) => AddTokenListElementData(e)));
|
||||
|
||||
final walletContracts = (ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as EthereumWallet)
|
||||
.getWalletTokenContractAddresses();
|
||||
final walletContracts = ref.read(pWalletTokenAddresses(widget.walletId));
|
||||
|
||||
final shouldMarkAsSelectedContracts = [
|
||||
...walletContracts,
|
||||
|
@ -209,8 +204,7 @@ class _EditWalletTokensViewState extends ConsumerState<EditWalletTokensView> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
final walletName = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).walletName));
|
||||
final walletName = ref.watch(pWalletName(widget.walletId));
|
||||
|
||||
if (isDesktop) {
|
||||
return ConditionalParent(
|
||||
|
|
|
@ -126,7 +126,7 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
|
|||
void initState() {
|
||||
_searchFieldController = TextEditingController();
|
||||
_searchFocusNode = FocusNode();
|
||||
_coinsTestnet.remove(Coin.firoTestNet);
|
||||
// _coinsTestnet.remove(Coin.firoTestNet);
|
||||
if (Platform.isWindows) {
|
||||
_coins.remove(Coin.monero);
|
||||
_coins.remove(Coin.wownero);
|
||||
|
|
|
@ -12,22 +12,22 @@ import 'dart:async';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_service_provider.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/ui/verify_recovery_phrase/mnemonic_word_count_state_provider.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/add_wallet_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/name_generator.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||
|
@ -81,10 +81,15 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
|
|||
void initState() {
|
||||
isDesktop = Util.isDesktop;
|
||||
|
||||
ref.read(walletsServiceChangeNotifierProvider).walletNames.then(
|
||||
(value) => namesToExclude.addAll(
|
||||
value.values.map((e) => e.name),
|
||||
),
|
||||
ref
|
||||
.read(mainDBProvider)
|
||||
.isar
|
||||
.walletInfo
|
||||
.where()
|
||||
.nameProperty()
|
||||
.findAll()
|
||||
.then(
|
||||
(values) => namesToExclude.addAll(values),
|
||||
);
|
||||
generator = NameGenerator();
|
||||
addWalletType = widget.addWalletType;
|
||||
|
@ -333,22 +338,9 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
|
|||
child: TextButton(
|
||||
onPressed: _nextEnabled
|
||||
? () async {
|
||||
final walletsService =
|
||||
ref.read(walletsServiceChangeNotifierProvider);
|
||||
final name = textEditingController.text;
|
||||
|
||||
final hasDuplicateName =
|
||||
await walletsService.checkForDuplicate(name);
|
||||
|
||||
if (mounted) {
|
||||
if (hasDuplicateName) {
|
||||
unawaited(showFloatingFlushBar(
|
||||
type: FlushBarType.warning,
|
||||
message: "Wallet name already in use.",
|
||||
iconAsset: Assets.svg.circleAlert,
|
||||
context: context,
|
||||
));
|
||||
} else {
|
||||
// hide keyboard if has focus
|
||||
if (FocusScope.of(context).hasFocus) {
|
||||
FocusScope.of(context).unfocus();
|
||||
|
@ -357,9 +349,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
|
|||
}
|
||||
|
||||
if (mounted) {
|
||||
ref
|
||||
.read(mnemonicWordCountStateProvider.state)
|
||||
.state =
|
||||
ref.read(mnemonicWordCountStateProvider.state).state =
|
||||
Constants.possibleLengthsForCoin(coin).last;
|
||||
ref.read(pNewWalletOptions.notifier).state = null;
|
||||
|
||||
|
@ -394,7 +384,6 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
: null,
|
||||
style: _nextEnabled
|
||||
? Theme.of(context)
|
||||
|
|
|
@ -21,14 +21,16 @@ import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_wa
|
|||
import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/services/coins/manager.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/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||
|
@ -37,14 +39,14 @@ import 'package:tuple/tuple.dart';
|
|||
class NewWalletRecoveryPhraseView extends ConsumerStatefulWidget {
|
||||
const NewWalletRecoveryPhraseView({
|
||||
Key? key,
|
||||
required this.manager,
|
||||
required this.wallet,
|
||||
required this.mnemonic,
|
||||
this.clipboardInterface = const ClipboardWrapper(),
|
||||
}) : super(key: key);
|
||||
|
||||
static const routeName = "/newWalletRecoveryPhrase";
|
||||
|
||||
final Manager manager;
|
||||
final Wallet wallet;
|
||||
final List<String> mnemonic;
|
||||
|
||||
final ClipboardInterface clipboardInterface;
|
||||
|
@ -58,14 +60,14 @@ class _NewWalletRecoveryPhraseViewState
|
|||
extends ConsumerState<NewWalletRecoveryPhraseView>
|
||||
// with WidgetsBindingObserver
|
||||
{
|
||||
late Manager _manager;
|
||||
late Wallet _wallet;
|
||||
late List<String> _mnemonic;
|
||||
late ClipboardInterface _clipboardInterface;
|
||||
late final bool isDesktop;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_manager = widget.manager;
|
||||
_wallet = widget.wallet;
|
||||
_mnemonic = widget.mnemonic;
|
||||
_clipboardInterface = widget.clipboardInterface;
|
||||
isDesktop = Util.isDesktop;
|
||||
|
@ -78,14 +80,14 @@ class _NewWalletRecoveryPhraseViewState
|
|||
}
|
||||
|
||||
Future<void> delete() async {
|
||||
await _wallet.exit();
|
||||
await ref
|
||||
.read(walletsServiceChangeNotifierProvider)
|
||||
.deleteWallet(_manager.walletName, false);
|
||||
await _manager.exitCurrentWallet();
|
||||
.read(pWallets)
|
||||
.deleteWallet(_wallet.info, ref.read(secureStoreProvider));
|
||||
}
|
||||
|
||||
Future<void> _copy() async {
|
||||
final words = await _manager.mnemonic;
|
||||
final words = _mnemonic;
|
||||
await _clipboardInterface.setData(ClipboardData(text: words.join(" ")));
|
||||
unawaited(showFloatingFlushBar(
|
||||
type: FlushBarType.info,
|
||||
|
@ -191,7 +193,7 @@ class _NewWalletRecoveryPhraseViewState
|
|||
),
|
||||
if (!isDesktop)
|
||||
Text(
|
||||
_manager.walletName,
|
||||
ref.watch(pWalletName(_wallet.walletId)),
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.label(context).copyWith(
|
||||
fontSize: 12,
|
||||
|
@ -305,7 +307,7 @@ class _NewWalletRecoveryPhraseViewState
|
|||
|
||||
unawaited(Navigator.of(context).pushNamed(
|
||||
VerifyRecoveryPhraseView.routeName,
|
||||
arguments: Tuple2(_manager, _mnemonic),
|
||||
arguments: Tuple2(_wallet, _mnemonic),
|
||||
));
|
||||
},
|
||||
style: Theme.of(context)
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
*/
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
@ -17,10 +19,9 @@ import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet
|
|||
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/recovery_phrase_explanation_dialog.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/services/coins/coin_service.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
|
@ -30,6 +31,10 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
|||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/crypto_currency/coins/tezos.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.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_app_bar.dart';
|
||||
|
@ -453,14 +458,17 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
},
|
||||
));
|
||||
|
||||
final walletsService = ref.read(
|
||||
walletsServiceChangeNotifierProvider);
|
||||
|
||||
final walletId =
|
||||
await walletsService.addNewWallet(
|
||||
name: walletName,
|
||||
coin: coin,
|
||||
shouldNotifyListeners: false,
|
||||
final info = WalletInfo.createNew(
|
||||
coin: widget.coin,
|
||||
name: widget.walletName,
|
||||
otherDataJsonString: coin == Coin.tezos
|
||||
? jsonEncode({
|
||||
WalletInfoKeys
|
||||
.tezosDerivationPath:
|
||||
Tezos.standardDerivationPath
|
||||
.value,
|
||||
})
|
||||
: null,
|
||||
);
|
||||
|
||||
var node = ref
|
||||
|
@ -480,44 +488,73 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
|
||||
final txTracker =
|
||||
TransactionNotificationTracker(
|
||||
walletId: walletId!);
|
||||
|
||||
final failovers = ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.failoverNodesFor(coin: widget.coin);
|
||||
|
||||
final wallet = CoinServiceAPI.from(
|
||||
coin,
|
||||
walletId,
|
||||
walletName,
|
||||
ref.read(secureStoreProvider),
|
||||
node,
|
||||
txTracker,
|
||||
ref.read(prefsChangeNotifierProvider),
|
||||
failovers,
|
||||
walletId: info.walletId,
|
||||
);
|
||||
|
||||
final manager = Manager(wallet);
|
||||
int? wordCount;
|
||||
String? mnemonicPassphrase;
|
||||
String? mnemonic;
|
||||
String? privateKey;
|
||||
|
||||
if (coin.hasMnemonicPassphraseSupport &&
|
||||
ref
|
||||
wordCount =
|
||||
Constants.defaultSeedPhraseLengthFor(
|
||||
coin: info.coin,
|
||||
);
|
||||
|
||||
if (coin == Coin.monero ||
|
||||
coin == Coin.wownero) {
|
||||
// currently a special case due to the
|
||||
// xmr/wow libraries handling their
|
||||
// own mnemonic generation
|
||||
} else if (wordCount > 0) {
|
||||
if (ref
|
||||
.read(pNewWalletOptions.state)
|
||||
.state !=
|
||||
null) {
|
||||
await manager.initializeNew((
|
||||
mnemonicPassphrase: ref
|
||||
if (coin.hasMnemonicPassphraseSupport) {
|
||||
mnemonicPassphrase = ref
|
||||
.read(pNewWalletOptions.state)
|
||||
.state!
|
||||
.mnemonicPassphrase,
|
||||
wordCount: ref
|
||||
.mnemonicPassphrase;
|
||||
} else {}
|
||||
|
||||
wordCount = ref
|
||||
.read(pNewWalletOptions.state)
|
||||
.state!
|
||||
.mnemonicWordsCount,
|
||||
));
|
||||
.mnemonicWordsCount;
|
||||
} else {
|
||||
await manager.initializeNew(null);
|
||||
mnemonicPassphrase = "";
|
||||
}
|
||||
|
||||
if (wordCount < 12 ||
|
||||
24 < wordCount ||
|
||||
wordCount % 3 != 0) {
|
||||
throw Exception("Invalid word count");
|
||||
}
|
||||
|
||||
final strength = (wordCount ~/ 3) * 32;
|
||||
|
||||
mnemonic = bip39.generateMnemonic(
|
||||
strength: strength,
|
||||
);
|
||||
}
|
||||
|
||||
final wallet = await Wallet.create(
|
||||
walletInfo: info,
|
||||
mainDB: ref.read(mainDBProvider),
|
||||
secureStorageInterface:
|
||||
ref.read(secureStoreProvider),
|
||||
nodeService: ref.read(
|
||||
nodeServiceChangeNotifierProvider),
|
||||
prefs:
|
||||
ref.read(prefsChangeNotifierProvider),
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
mnemonic: mnemonic,
|
||||
privateKey: privateKey,
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
|
||||
// pop progress dialog
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
|
@ -531,8 +568,9 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
unawaited(Navigator.of(context).pushNamed(
|
||||
NewWalletRecoveryPhraseView.routeName,
|
||||
arguments: Tuple2(
|
||||
manager,
|
||||
await manager.mnemonic,
|
||||
wallet,
|
||||
await (wallet as MnemonicInterface)
|
||||
.getMnemonicAsWords(),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
|
@ -32,10 +33,9 @@ import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/v
|
|||
import 'package:stackwallet/pages/home_view/home_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/services/coins/coin_service.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
|
@ -50,6 +50,10 @@ import 'package:stackwallet/utilities/enums/form_input_status_enum.dart';
|
|||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/supporting/epiccash_wallet_info_extension.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||
|
@ -201,6 +205,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
|||
mnemonic = mnemonic.trim();
|
||||
|
||||
int height = 0;
|
||||
String? otherDataJsonString;
|
||||
|
||||
if (widget.coin == Coin.monero) {
|
||||
height = monero.getHeigthByDate(date: widget.restoreFromDate);
|
||||
|
@ -227,6 +232,22 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
|||
if (height < 0) {
|
||||
height = 0;
|
||||
}
|
||||
|
||||
otherDataJsonString = jsonEncode(
|
||||
{
|
||||
WalletInfoKeys.epiccashData: jsonEncode(
|
||||
ExtraEpiccashWalletInfo(
|
||||
receivingIndex: 0,
|
||||
changeIndex: 0,
|
||||
slatesToAddresses: {},
|
||||
slatesToCommits: {},
|
||||
lastScannedBlock: height,
|
||||
restoreHeight: height,
|
||||
creationHeight: height,
|
||||
).toMap(),
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: do actual check to make sure it is a valid mnemonic for monero
|
||||
|
@ -239,13 +260,14 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
|||
));
|
||||
} else {
|
||||
if (!Platform.isLinux) await Wakelock.enable();
|
||||
final walletsService = ref.read(walletsServiceChangeNotifierProvider);
|
||||
|
||||
final walletId = await walletsService.addNewWallet(
|
||||
name: widget.walletName,
|
||||
final info = WalletInfo.createNew(
|
||||
coin: widget.coin,
|
||||
shouldNotifyListeners: false,
|
||||
name: widget.walletName,
|
||||
restoreHeight: height,
|
||||
otherDataJsonString: otherDataJsonString,
|
||||
);
|
||||
|
||||
bool isRestoring = true;
|
||||
// show restoring in progress
|
||||
unawaited(showDialog<dynamic>(
|
||||
|
@ -256,13 +278,10 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
|||
return RestoringDialog(
|
||||
onCancel: () async {
|
||||
isRestoring = false;
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider.notifier)
|
||||
.removeWallet(walletId: walletId!);
|
||||
|
||||
await walletsService.deleteWallet(
|
||||
widget.walletName,
|
||||
false,
|
||||
await ref.read(pWallets).deleteWallet(
|
||||
info,
|
||||
ref.read(secureStoreProvider),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -281,49 +300,35 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
|||
);
|
||||
}
|
||||
|
||||
final txTracker = TransactionNotificationTracker(walletId: walletId!);
|
||||
|
||||
final failovers = ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.failoverNodesFor(coin: widget.coin);
|
||||
|
||||
final wallet = CoinServiceAPI.from(
|
||||
widget.coin,
|
||||
walletId,
|
||||
widget.walletName,
|
||||
ref.read(secureStoreProvider),
|
||||
node,
|
||||
txTracker,
|
||||
ref.read(prefsChangeNotifierProvider),
|
||||
failovers,
|
||||
);
|
||||
|
||||
final manager = Manager(wallet);
|
||||
final txTracker =
|
||||
TransactionNotificationTracker(walletId: info.walletId);
|
||||
|
||||
try {
|
||||
// TODO GUI option to set maxUnusedAddressGap?
|
||||
// default is 20 but it may miss some transactions if
|
||||
// the previous wallet software generated many addresses
|
||||
// without using them
|
||||
await manager.recoverFromMnemonic(
|
||||
mnemonic: mnemonic,
|
||||
final wallet = await Wallet.create(
|
||||
walletInfo: info,
|
||||
mainDB: ref.read(mainDBProvider),
|
||||
secureStorageInterface: ref.read(secureStoreProvider),
|
||||
nodeService: ref.read(nodeServiceChangeNotifierProvider),
|
||||
prefs: ref.read(prefsChangeNotifierProvider),
|
||||
mnemonicPassphrase: widget.mnemonicPassphrase,
|
||||
maxUnusedAddressGap: widget.coin == Coin.firo ? 50 : 20,
|
||||
maxNumberOfIndexesToCheck: 1000,
|
||||
height: height,
|
||||
mnemonic: mnemonic,
|
||||
);
|
||||
|
||||
if (wallet is EpiccashWallet) {
|
||||
await wallet.init(isRestore: true);
|
||||
} else {
|
||||
await wallet.init();
|
||||
}
|
||||
|
||||
await wallet.recover(isRescan: false);
|
||||
|
||||
// check if state is still active before continuing
|
||||
if (mounted) {
|
||||
await ref
|
||||
.read(walletsServiceChangeNotifierProvider)
|
||||
.setMnemonicVerified(
|
||||
walletId: manager.walletId,
|
||||
await wallet.info.setMnemonicVerified(
|
||||
isar: ref.read(mainDBProvider).isar,
|
||||
);
|
||||
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider.notifier)
|
||||
.addWallet(walletId: manager.walletId, manager: manager);
|
||||
ref.read(pWallets).addWallet(wallet);
|
||||
|
||||
final isCreateSpecialEthWallet =
|
||||
ref.read(createSpecialEthWalletRoutingFlag);
|
||||
|
@ -360,11 +365,11 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
|||
(route) => false,
|
||||
),
|
||||
);
|
||||
if (manager.coin == Coin.ethereum) {
|
||||
if (info.coin == Coin.ethereum) {
|
||||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
EditWalletTokensView.routeName,
|
||||
arguments: manager.walletId,
|
||||
arguments: wallet.walletId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -410,8 +415,8 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
|||
builder: (context) {
|
||||
return RestoreFailedDialog(
|
||||
errorMessage: e.toString(),
|
||||
walletId: wallet.walletId,
|
||||
walletName: wallet.walletName,
|
||||
walletId: info.walletId,
|
||||
walletName: info.name,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||
|
||||
class RestoreFailedDialog extends ConsumerStatefulWidget {
|
||||
|
@ -63,14 +65,11 @@ class _RestoreFailedDialogState extends ConsumerState<RestoreFailedDialog> {
|
|||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
onPressed: () async {
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider.notifier)
|
||||
.removeWallet(walletId: walletId);
|
||||
|
||||
await ref.read(walletsServiceChangeNotifierProvider).deleteWallet(
|
||||
walletName,
|
||||
false,
|
||||
await ref.read(pWallets).deleteWallet(
|
||||
ref.read(pWalletInfo(walletId)),
|
||||
ref.read(secureStoreProvider),
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
|
|
@ -10,17 +10,16 @@
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/coin_entity.dart';
|
||||
import 'package:stackwallet/models/add_wallet_list_entity/sub_classes/eth_token_entity.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/verify_recovery_phrase_view.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_service_provider.dart';
|
||||
import 'package:stackwallet/services/wallets_service.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/all_wallets_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.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';
|
||||
|
@ -54,8 +53,6 @@ class SelectWalletForTokenView extends ConsumerStatefulWidget {
|
|||
class _SelectWalletForTokenViewState
|
||||
extends ConsumerState<SelectWalletForTokenView> {
|
||||
final isDesktop = Util.isDesktop;
|
||||
late final List<String> ethWalletIds;
|
||||
bool _hasEthWallets = false;
|
||||
|
||||
String? _selectedWalletId;
|
||||
|
||||
|
@ -77,49 +74,23 @@ class _SelectWalletForTokenViewState
|
|||
);
|
||||
}
|
||||
|
||||
late int _cachedWalletCount;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final ethWalletInfos = ref
|
||||
.watch(pAllWalletsInfo)
|
||||
.where((e) => e.coin == widget.entity.coin)
|
||||
.toList();
|
||||
|
||||
void _updateWalletsList(Map<String, WalletInfo> walletsData) {
|
||||
_cachedWalletCount = walletsData.length;
|
||||
final _hasEthWallets = ethWalletInfos.isNotEmpty;
|
||||
|
||||
walletsData.removeWhere((key, value) => value.coin != widget.entity.coin);
|
||||
ethWalletIds.clear();
|
||||
final List<String> ethWalletIds = [];
|
||||
|
||||
_hasEthWallets = walletsData.isNotEmpty;
|
||||
|
||||
// TODO: proper wallet data class instead of this Hive silliness
|
||||
for (final walletId in walletsData.values.map((e) => e.walletId).toList()) {
|
||||
final walletContracts = DB.instance.get<dynamic>(
|
||||
boxName: walletId,
|
||||
key: DBKeys.ethTokenContracts,
|
||||
) as List<String>? ??
|
||||
[];
|
||||
for (final walletId in ethWalletInfos.map((e) => e.walletId).toList()) {
|
||||
final walletContracts = ref.read(pWalletTokenAddresses(walletId));
|
||||
if (!walletContracts.contains(widget.entity.token.address)) {
|
||||
ethWalletIds.add(walletId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
ethWalletIds = [];
|
||||
|
||||
final walletsData =
|
||||
ref.read(walletsServiceChangeNotifierProvider).fetchWalletsData();
|
||||
_updateWalletsList(walletsData);
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// dumb hack
|
||||
ref.watch(newEthWalletTriggerTempUntilHiveCompletelyDeleted);
|
||||
final walletsData =
|
||||
ref.read(walletsServiceChangeNotifierProvider).fetchWalletsData();
|
||||
if (walletsData.length != _cachedWalletCount) {
|
||||
_updateWalletsList(walletsData);
|
||||
}
|
||||
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
|
|
|
@ -24,14 +24,17 @@ import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/v
|
|||
import 'package:stackwallet/pages/home_view/home_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/services/coins/manager.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';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||
|
@ -42,13 +45,13 @@ final createSpecialEthWalletRoutingFlag = StateProvider((ref) => false);
|
|||
class VerifyRecoveryPhraseView extends ConsumerStatefulWidget {
|
||||
const VerifyRecoveryPhraseView({
|
||||
Key? key,
|
||||
required this.manager,
|
||||
required this.wallet,
|
||||
required this.mnemonic,
|
||||
}) : super(key: key);
|
||||
|
||||
static const routeName = "/verifyRecoveryPhrase";
|
||||
|
||||
final Manager manager;
|
||||
final Wallet wallet;
|
||||
final List<String> mnemonic;
|
||||
|
||||
@override
|
||||
|
@ -60,13 +63,13 @@ class _VerifyRecoveryPhraseViewState
|
|||
extends ConsumerState<VerifyRecoveryPhraseView>
|
||||
// with WidgetsBindingObserver
|
||||
{
|
||||
late Manager _manager;
|
||||
late Wallet _wallet;
|
||||
late List<String> _mnemonic;
|
||||
late final bool isDesktop;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_manager = widget.manager;
|
||||
_wallet = widget.wallet;
|
||||
_mnemonic = widget.mnemonic;
|
||||
isDesktop = Util.isDesktop;
|
||||
// WidgetsBinding.instance?.addObserver(this);
|
||||
|
@ -119,13 +122,11 @@ class _VerifyRecoveryPhraseViewState
|
|||
}
|
||||
}
|
||||
|
||||
await ref.read(walletsServiceChangeNotifierProvider).setMnemonicVerified(
|
||||
walletId: _manager.walletId,
|
||||
await ref.read(pWalletInfo(_wallet.walletId)).setMnemonicVerified(
|
||||
isar: ref.read(mainDBProvider).isar,
|
||||
);
|
||||
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider.notifier)
|
||||
.addWallet(walletId: _manager.walletId, manager: _manager);
|
||||
ref.read(pWallets).addWallet(_wallet);
|
||||
|
||||
final isCreateSpecialEthWallet =
|
||||
ref.read(createSpecialEthWalletRoutingFlag);
|
||||
|
@ -153,11 +154,11 @@ class _VerifyRecoveryPhraseViewState
|
|||
DesktopHomeView.routeName,
|
||||
),
|
||||
);
|
||||
if (widget.manager.coin == Coin.ethereum) {
|
||||
if (widget.wallet.info.coin == Coin.ethereum) {
|
||||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
EditWalletTokensView.routeName,
|
||||
arguments: widget.manager.walletId,
|
||||
arguments: widget.wallet.walletId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -176,11 +177,11 @@ class _VerifyRecoveryPhraseViewState
|
|||
(route) => false,
|
||||
),
|
||||
);
|
||||
if (widget.manager.coin == Coin.ethereum) {
|
||||
if (widget.wallet.info.coin == Coin.ethereum) {
|
||||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
EditWalletTokensView.routeName,
|
||||
arguments: widget.manager.walletId,
|
||||
arguments: widget.wallet.walletId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -260,10 +261,10 @@ class _VerifyRecoveryPhraseViewState
|
|||
}
|
||||
|
||||
Future<void> delete() async {
|
||||
await ref
|
||||
.read(walletsServiceChangeNotifierProvider)
|
||||
.deleteWallet(_manager.walletName, false);
|
||||
await _manager.exitCurrentWallet();
|
||||
await ref.read(pWallets).deleteWallet(
|
||||
_wallet.info,
|
||||
ref.read(secureStoreProvider),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -79,14 +79,14 @@ class _AddressBookViewState extends ConsumerState<AddressBookView> {
|
|||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
List<ContactAddressEntry> addresses = [];
|
||||
final managers = ref.read(walletsChangeNotifierProvider).managers;
|
||||
for (final manager in managers) {
|
||||
final wallets = ref.read(pWallets).wallets;
|
||||
for (final wallet in wallets) {
|
||||
addresses.add(
|
||||
ContactAddressEntry()
|
||||
..coinName = manager.coin.name
|
||||
..address = await manager.currentReceivingAddress
|
||||
..coinName = wallet.info.coin.name
|
||||
..address = (await wallet.getCurrentReceivingAddress())!.value
|
||||
..label = "Current Receiving"
|
||||
..other = manager.walletName,
|
||||
..other = wallet.info.name,
|
||||
);
|
||||
}
|
||||
final self = ContactEntry(
|
||||
|
|
|
@ -15,16 +15,14 @@ import 'package:flutter/services.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/add_new_contact_address_view.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
|
||||
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
|
@ -63,29 +61,33 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
|
|||
|
||||
List<Tuple2<String, Transaction>> _cachedTransactions = [];
|
||||
|
||||
Future<List<Tuple2<String, Transaction>>> _filteredTransactionsByContact(
|
||||
List<Manager> managers,
|
||||
) async {
|
||||
Future<List<Tuple2<String, Transaction>>>
|
||||
_filteredTransactionsByContact() async {
|
||||
final contact =
|
||||
ref.read(addressBookServiceProvider).getContactById(_contactId);
|
||||
|
||||
// TODO: optimise
|
||||
|
||||
List<Tuple2<String, Transaction>> result = [];
|
||||
for (final manager in managers) {
|
||||
final transactions = await MainDB.instance
|
||||
.getTransactions(manager.walletId)
|
||||
final transactions = await ref
|
||||
.read(mainDBProvider)
|
||||
.isar
|
||||
.transactions
|
||||
.where()
|
||||
.filter()
|
||||
.anyOf(contact.addresses.map((e) => e.address),
|
||||
(q, String e) => q.address((q) => q.valueEqualTo(e)))
|
||||
.sortByTimestampDesc()
|
||||
.findAll();
|
||||
|
||||
List<Tuple2<String, Transaction>> result = [];
|
||||
|
||||
for (final tx in transactions) {
|
||||
result.add(Tuple2(manager.walletId, tx));
|
||||
}
|
||||
result.add(Tuple2(tx.walletId, tx));
|
||||
}
|
||||
|
||||
// sort by date
|
||||
result.sort((a, b) => b.item2.timestamp - a.item2.timestamp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -461,8 +463,7 @@ class _ContactDetailsViewState extends ConsumerState<ContactDetailsView> {
|
|||
height: 12,
|
||||
),
|
||||
FutureBuilder(
|
||||
future: _filteredTransactionsByContact(
|
||||
ref.watch(walletsChangeNotifierProvider).managers),
|
||||
future: _filteredTransactionsByContact(),
|
||||
builder: (_,
|
||||
AsyncSnapshot<List<Tuple2<String, Transaction>>>
|
||||
snapshot) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import 'package:stackwallet/notifications/show_flush_bar.dart';
|
|||
import 'package:stackwallet/pages/address_book_views/subviews/contact_details_view.dart';
|
||||
import 'package:stackwallet/pages/exchange_view/exchange_step_views/step_2_view.dart';
|
||||
import 'package:stackwallet/pages/send_view/send_view.dart';
|
||||
import 'package:stackwallet/providers/global/active_wallet_provider.dart';
|
||||
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
|
@ -28,6 +29,7 @@ import 'package:stackwallet/utilities/assets.dart';
|
|||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
@ -51,21 +53,15 @@ class ContactPopUp extends ConsumerWidget {
|
|||
final contact = ref.watch(addressBookServiceProvider
|
||||
.select((value) => value.getContactById(contactId)));
|
||||
|
||||
final active = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.managers
|
||||
.where((e) => e.isActiveWallet)
|
||||
.toList(growable: false);
|
||||
final active = ref.read(currentWalletIdProvider);
|
||||
|
||||
assert(active.isEmpty || active.length == 1);
|
||||
|
||||
bool hasActiveWallet = active.length == 1;
|
||||
bool hasActiveWallet = active != null;
|
||||
bool isExchangeFlow =
|
||||
ref.watch(exchangeFlowIsActiveStateProvider.state).state;
|
||||
|
||||
final addresses = contact.addressesSorted.where((e) {
|
||||
if (hasActiveWallet && !isExchangeFlow) {
|
||||
return e.coin == active[0].coin;
|
||||
return e.coin == ref.watch(pWalletCoin(active));
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
@ -201,7 +197,7 @@ class ContactPopUp extends ConsumerWidget {
|
|||
child: RoundedWhiteContainer(
|
||||
child: Center(
|
||||
child: Text(
|
||||
"No ${active[0].coin.prettyName} addresses found",
|
||||
"No ${ref.watch(pWalletCoin(active!)).prettyName} addresses found",
|
||||
style:
|
||||
STextStyles.itemSubtitle(context),
|
||||
),
|
||||
|
@ -372,8 +368,9 @@ class ContactPopUp extends ConsumerWidget {
|
|||
.pushNamed(
|
||||
SendView.routeName,
|
||||
arguments: Tuple3(
|
||||
active[0].walletId,
|
||||
active[0].coin,
|
||||
active,
|
||||
ref.read(
|
||||
pWalletCoin(active)),
|
||||
SendViewAutoFillData(
|
||||
address: address,
|
||||
contactLabel:
|
||||
|
|
|
@ -1160,15 +1160,14 @@ class _BuyFormState extends ConsumerState<BuyForm> {
|
|||
)
|
||||
.then((value) async {
|
||||
if (value is String) {
|
||||
final manager = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(value);
|
||||
final wallet = ref.read(pWallets).getWallet(value);
|
||||
|
||||
// _toController.text = manager.walletName;
|
||||
// model.recipientAddress =
|
||||
// await manager.currentReceivingAddress;
|
||||
_receiveAddressController.text =
|
||||
await manager.currentReceivingAddress;
|
||||
(await wallet.getCurrentReceivingAddress())!
|
||||
.value;
|
||||
|
||||
setState(() {
|
||||
_addressToggleFlag =
|
||||
|
|
|
@ -20,11 +20,13 @@ import 'package:stackwallet/pages/cashfusion/fusion_rounds_selection_sheet.dart'
|
|||
import 'package:stackwallet/providers/cash_fusion/fusion_progress_ui_state_provider.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/fusion_wallet_interface.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';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||
|
@ -54,6 +56,7 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
late final FocusNode portFocusNode;
|
||||
late final TextEditingController fusionRoundController;
|
||||
late final FocusNode fusionRoundFocusNode;
|
||||
late final Coin coin;
|
||||
|
||||
bool _enableSSLCheckbox = false;
|
||||
bool _enableStartButton = false;
|
||||
|
@ -61,11 +64,8 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
FusionOption _option = FusionOption.continuous;
|
||||
|
||||
Future<void> _startFusion() async {
|
||||
final wallet = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet;
|
||||
final fusionWallet = wallet as FusionWalletInterface;
|
||||
final fusionWallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as CashFusionInterface;
|
||||
|
||||
try {
|
||||
fusionWallet.uiState = ref.read(
|
||||
|
@ -90,9 +90,7 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
);
|
||||
|
||||
// update user prefs (persistent)
|
||||
ref
|
||||
.read(prefsChangeNotifierProvider)
|
||||
.setFusionServerInfo(wallet.coin, newInfo);
|
||||
ref.read(prefsChangeNotifierProvider).setFusionServerInfo(coin, newInfo);
|
||||
|
||||
unawaited(
|
||||
fusionWallet.fuse(
|
||||
|
@ -116,11 +114,11 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
portFocusNode = FocusNode();
|
||||
fusionRoundFocusNode = FocusNode();
|
||||
|
||||
final info = ref.read(prefsChangeNotifierProvider).getFusionServerInfo(ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet
|
||||
.coin);
|
||||
coin = ref.read(pWalletCoin(widget.walletId));
|
||||
|
||||
final info =
|
||||
ref.read(prefsChangeNotifierProvider).getFusionServerInfo(coin);
|
||||
|
||||
serverController.text = info.host;
|
||||
portController.text = info.port.toString();
|
||||
_enableSSLCheckbox = info.ssl;
|
||||
|
@ -221,11 +219,7 @@ class _CashFusionViewState extends ConsumerState<CashFusionView> {
|
|||
CustomTextButton(
|
||||
text: "Default",
|
||||
onTap: () {
|
||||
final def = kFusionServerInfoDefaults[ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet
|
||||
.coin]!;
|
||||
final def = kFusionServerInfoDefaults[coin]!;
|
||||
serverController.text = def.host;
|
||||
portController.text = def.port.toString();
|
||||
fusionRoundController.text =
|
||||
|
|
|
@ -16,12 +16,13 @@ import 'package:stackwallet/pages_desktop_specific/cashfusion/sub_widgets/fusion
|
|||
import 'package:stackwallet/providers/cash_fusion/fusion_progress_ui_state_provider.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/fusion_wallet_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.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/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
|
@ -38,7 +39,6 @@ class FusionProgressView extends ConsumerStatefulWidget {
|
|||
static const routeName = "/cashFusionProgressView";
|
||||
|
||||
final String walletId;
|
||||
|
||||
@override
|
||||
ConsumerState<FusionProgressView> createState() => _FusionProgressViewState();
|
||||
}
|
||||
|
@ -70,10 +70,8 @@ class _FusionProgressViewState extends ConsumerState<FusionProgressView> {
|
|||
);
|
||||
|
||||
if (shouldCancel == true && mounted) {
|
||||
final fusionWallet = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as FusionWalletInterface;
|
||||
final fusionWallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as CashFusionInterface;
|
||||
|
||||
await showLoading(
|
||||
whileFuture: Future.wait([
|
||||
|
@ -93,11 +91,7 @@ class _FusionProgressViewState extends ConsumerState<FusionProgressView> {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
coin = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet
|
||||
.coin;
|
||||
coin = ref.read(pWalletCoin(widget.walletId));
|
||||
super.initState();
|
||||
}
|
||||
|
||||
|
@ -238,10 +232,8 @@ class _FusionProgressViewState extends ConsumerState<FusionProgressView> {
|
|||
|
||||
/// Fuse again.
|
||||
void _fuseAgain() async {
|
||||
final fusionWallet = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as FusionWalletInterface;
|
||||
final fusionWallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as CashFusionInterface;
|
||||
|
||||
final fusionInfo =
|
||||
ref.read(prefsChangeNotifierProvider).getFusionServerInfo(coin);
|
||||
|
|
|
@ -19,7 +19,6 @@ import 'package:stackwallet/models/isar/models/isar_models.dart';
|
|||
import 'package:stackwallet/pages/coin_control/utxo_card.dart';
|
||||
import 'package:stackwallet/pages/coin_control/utxo_details_view.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/coin_control_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||
|
@ -27,6 +26,8 @@ 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';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart';
|
||||
import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart';
|
||||
import 'package:stackwallet/widgets/app_bar_field.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
|
@ -82,11 +83,9 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
|
|||
final Set<UTXO> _selectedBlocked = {};
|
||||
|
||||
Future<void> _refreshBalance() async {
|
||||
final coinControlInterface = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as CoinControlInterface;
|
||||
await coinControlInterface.refreshBalance(notify: true);
|
||||
final coinControlInterface =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as CoinControlInterface;
|
||||
await coinControlInterface.updateBalance();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -113,25 +112,14 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
|
|||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
|
||||
final coin = ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value
|
||||
.getManager(
|
||||
widget.walletId,
|
||||
)
|
||||
.coin,
|
||||
),
|
||||
);
|
||||
final minConfirms = ref
|
||||
.watch(pWallets)
|
||||
.getWallet(widget.walletId)
|
||||
.cryptoCurrency
|
||||
.minConfirms;
|
||||
|
||||
final currentChainHeight = ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value
|
||||
.getManager(
|
||||
widget.walletId,
|
||||
)
|
||||
.currentHeight,
|
||||
),
|
||||
);
|
||||
final coin = ref.watch(pWalletCoin(widget.walletId));
|
||||
final currentHeight = ref.watch(pWalletChainHeight(widget.walletId));
|
||||
|
||||
if (_sort == CCSortDescriptor.address && !_isSearching) {
|
||||
_list = null;
|
||||
|
@ -357,8 +345,8 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
|
|||
(widget.type == CoinControlViewType.use &&
|
||||
!utxo.isBlocked &&
|
||||
utxo.isConfirmed(
|
||||
currentChainHeight,
|
||||
coin.requiredConfirmations,
|
||||
currentHeight,
|
||||
minConfirms,
|
||||
)),
|
||||
initialSelectedState: isSelected,
|
||||
onSelectedChanged: (value) {
|
||||
|
@ -420,8 +408,8 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
|
|||
CoinControlViewType.use &&
|
||||
!_showBlocked &&
|
||||
utxo.isConfirmed(
|
||||
currentChainHeight,
|
||||
coin.requiredConfirmations,
|
||||
currentHeight,
|
||||
minConfirms,
|
||||
)),
|
||||
initialSelectedState: isSelected,
|
||||
onSelectedChanged: (value) {
|
||||
|
@ -562,8 +550,8 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
|
|||
.use &&
|
||||
!utxo.isBlocked &&
|
||||
utxo.isConfirmed(
|
||||
currentChainHeight,
|
||||
coin.requiredConfirmations,
|
||||
currentHeight,
|
||||
minConfirms,
|
||||
)),
|
||||
initialSelectedState: isSelected,
|
||||
onSelectedChanged: (value) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
|||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/utxo_status_icon.dart';
|
||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||
|
@ -64,11 +65,8 @@ class _UtxoCardState extends ConsumerState<UtxoCard> {
|
|||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
|
||||
final coin = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).coin));
|
||||
|
||||
final currentChainHeight = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).currentHeight));
|
||||
final coin = ref.watch(pWalletCoin(widget.walletId));
|
||||
final currentHeight = ref.watch(pWalletChainHeight(widget.walletId));
|
||||
|
||||
return ConditionalParent(
|
||||
condition: widget.onPressed != null,
|
||||
|
@ -113,8 +111,12 @@ class _UtxoCardState extends ConsumerState<UtxoCard> {
|
|||
child: UTXOStatusIcon(
|
||||
blocked: utxo.isBlocked,
|
||||
status: utxo.isConfirmed(
|
||||
currentChainHeight,
|
||||
coin.requiredConfirmations,
|
||||
currentHeight,
|
||||
ref
|
||||
.watch(pWallets)
|
||||
.getWallet(widget.walletId)
|
||||
.cryptoCurrency
|
||||
.minConfirms,
|
||||
)
|
||||
? UTXOStatusIconStatus.confirmed
|
||||
: UTXOStatusIconStatus.unconfirmed,
|
||||
|
|
|
@ -23,6 +23,7 @@ import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
|||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.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';
|
||||
|
@ -91,21 +92,12 @@ class _UtxoDetailsViewState extends ConsumerState<UtxoDetailsView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final coin = ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value.getManager(widget.walletId).coin,
|
||||
),
|
||||
);
|
||||
|
||||
final currentHeight = ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value.getManager(widget.walletId).currentHeight,
|
||||
),
|
||||
);
|
||||
final coin = ref.watch(pWalletCoin(widget.walletId));
|
||||
final currentHeight = ref.watch(pWalletChainHeight(widget.walletId));
|
||||
|
||||
final confirmed = utxo!.isConfirmed(
|
||||
currentHeight,
|
||||
coin.requiredConfirmations,
|
||||
ref.watch(pWallets).getWallet(widget.walletId).cryptoCurrency.minConfirms,
|
||||
);
|
||||
|
||||
return ConditionalParent(
|
||||
|
|
|
@ -15,6 +15,7 @@ import 'package:stackwallet/themes/stack_colors.dart';
|
|||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
@ -47,8 +48,12 @@ class _ChooseFromStackViewState extends ConsumerState<ChooseFromStackView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final walletIds = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getWalletIdsFor(coin: coin)));
|
||||
final walletIds = ref
|
||||
.watch(pWallets)
|
||||
.wallets
|
||||
.where((e) => e.info.coin == coin)
|
||||
.map((e) => e.walletId)
|
||||
.toList();
|
||||
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
|
@ -78,8 +83,7 @@ class _ChooseFromStackViewState extends ConsumerState<ChooseFromStackView> {
|
|||
: ListView.builder(
|
||||
itemCount: walletIds.length,
|
||||
itemBuilder: (context, index) {
|
||||
final manager = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(walletIds[index])));
|
||||
final walletId = walletIds[index];
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5.0),
|
||||
|
@ -98,7 +102,7 @@ class _ChooseFromStackViewState extends ConsumerState<ChooseFromStackView> {
|
|||
elevation: 0,
|
||||
onPressed: () async {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop(manager.walletId);
|
||||
Navigator.of(context).pop(walletId);
|
||||
}
|
||||
},
|
||||
child: RoundedWhiteContainer(
|
||||
|
@ -115,7 +119,7 @@ class _ChooseFromStackViewState extends ConsumerState<ChooseFromStackView> {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
manager.walletName,
|
||||
ref.watch(pWalletName(walletId)),
|
||||
style: STextStyles.titleBold12(context),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
|
|
|
@ -13,14 +13,15 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/models/trade_wallet_lookup.dart';
|
||||
import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
|
||||
import 'package:stackwallet/pages/send_view/sub_widgets/sending_transaction_dialog.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||
|
@ -29,6 +30,9 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
|||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/models/tx_data.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.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';
|
||||
|
@ -44,7 +48,7 @@ import 'package:uuid/uuid.dart';
|
|||
class ConfirmChangeNowSendView extends ConsumerStatefulWidget {
|
||||
const ConfirmChangeNowSendView({
|
||||
Key? key,
|
||||
required this.transactionInfo,
|
||||
required this.txData,
|
||||
required this.walletId,
|
||||
this.routeOnSuccessName = WalletView.routeName,
|
||||
required this.trade,
|
||||
|
@ -54,7 +58,7 @@ class ConfirmChangeNowSendView extends ConsumerStatefulWidget {
|
|||
|
||||
static const String routeName = "/confirmChangeNowSend";
|
||||
|
||||
final Map<String, dynamic> transactionInfo;
|
||||
final TxData txData;
|
||||
final String walletId;
|
||||
final String routeOnSuccessName;
|
||||
final Trade trade;
|
||||
|
@ -68,7 +72,6 @@ class ConfirmChangeNowSendView extends ConsumerStatefulWidget {
|
|||
|
||||
class _ConfirmChangeNowSendViewState
|
||||
extends ConsumerState<ConfirmChangeNowSendView> {
|
||||
late final Map<String, dynamic> transactionInfo;
|
||||
late final String walletId;
|
||||
late final String routeOnSuccessName;
|
||||
late final Trade trade;
|
||||
|
@ -76,8 +79,8 @@ class _ConfirmChangeNowSendViewState
|
|||
final isDesktop = Util.isDesktop;
|
||||
|
||||
Future<void> _attemptSend(BuildContext context) async {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
final coin = wallet.info.coin;
|
||||
|
||||
final sendProgressController = ProgressAndSuccessController();
|
||||
|
||||
|
@ -88,7 +91,7 @@ class _ConfirmChangeNowSendViewState
|
|||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return SendingTransactionDialog(
|
||||
coin: manager.coin,
|
||||
coin: coin,
|
||||
controller: sendProgressController,
|
||||
);
|
||||
},
|
||||
|
@ -102,19 +105,18 @@ class _ConfirmChangeNowSendViewState
|
|||
);
|
||||
|
||||
late String txid;
|
||||
Future<String> txidFuture;
|
||||
Future<TxData> txidFuture;
|
||||
|
||||
final String note = transactionInfo["note"] as String? ?? "";
|
||||
final String note = widget.txData.note ?? "";
|
||||
|
||||
try {
|
||||
if (widget.shouldSendPublicFiroFunds == true) {
|
||||
txidFuture = (manager.wallet as FiroWallet)
|
||||
.confirmSendPublic(txData: transactionInfo);
|
||||
if (wallet is FiroWallet && widget.shouldSendPublicFiroFunds == false) {
|
||||
txidFuture = wallet.confirmSendLelantus(txData: widget.txData);
|
||||
} else {
|
||||
txidFuture = manager.confirmSend(txData: transactionInfo);
|
||||
txidFuture = wallet.confirmSend(txData: widget.txData);
|
||||
}
|
||||
|
||||
unawaited(manager.refresh());
|
||||
unawaited(wallet.refresh());
|
||||
|
||||
final results = await Future.wait([
|
||||
txidFuture,
|
||||
|
@ -124,12 +126,16 @@ class _ConfirmChangeNowSendViewState
|
|||
sendProgressController.triggerSuccess?.call();
|
||||
await Future<void>.delayed(const Duration(seconds: 5));
|
||||
|
||||
txid = results.first as String;
|
||||
txid = (results.first as TxData).txid!;
|
||||
|
||||
// save note
|
||||
await ref
|
||||
.read(notesServiceChangeNotifierProvider(walletId))
|
||||
.editOrAddNote(txid: txid, note: note);
|
||||
await ref.read(mainDBProvider).putTransactionNote(
|
||||
TransactionNote(
|
||||
walletId: walletId,
|
||||
txid: txid,
|
||||
value: note,
|
||||
),
|
||||
);
|
||||
|
||||
await ref.read(tradeSentFromStackLookupProvider).save(
|
||||
tradeWalletLookup: TradeWalletLookup(
|
||||
|
@ -199,8 +205,7 @@ class _ConfirmChangeNowSendViewState
|
|||
Future<void> _confirmSend() async {
|
||||
final dynamic unlocked;
|
||||
|
||||
final coin =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId).coin;
|
||||
final coin = ref.read(pWalletCoin(walletId));
|
||||
|
||||
if (Util.isDesktop) {
|
||||
unlocked = await showDialog<bool?>(
|
||||
|
@ -257,7 +262,6 @@ class _ConfirmChangeNowSendViewState
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
transactionInfo = widget.transactionInfo;
|
||||
walletId = widget.walletId;
|
||||
routeOnSuccessName = widget.routeOnSuccessName;
|
||||
trade = widget.trade;
|
||||
|
@ -266,9 +270,6 @@ class _ConfirmChangeNowSendViewState
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final managerProvider = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManagerProvider(walletId)));
|
||||
|
||||
return ConditionalParent(
|
||||
condition: !isDesktop,
|
||||
builder: (child) {
|
||||
|
@ -340,7 +341,7 @@ class _ConfirmChangeNowSendViewState
|
|||
width: 12,
|
||||
),
|
||||
Text(
|
||||
"Confirm ${ref.watch(managerProvider.select((value) => value.coin)).ticker} transaction",
|
||||
"Confirm ${ref.watch(pWalletCoin(walletId)).ticker} transaction",
|
||||
style: STextStyles.desktopH3(context),
|
||||
)
|
||||
],
|
||||
|
@ -384,18 +385,9 @@ class _ConfirmChangeNowSendViewState
|
|||
children: [
|
||||
Text(
|
||||
ref
|
||||
.watch(pAmountFormatter(ref.watch(
|
||||
managerProvider.select((value) => value.coin),
|
||||
)))
|
||||
.format(transactionInfo["fee"] is Amount
|
||||
? transactionInfo["fee"] as Amount
|
||||
: (transactionInfo["fee"] as int)
|
||||
.toAmountAsRaw(
|
||||
fractionDigits: ref.watch(
|
||||
managerProvider.select(
|
||||
(value) => value.coin.decimals),
|
||||
),
|
||||
)),
|
||||
.watch(pAmountFormatter(
|
||||
ref.watch(pWalletCoin(walletId))))
|
||||
.format(widget.txData.fee!),
|
||||
style:
|
||||
STextStyles.desktopTextExtraExtraSmall(context)
|
||||
.copyWith(
|
||||
|
@ -427,17 +419,9 @@ class _ConfirmChangeNowSendViewState
|
|||
),
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final coin = ref.watch(
|
||||
managerProvider.select((value) => value.coin),
|
||||
);
|
||||
final fee = transactionInfo["fee"] is Amount
|
||||
? transactionInfo["fee"] as Amount
|
||||
: (transactionInfo["fee"] as int)
|
||||
.toAmountAsRaw(
|
||||
fractionDigits: coin.decimals,
|
||||
);
|
||||
final amount =
|
||||
transactionInfo["recipientAmt"] as Amount;
|
||||
final coin = ref.read(pWalletCoin(walletId));
|
||||
final fee = widget.txData.fee!;
|
||||
final amount = widget.txData.amountWithoutChange!;
|
||||
final total = amount + fee;
|
||||
|
||||
return Text(
|
||||
|
@ -509,7 +493,7 @@ class _ConfirmChangeNowSendViewState
|
|||
),
|
||||
),
|
||||
child: Text(
|
||||
"Send ${ref.watch(managerProvider.select((value) => value.coin)).ticker}",
|
||||
"Send ${ref.watch(pWalletCoin(walletId)).ticker}",
|
||||
style: isDesktop
|
||||
? STextStyles.desktopTextMedium(context)
|
||||
: STextStyles.pageTitleH1(context),
|
||||
|
@ -536,10 +520,7 @@ class _ConfirmChangeNowSendViewState
|
|||
height: 4,
|
||||
),
|
||||
Text(
|
||||
ref
|
||||
.watch(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.walletName,
|
||||
ref.watch(pWalletName(walletId)),
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
],
|
||||
|
@ -566,7 +547,7 @@ class _ConfirmChangeNowSendViewState
|
|||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"${transactionInfo["address"] ?? "ERROR"}",
|
||||
widget.txData.recipients!.first.address,
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
],
|
||||
|
@ -595,15 +576,14 @@ class _ConfirmChangeNowSendViewState
|
|||
children: [
|
||||
child,
|
||||
Builder(builder: (context) {
|
||||
final coin = ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value.getManager(walletId).coin));
|
||||
final coin = ref.watch(pWalletCoin(walletId));
|
||||
final price = ref.watch(
|
||||
priceAnd24hChangeNotifierProvider
|
||||
.select((value) => value.getPrice(coin)));
|
||||
final amount =
|
||||
transactionInfo["recipientAmt"] as Amount;
|
||||
final value = (price.item1 * amount.decimal)
|
||||
final amountWithoutChange =
|
||||
widget.txData.amountWithoutChange!;
|
||||
final value =
|
||||
(price.item1 * amountWithoutChange.decimal)
|
||||
.toAmount(fractionDigits: 2);
|
||||
final currency = ref.watch(prefsChangeNotifierProvider
|
||||
.select((value) => value.currency));
|
||||
|
@ -628,10 +608,9 @@ class _ConfirmChangeNowSendViewState
|
|||
),
|
||||
child: Text(
|
||||
ref
|
||||
.watch(pAmountFormatter(ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value.getManager(walletId).coin))))
|
||||
.format((transactionInfo["recipientAmt"] as Amount)),
|
||||
.watch(pAmountFormatter(
|
||||
ref.watch(pWalletCoin(walletId))))
|
||||
.format((widget.txData.amountWithoutChange!)),
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
|
@ -658,18 +637,10 @@ class _ConfirmChangeNowSendViewState
|
|||
),
|
||||
Text(
|
||||
ref
|
||||
.watch(pAmountFormatter(ref.watch(
|
||||
managerProvider.select((value) => value.coin),
|
||||
)))
|
||||
.watch(
|
||||
pAmountFormatter(ref.read(pWalletCoin(walletId))))
|
||||
.format(
|
||||
(transactionInfo["fee"] is Amount
|
||||
? transactionInfo["fee"] as Amount
|
||||
: (transactionInfo["fee"] as int).toAmountAsRaw(
|
||||
fractionDigits: ref.watch(
|
||||
managerProvider.select(
|
||||
(value) => value.coin.decimals,
|
||||
),
|
||||
))),
|
||||
widget.txData.fee!,
|
||||
),
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
textAlign: TextAlign.right,
|
||||
|
@ -698,7 +669,7 @@ class _ConfirmChangeNowSendViewState
|
|||
height: 4,
|
||||
),
|
||||
Text(
|
||||
transactionInfo["note"] as String? ?? "",
|
||||
widget.txData.note ?? "",
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
],
|
||||
|
@ -751,16 +722,9 @@ class _ConfirmChangeNowSendViewState
|
|||
),
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final coin = ref.watch(
|
||||
managerProvider.select((value) => value.coin),
|
||||
);
|
||||
final fee = transactionInfo["fee"] is Amount
|
||||
? transactionInfo["fee"] as Amount
|
||||
: (transactionInfo["fee"] as int).toAmountAsRaw(
|
||||
fractionDigits: coin.decimals,
|
||||
);
|
||||
final amount =
|
||||
transactionInfo["recipientAmt"] as Amount;
|
||||
final coin = ref.watch(pWalletCoin(walletId));
|
||||
final fee = widget.txData.fee!;
|
||||
final amount = widget.txData.amountWithoutChange!;
|
||||
final total = amount + fee;
|
||||
|
||||
return Text(
|
||||
|
|
|
@ -96,22 +96,22 @@ class _Step2ViewState extends ConsumerState<Step2View> {
|
|||
if (model.receiveTicker.toLowerCase() ==
|
||||
tuple.item2.ticker.toLowerCase()) {
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(tuple.item1)
|
||||
.currentReceivingAddress
|
||||
.read(pWallets)
|
||||
.getWallet(tuple.item1)
|
||||
.getCurrentReceivingAddress()
|
||||
.then((value) {
|
||||
_toController.text = value;
|
||||
_toController.text = value!.value;
|
||||
model.recipientAddress = _toController.text;
|
||||
});
|
||||
} else {
|
||||
if (model.sendTicker.toUpperCase() ==
|
||||
tuple.item2.ticker.toUpperCase()) {
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(tuple.item1)
|
||||
.currentReceivingAddress
|
||||
.read(pWallets)
|
||||
.getWallet(tuple.item1)
|
||||
.getCurrentReceivingAddress()
|
||||
.then((value) {
|
||||
_refundController.text = value;
|
||||
_refundController.text = value!.value;
|
||||
model.refundAddress = _refundController.text;
|
||||
});
|
||||
}
|
||||
|
@ -218,15 +218,14 @@ class _Step2ViewState extends ConsumerState<Step2View> {
|
|||
)
|
||||
.then((value) async {
|
||||
if (value is String) {
|
||||
final manager = ref
|
||||
.read(
|
||||
walletsChangeNotifierProvider)
|
||||
.getManager(value);
|
||||
final wallet = ref
|
||||
.read(pWallets)
|
||||
.getWallet(value);
|
||||
|
||||
_toController.text =
|
||||
manager.walletName;
|
||||
model.recipientAddress = await manager
|
||||
.currentReceivingAddress;
|
||||
_toController.text = wallet.info.name;
|
||||
model.recipientAddress = (await wallet
|
||||
.getCurrentReceivingAddress())!
|
||||
.value;
|
||||
|
||||
setState(() {
|
||||
enableNext =
|
||||
|
@ -490,15 +489,15 @@ class _Step2ViewState extends ConsumerState<Step2View> {
|
|||
)
|
||||
.then((value) async {
|
||||
if (value is String) {
|
||||
final manager = ref
|
||||
.read(
|
||||
walletsChangeNotifierProvider)
|
||||
.getManager(value);
|
||||
final wallet = ref
|
||||
.read(pWallets)
|
||||
.getWallet(value);
|
||||
|
||||
_refundController.text =
|
||||
manager.walletName;
|
||||
model.refundAddress = await manager
|
||||
.currentReceivingAddress;
|
||||
wallet.info.name;
|
||||
model.refundAddress = (await wallet
|
||||
.getCurrentReceivingAddress())!
|
||||
.value;
|
||||
}
|
||||
setState(() {
|
||||
enableNext =
|
||||
|
|
|
@ -25,7 +25,6 @@ import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dia
|
|||
import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||
|
@ -35,6 +34,9 @@ import 'package:stackwallet/utilities/constants.dart';
|
|||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/models/tx_data.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||
|
@ -71,9 +73,9 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
try {
|
||||
final coin = coinFromTickerCaseInsensitive(ticker);
|
||||
return ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.managers
|
||||
.where((element) => element.coin == coin)
|
||||
.read(pWallets)
|
||||
.wallets
|
||||
.where((e) => e.info.coin == coin)
|
||||
.isNotEmpty;
|
||||
} catch (_) {
|
||||
return false;
|
||||
|
@ -134,11 +136,9 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
}
|
||||
|
||||
Future<bool?> _showSendFromFiroBalanceSelectSheet(String walletId) async {
|
||||
final firoWallet = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.wallet as FiroWallet;
|
||||
final locale = ref.read(localeServiceChangeNotifierProvider).locale;
|
||||
final coin = ref.read(pWalletCoin(walletId));
|
||||
final balancePublic = ref.read(pWalletBalance(walletId));
|
||||
final balancePrivate = ref.read(pWalletBalanceSecondary(walletId));
|
||||
|
||||
return await showModalBottomSheet<bool?>(
|
||||
context: context,
|
||||
|
@ -172,7 +172,7 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
),
|
||||
SecondaryButton(
|
||||
label:
|
||||
"${ref.watch(pAmountFormatter(firoWallet.coin)).format(firoWallet.balancePrivate.spendable)} (private)",
|
||||
"${ref.watch(pAmountFormatter(coin)).format(balancePrivate.spendable)} (private)",
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
),
|
||||
const SizedBox(
|
||||
|
@ -180,7 +180,7 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
),
|
||||
SecondaryButton(
|
||||
label:
|
||||
"${ref.watch(pAmountFormatter(firoWallet.coin)).format(firoWallet.balance.spendable)} (public)",
|
||||
"${ref.watch(pAmountFormatter(coin)).format(balancePublic.spendable)} (public)",
|
||||
onPressed: () => Navigator.of(context).pop(true),
|
||||
),
|
||||
const SizedBox(
|
||||
|
@ -206,11 +206,10 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
firoPublicSend = false;
|
||||
}
|
||||
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(tuple.item1);
|
||||
final wallet = ref.read(pWallets).getWallet(tuple.item1);
|
||||
|
||||
final Amount amount = model.sendAmount.toAmount(
|
||||
fractionDigits: manager.coin.decimals,
|
||||
fractionDigits: wallet.info.coin.decimals,
|
||||
);
|
||||
final address = model.trade!.payInAddress;
|
||||
|
||||
|
@ -225,7 +224,7 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return BuildingTransactionDialog(
|
||||
coin: manager.coin,
|
||||
coin: wallet.info.coin,
|
||||
onCancel: () {
|
||||
wasCancelled = true;
|
||||
},
|
||||
|
@ -240,32 +239,45 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
),
|
||||
);
|
||||
|
||||
Future<Map<String, dynamic>> txDataFuture;
|
||||
Future<TxData> txDataFuture;
|
||||
|
||||
if (firoPublicSend) {
|
||||
txDataFuture = (manager.wallet as FiroWallet).prepareSendPublic(
|
||||
// TODO: [prio=high] Firo spark
|
||||
|
||||
if (wallet is FiroWallet && !firoPublicSend) {
|
||||
txDataFuture = wallet.prepareSendLelantus(
|
||||
txData: TxData(
|
||||
recipients: [
|
||||
(
|
||||
address: address,
|
||||
amount: amount,
|
||||
args: {
|
||||
"feeRate": FeeRateType.average,
|
||||
// ref.read(feeRateTypeStateProvider)
|
||||
},
|
||||
isChange: false,
|
||||
)
|
||||
],
|
||||
note: "${model.trade!.payInCurrency.toUpperCase()}/"
|
||||
"${model.trade!.payOutCurrency.toUpperCase()} exchange",
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final memo =
|
||||
manager.coin == Coin.stellar || manager.coin == Coin.stellarTestnet
|
||||
final memo = wallet.info.coin == Coin.stellar ||
|
||||
wallet.info.coin == Coin.stellarTestnet
|
||||
? model.trade!.payInExtraId.isNotEmpty
|
||||
? model.trade!.payInExtraId
|
||||
: null
|
||||
: null;
|
||||
txDataFuture = manager.prepareSend(
|
||||
txDataFuture = wallet.prepareSend(
|
||||
txData: TxData(
|
||||
recipients: [
|
||||
(
|
||||
address: address,
|
||||
amount: amount,
|
||||
args: {
|
||||
"memo": memo,
|
||||
"feeRate": FeeRateType.average,
|
||||
// ref.read(feeRateTypeStateProvider)
|
||||
},
|
||||
isChange: false,
|
||||
),
|
||||
],
|
||||
memo: memo,
|
||||
feeRateType: FeeRateType.average,
|
||||
note: "${model.trade!.payInCurrency.toUpperCase()}/"
|
||||
"${model.trade!.payOutCurrency.toUpperCase()} exchange",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -274,7 +286,7 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
time,
|
||||
]);
|
||||
|
||||
final txData = results.first as Map<String, dynamic>;
|
||||
final txData = results.first as TxData;
|
||||
|
||||
if (!wasCancelled) {
|
||||
// pop building dialog
|
||||
|
@ -283,17 +295,13 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
txData["note"] =
|
||||
"${model.trade!.payInCurrency.toUpperCase()}/${model.trade!.payOutCurrency.toUpperCase()} exchange";
|
||||
txData["address"] = address;
|
||||
|
||||
if (mounted) {
|
||||
unawaited(
|
||||
Navigator.of(context).push(
|
||||
RouteGenerator.getRoute(
|
||||
shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute,
|
||||
builder: (_) => ConfirmChangeNowSendView(
|
||||
transactionInfo: txData,
|
||||
txData: txData,
|
||||
walletId: tuple.item1,
|
||||
routeOnSuccessName: HomeView.routeName,
|
||||
trade: model.trade!,
|
||||
|
@ -815,9 +823,10 @@ class _Step4ViewState extends ConsumerState<Step4View> {
|
|||
model.sendTicker.toLowerCase() ==
|
||||
tuple.item2.ticker.toLowerCase()) {
|
||||
final walletName = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(tuple.item1)
|
||||
.walletName;
|
||||
.read(pWallets)
|
||||
.getWallet(tuple.item1)
|
||||
.info
|
||||
.name;
|
||||
buttonTitle = "Send from $walletName";
|
||||
}
|
||||
|
||||
|
|
|
@ -195,9 +195,9 @@ class _ExchangeViewState extends ConsumerState<ExchangeView> {
|
|||
if (txid != null &&
|
||||
walletIds != null &&
|
||||
walletIds.isNotEmpty) {
|
||||
final manager = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletIds.first);
|
||||
final wallet = ref
|
||||
.read(pWallets)
|
||||
.getWallet(walletIds.first);
|
||||
|
||||
//todo: check if print needed
|
||||
// debugPrint("name: ${manager.walletName}");
|
||||
|
@ -212,7 +212,7 @@ class _ExchangeViewState extends ConsumerState<ExchangeView> {
|
|||
unawaited(Navigator.of(context).pushNamed(
|
||||
TradeDetailsView.routeName,
|
||||
arguments: Tuple4(tradeId, tx,
|
||||
walletIds.first, manager.walletName),
|
||||
walletIds.first, wallet.info.name),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -21,8 +21,6 @@ import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dia
|
|||
import 'package:stackwallet/pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
|
@ -33,6 +31,9 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
|||
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/models/tx_data.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.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';
|
||||
|
@ -85,8 +86,12 @@ class _SendFromViewState extends ConsumerState<SendFromView> {
|
|||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
|
||||
final walletIds = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getWalletIdsFor(coin: coin)));
|
||||
final walletIds = ref
|
||||
.watch(pWallets)
|
||||
.wallets
|
||||
.where((e) => e.info.coin == coin)
|
||||
.map((e) => e.walletId)
|
||||
.toList();
|
||||
|
||||
final isDesktop = Util.isDesktop;
|
||||
|
||||
|
@ -224,7 +229,9 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
late final String address;
|
||||
late final Trade trade;
|
||||
|
||||
Future<void> _send(Manager manager, {bool? shouldSendPublicFiroFunds}) async {
|
||||
Future<void> _send({bool? shouldSendPublicFiroFunds}) async {
|
||||
final coin = ref.read(pWalletCoin(walletId));
|
||||
|
||||
try {
|
||||
bool wasCancelled = false;
|
||||
|
||||
|
@ -245,7 +252,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
),
|
||||
),
|
||||
child: BuildingTransactionDialog(
|
||||
coin: manager.coin,
|
||||
coin: coin,
|
||||
onCancel: () {
|
||||
wasCancelled = true;
|
||||
|
||||
|
@ -263,46 +270,56 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> txData;
|
||||
Future<Map<String, dynamic>> txDataFuture;
|
||||
TxData txData;
|
||||
Future<TxData> txDataFuture;
|
||||
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
|
||||
// if not firo then do normal send
|
||||
if (shouldSendPublicFiroFunds == null) {
|
||||
final memo =
|
||||
manager.coin == Coin.stellar || manager.coin == Coin.stellarTestnet
|
||||
final memo = coin == Coin.stellar || coin == Coin.stellarTestnet
|
||||
? trade.payInExtraId.isNotEmpty
|
||||
? trade.payInExtraId
|
||||
: null
|
||||
: null;
|
||||
txDataFuture = manager.prepareSend(
|
||||
txDataFuture = wallet.prepareSend(
|
||||
txData: TxData(
|
||||
recipients: [
|
||||
(
|
||||
address: address,
|
||||
amount: amount,
|
||||
args: {
|
||||
"memo": memo,
|
||||
"feeRate": FeeRateType.average,
|
||||
// ref.read(feeRateTypeStateProvider)
|
||||
},
|
||||
amount: amount, isChange: false,
|
||||
),
|
||||
],
|
||||
memo: memo,
|
||||
feeRateType: FeeRateType.average,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
final firoWallet = manager.wallet as FiroWallet;
|
||||
final firoWallet = wallet as FiroWallet;
|
||||
// otherwise do firo send based on balance selected
|
||||
if (shouldSendPublicFiroFunds) {
|
||||
txDataFuture = firoWallet.prepareSendPublic(
|
||||
txDataFuture = wallet.prepareSend(
|
||||
txData: TxData(
|
||||
recipients: [
|
||||
(
|
||||
address: address,
|
||||
amount: amount,
|
||||
args: {
|
||||
"feeRate": FeeRateType.average,
|
||||
// ref.read(feeRateTypeStateProvider)
|
||||
},
|
||||
amount: amount, isChange: false,
|
||||
),
|
||||
],
|
||||
feeRateType: FeeRateType.average,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
txDataFuture = firoWallet.prepareSend(
|
||||
txDataFuture = firoWallet.prepareSendLelantus(
|
||||
txData: TxData(
|
||||
recipients: [
|
||||
(
|
||||
address: address,
|
||||
amount: amount,
|
||||
args: {
|
||||
"feeRate": FeeRateType.average,
|
||||
// ref.read(feeRateTypeStateProvider)
|
||||
},
|
||||
amount: amount, isChange: false,
|
||||
),
|
||||
],
|
||||
// feeRateType: FeeRateType.average,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -312,7 +329,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
time,
|
||||
]);
|
||||
|
||||
txData = results.first as Map<String, dynamic>;
|
||||
txData = results.first as TxData;
|
||||
|
||||
if (!wasCancelled) {
|
||||
// pop building dialog
|
||||
|
@ -324,16 +341,17 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
).pop();
|
||||
}
|
||||
|
||||
txData["note"] =
|
||||
"${trade.payInCurrency.toUpperCase()}/${trade.payOutCurrency.toUpperCase()} exchange";
|
||||
txData["address"] = address;
|
||||
txData = txData.copyWith(
|
||||
note: "${trade.payInCurrency.toUpperCase()}/"
|
||||
"${trade.payOutCurrency.toUpperCase()} exchange",
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
await Navigator.of(context).push(
|
||||
RouteGenerator.getRoute(
|
||||
shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute,
|
||||
builder: (_) => ConfirmChangeNowSendView(
|
||||
transactionInfo: txData,
|
||||
txData: txData,
|
||||
walletId: walletId,
|
||||
routeOnSuccessName: Util.isDesktop
|
||||
? DesktopExchangeView.routeName
|
||||
|
@ -396,14 +414,12 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final manager = ref.watch(ref
|
||||
.watch(walletsChangeNotifierProvider.notifier)
|
||||
.getManagerProvider(walletId));
|
||||
final wallet = ref.watch(pWallets).getWallet(walletId);
|
||||
|
||||
final locale = ref.watch(
|
||||
localeServiceChangeNotifierProvider.select((value) => value.locale));
|
||||
|
||||
final coin = manager.coin;
|
||||
final coin = ref.watch(pWalletCoin(walletId));
|
||||
|
||||
final isFiro = coin == Coin.firoTestNet || coin == Coin.firo;
|
||||
|
||||
|
@ -438,7 +454,6 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
if (mounted) {
|
||||
unawaited(
|
||||
_send(
|
||||
manager,
|
||||
shouldSendPublicFiroFunds: false,
|
||||
),
|
||||
);
|
||||
|
@ -465,10 +480,9 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
Text(
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
(manager.wallet as FiroWallet)
|
||||
.availablePrivateBalance(),
|
||||
),
|
||||
ref.watch(pAmountFormatter(coin)).format(ref
|
||||
.watch(pWalletBalance(walletId))
|
||||
.spendable),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
],
|
||||
|
@ -501,7 +515,6 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
if (mounted) {
|
||||
unawaited(
|
||||
_send(
|
||||
manager,
|
||||
shouldSendPublicFiroFunds: true,
|
||||
),
|
||||
);
|
||||
|
@ -529,8 +542,11 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
),
|
||||
Text(
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
(manager.wallet as FiroWallet)
|
||||
.availablePublicBalance()),
|
||||
ref
|
||||
.watch(
|
||||
pWalletBalanceSecondary(walletId))
|
||||
.spendable,
|
||||
),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
],
|
||||
|
@ -569,7 +585,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
onPressed: () async {
|
||||
if (mounted) {
|
||||
unawaited(
|
||||
_send(manager),
|
||||
_send(),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
@ -581,7 +597,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.colorForCoin(manager.coin)
|
||||
.colorForCoin(coin)
|
||||
.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
|
@ -609,7 +625,7 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
manager.walletName,
|
||||
ref.watch(pWalletName(walletId)),
|
||||
style: STextStyles.titleBold12(context),
|
||||
),
|
||||
if (!isFiro)
|
||||
|
@ -618,9 +634,8 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
),
|
||||
if (!isFiro)
|
||||
Text(
|
||||
ref
|
||||
.watch(pAmountFormatter(coin))
|
||||
.format(manager.balance.spendable),
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
ref.watch(pWalletBalance(walletId)).spendable),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -84,8 +84,6 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
late final Transaction? transactionIfSentFromStack;
|
||||
late final String? walletId;
|
||||
|
||||
String _note = "";
|
||||
|
||||
bool isStackCoin(String ticker) {
|
||||
try {
|
||||
try {
|
||||
|
@ -960,7 +958,9 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
maxHeight: 360,
|
||||
child: EditTradeNoteView(
|
||||
tradeId: tradeId,
|
||||
note: _note,
|
||||
note: ref
|
||||
.read(tradeNoteServiceProvider)
|
||||
.getNote(tradeId: tradeId),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -1046,7 +1046,6 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
txid:
|
||||
transactionIfSentFromStack!.txid,
|
||||
walletId: walletId!,
|
||||
note: _note,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -1057,10 +1056,9 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
onTap: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
EditNoteView.routeName,
|
||||
arguments: Tuple3(
|
||||
arguments: Tuple2(
|
||||
transactionIfSentFromStack!.txid,
|
||||
walletId!,
|
||||
_note,
|
||||
walletId,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -1089,22 +1087,19 @@ class _TradeDetailsViewState extends ConsumerState<TradeDetailsView> {
|
|||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
FutureBuilder(
|
||||
future: ref.watch(
|
||||
notesServiceChangeNotifierProvider(walletId!).select(
|
||||
(value) => value.getNoteFor(
|
||||
txid: transactionIfSentFromStack!.txid))),
|
||||
builder:
|
||||
(builderContext, AsyncSnapshot<String> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasData) {
|
||||
_note = snapshot.data ?? "";
|
||||
}
|
||||
return SelectableText(
|
||||
_note,
|
||||
SelectableText(
|
||||
ref
|
||||
.watch(
|
||||
pTransactionNote(
|
||||
(
|
||||
txid: transactionIfSentFromStack!.txid,
|
||||
walletId: walletId!,
|
||||
),
|
||||
),
|
||||
)
|
||||
?.value ??
|
||||
"",
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -33,7 +33,6 @@ import 'package:stackwallet/utilities/text_styles.dart';
|
|||
import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/onetime_popups/tor_has_been_add_dialog.dart';
|
||||
import 'package:stackwallet/widgets/small_tor_icon.dart';
|
||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||
|
||||
|
@ -130,9 +129,9 @@ class _HomeViewState extends ConsumerState<HomeView> {
|
|||
|
||||
ref.read(notificationsProvider).startCheckingWatchedNotifications();
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
showOneTimeTorHasBeenAddedDialogIfRequired(context);
|
||||
});
|
||||
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
// showOneTimeTorHasBeenAddedDialogIfRequired(context);
|
||||
// });
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
|
|
@ -10,11 +10,12 @@
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/favourite_wallets_provider.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
|
||||
|
@ -61,8 +62,8 @@ class ManageFavoritesView extends StatelessWidget {
|
|||
body: isDesktop
|
||||
? Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final favorites = ref.watch(favoritesProvider);
|
||||
final nonFavorites = ref.watch(nonFavoritesProvider);
|
||||
final favorites = ref.watch(pFavouriteWalletInfos(true));
|
||||
final nonFavorites = ref.watch(pFavouriteWalletInfos(false));
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
|
@ -108,8 +109,7 @@ class ManageFavoritesView extends StatelessWidget {
|
|||
key: key,
|
||||
itemCount: favorites.length,
|
||||
itemBuilder: (builderContext, index) {
|
||||
final walletId =
|
||||
ref.read(favorites[index]).walletId;
|
||||
final walletId = favorites[index].walletId;
|
||||
return Padding(
|
||||
key: Key(
|
||||
"manageFavoriteWalletsItem_$walletId",
|
||||
|
@ -127,14 +127,43 @@ class ManageFavoritesView extends StatelessWidget {
|
|||
);
|
||||
},
|
||||
onReorder: (oldIndex, newIndex) {
|
||||
ref
|
||||
.read(walletsServiceChangeNotifierProvider)
|
||||
.moveFavorite(
|
||||
fromIndex: oldIndex, toIndex: newIndex);
|
||||
final isar = ref.read(mainDBProvider).isar;
|
||||
|
||||
ref
|
||||
.read(favoritesProvider)
|
||||
.reorder(oldIndex, newIndex, true);
|
||||
final actualIndex =
|
||||
favorites[oldIndex].favouriteOrderIndex;
|
||||
if (oldIndex > newIndex) {
|
||||
for (int i = oldIndex - 1; i >= newIndex; i--) {
|
||||
final next = favorites[i];
|
||||
next.updateIsFavourite(
|
||||
true,
|
||||
isar: isar,
|
||||
customIndexOverride:
|
||||
next.favouriteOrderIndex + 1,
|
||||
);
|
||||
}
|
||||
favorites[oldIndex].updateIsFavourite(
|
||||
true,
|
||||
isar: isar,
|
||||
customIndexOverride:
|
||||
actualIndex - (oldIndex - newIndex),
|
||||
);
|
||||
} else {
|
||||
for (int i = oldIndex + 1; i < newIndex; i++) {
|
||||
final next = favorites[i];
|
||||
next.updateIsFavourite(
|
||||
true,
|
||||
isar: isar,
|
||||
customIndexOverride:
|
||||
next.favouriteOrderIndex - 1,
|
||||
);
|
||||
}
|
||||
favorites[oldIndex].updateIsFavourite(
|
||||
true,
|
||||
isar: isar,
|
||||
customIndexOverride:
|
||||
actualIndex + (newIndex - oldIndex),
|
||||
);
|
||||
}
|
||||
},
|
||||
proxyDecorator: (child, index, animation) {
|
||||
return Material(
|
||||
|
@ -176,8 +205,7 @@ class ManageFavoritesView extends StatelessWidget {
|
|||
itemBuilder: (buildContext, index) {
|
||||
// final walletId = ref.watch(
|
||||
// nonFavorites[index].select((value) => value.walletId));
|
||||
final walletId =
|
||||
ref.read(nonFavorites[index]).walletId;
|
||||
final walletId = nonFavorites[index].walletId;
|
||||
return Padding(
|
||||
key: Key(
|
||||
"manageNonFavoriteWalletsItem_$walletId",
|
||||
|
@ -236,13 +264,13 @@ class ManageFavoritesView extends StatelessWidget {
|
|||
Expanded(
|
||||
child: Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final favorites = ref.watch(favoritesProvider);
|
||||
final favorites =
|
||||
ref.watch(pFavouriteWalletInfos(true));
|
||||
return ReorderableListView.builder(
|
||||
key: key,
|
||||
itemCount: favorites.length,
|
||||
itemBuilder: (builderContext, index) {
|
||||
final walletId =
|
||||
ref.read(favorites[index]).walletId;
|
||||
final walletId = favorites[index].walletId;
|
||||
return Padding(
|
||||
key: Key(
|
||||
"manageFavoriteWalletsItem_$walletId",
|
||||
|
@ -254,14 +282,43 @@ class ManageFavoritesView extends StatelessWidget {
|
|||
);
|
||||
},
|
||||
onReorder: (oldIndex, newIndex) {
|
||||
ref
|
||||
.read(walletsServiceChangeNotifierProvider)
|
||||
.moveFavorite(
|
||||
fromIndex: oldIndex, toIndex: newIndex);
|
||||
final isar = ref.read(mainDBProvider).isar;
|
||||
|
||||
ref
|
||||
.read(favoritesProvider)
|
||||
.reorder(oldIndex, newIndex, true);
|
||||
final actualIndex =
|
||||
favorites[oldIndex].favouriteOrderIndex;
|
||||
if (oldIndex > newIndex) {
|
||||
for (int i = oldIndex - 1; i >= newIndex; i--) {
|
||||
final next = favorites[i];
|
||||
next.updateIsFavourite(
|
||||
true,
|
||||
isar: isar,
|
||||
customIndexOverride:
|
||||
next.favouriteOrderIndex + 1,
|
||||
);
|
||||
}
|
||||
favorites[oldIndex].updateIsFavourite(
|
||||
true,
|
||||
isar: isar,
|
||||
customIndexOverride:
|
||||
actualIndex - (oldIndex - newIndex),
|
||||
);
|
||||
} else {
|
||||
for (int i = oldIndex + 1; i < newIndex; i++) {
|
||||
final next = favorites[i];
|
||||
next.updateIsFavourite(
|
||||
true,
|
||||
isar: isar,
|
||||
customIndexOverride:
|
||||
next.favouriteOrderIndex - 1,
|
||||
);
|
||||
}
|
||||
favorites[oldIndex].updateIsFavourite(
|
||||
true,
|
||||
isar: isar,
|
||||
customIndexOverride:
|
||||
actualIndex + (newIndex - oldIndex),
|
||||
);
|
||||
}
|
||||
},
|
||||
proxyDecorator: (child, index, animation) {
|
||||
return Material(
|
||||
|
@ -301,15 +358,15 @@ class ManageFavoritesView extends StatelessWidget {
|
|||
Expanded(
|
||||
child: Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final nonFavorites = ref.watch(nonFavoritesProvider);
|
||||
final nonFavorites =
|
||||
ref.watch(pFavouriteWalletInfos(false));
|
||||
|
||||
return ListView.builder(
|
||||
itemCount: nonFavorites.length,
|
||||
itemBuilder: (buildContext, index) {
|
||||
// final walletId = ref.watch(
|
||||
// nonFavorites[index].select((value) => value.walletId));
|
||||
final walletId =
|
||||
ref.read(nonFavorites[index]).walletId;
|
||||
final walletId = nonFavorites[index].walletId;
|
||||
return Padding(
|
||||
key: Key(
|
||||
"manageNonFavoriteWalletsItem_$walletId",
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
|
||||
// import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
// import 'package:stackwallet/services/coins/banano/banano_wallet.dart';
|
||||
// import 'package:stackwallet/services/coins/manager.dart';
|
||||
//
|
||||
// import 'package:stackwallet/themes/stack_colors.dart';
|
||||
// import 'package:stackwallet/utilities/assets.dart';
|
||||
// import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -146,7 +146,7 @@
|
|||
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
// final address = await ref
|
||||
// .read(walletsChangeNotifierProvider)
|
||||
// .getManager(walletId)
|
||||
// .getWallet(walletId)
|
||||
// .currentReceivingAddress;
|
||||
// setState(() {
|
||||
// receivingAddress = address;
|
||||
|
@ -164,8 +164,8 @@
|
|||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// final Coin coin = ref.watch(managerProvider.select((value) => value.coin));
|
||||
// final manager = ref.watch(walletsChangeNotifierProvider
|
||||
// .select((value) => value.getManager(widget.walletId)));
|
||||
// final wallet = ref.watch(walletsChangeNotifierProvider
|
||||
// .select((value) => value.getWallet(widget.walletId)));
|
||||
//
|
||||
// List<int>? imageBytes;
|
||||
// imageBytes = (manager.wallet as BananoWallet).getMonkeyImageBytes();
|
||||
|
|
|
@ -8,15 +8,15 @@ import 'package:path_provider/path_provider.dart';
|
|||
import 'package:permission_handler/permission_handler.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/monkey_service.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.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/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/banano_wallet.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';
|
||||
|
@ -48,9 +48,7 @@ class _MonkeyViewState extends ConsumerState<MonkeyView> {
|
|||
List<int>? imageBytes;
|
||||
|
||||
Future<void> _updateWalletMonKey(Uint8List monKeyBytes) async {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||
await (manager.wallet as BananoWallet)
|
||||
await (ref.read(pWallets).getWallet(walletId) as BananoWallet)
|
||||
.updateMonkeyImageBytes(monKeyBytes.toList());
|
||||
}
|
||||
|
||||
|
@ -83,9 +81,9 @@ class _MonkeyViewState extends ConsumerState<MonkeyView> {
|
|||
}
|
||||
|
||||
final address = await ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.currentReceivingAddress;
|
||||
.read(pWallets)
|
||||
.getWallet(walletId)
|
||||
.getCurrentReceivingAddress();
|
||||
final docPath = dir.path;
|
||||
String filePath = "$docPath/monkey_$address";
|
||||
|
||||
|
@ -110,13 +108,12 @@ class _MonkeyViewState extends ConsumerState<MonkeyView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final manager = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId)));
|
||||
final Coin coin = manager.coin;
|
||||
final wallet = ref.watch(pWallets).getWallet(widget.walletId);
|
||||
final coin = ref.watch(pWalletCoin(widget.walletId));
|
||||
|
||||
final bool isDesktop = Util.isDesktop;
|
||||
|
||||
imageBytes ??= (manager.wallet as BananoWallet).getMonkeyImageBytes();
|
||||
imageBytes ??= (wallet as BananoWallet).getMonkeyImageBytes();
|
||||
|
||||
return Background(
|
||||
child: ConditionalParent(
|
||||
|
@ -344,7 +341,7 @@ class _MonkeyViewState extends ConsumerState<MonkeyView> {
|
|||
whileFuture: Future.wait([
|
||||
_saveMonKeyToFile(
|
||||
bytes: Uint8List.fromList(
|
||||
(manager.wallet as BananoWallet)
|
||||
(wallet as BananoWallet)
|
||||
.getMonkeyImageBytes()!),
|
||||
),
|
||||
Future<void>.delayed(
|
||||
|
@ -386,11 +383,11 @@ class _MonkeyViewState extends ConsumerState<MonkeyView> {
|
|||
bool didError = false;
|
||||
await showLoading(
|
||||
whileFuture: Future.wait([
|
||||
manager.currentReceivingAddress.then(
|
||||
wallet.getCurrentReceivingAddress().then(
|
||||
(address) async => await ref
|
||||
.read(pMonKeyService)
|
||||
.fetchMonKey(
|
||||
address: address,
|
||||
address: address!.value,
|
||||
png: true,
|
||||
)
|
||||
.then(
|
||||
|
@ -489,10 +486,10 @@ class _MonkeyViewState extends ConsumerState<MonkeyView> {
|
|||
onPressed: () async {
|
||||
await showLoading(
|
||||
whileFuture: Future.wait([
|
||||
manager.currentReceivingAddress.then(
|
||||
wallet.getCurrentReceivingAddress().then(
|
||||
(address) async => await ref
|
||||
.read(pMonKeyService)
|
||||
.fetchMonKey(address: address)
|
||||
.fetchMonKey(address: address!.value)
|
||||
.then(
|
||||
(monKeyBytes) async =>
|
||||
await _updateWalletMonKey(
|
||||
|
@ -520,8 +517,8 @@ class _MonkeyViewState extends ConsumerState<MonkeyView> {
|
|||
},
|
||||
);
|
||||
|
||||
imageBytes = (manager.wallet as BananoWallet)
|
||||
.getMonkeyImageBytes();
|
||||
imageBytes =
|
||||
(wallet as BananoWallet).getMonkeyImageBytes();
|
||||
|
||||
if (imageBytes != null) {
|
||||
setState(() {});
|
||||
|
|
|
@ -13,7 +13,6 @@ import 'package:stackwallet/networking/http.dart';
|
|||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/tor_service.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
|
@ -23,6 +22,7 @@ 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/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||
|
@ -57,8 +57,7 @@ class _OrdinalDetailsViewState extends ConsumerState<OrdinalDetailsView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final coin = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).coin));
|
||||
final coin = ref.watch(pWalletCoin(widget.walletId));
|
||||
|
||||
return Background(
|
||||
child: SafeArea(
|
||||
|
|
|
@ -13,11 +13,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/pages/ordinals/widgets/ordinals_list.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/ordinals_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/show_loading.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
|
||||
|
@ -89,10 +89,8 @@ class _OrdinalsViewState extends ConsumerState<OrdinalsView> {
|
|||
await showLoading(
|
||||
whileFuture: Future.wait<void>([
|
||||
Future.delayed(const Duration(seconds: 2)),
|
||||
(ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as OrdinalsInterface)
|
||||
(ref.read(pWallets).getWallet(widget.walletId)
|
||||
as OrdinalsInterface)
|
||||
.refreshInscriptions()
|
||||
]),
|
||||
context: context,
|
||||
|
|
|
@ -26,12 +26,13 @@ import 'package:stackwallet/pages/send_view/send_view.dart';
|
|||
import 'package:stackwallet/providers/global/locale_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/models/tx_data.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/paynym_follow_toggle_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
|
@ -59,13 +60,12 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
|
|||
bool _showInsufficientFundsInfo = false;
|
||||
|
||||
Future<void> _onSend() async {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
|
||||
final wallet = ref.read(pWallets).getWallet(widget.walletId);
|
||||
await Navigator.of(context).pushNamed(
|
||||
SendView.routeName,
|
||||
arguments: Tuple3(
|
||||
manager.walletId,
|
||||
manager.coin,
|
||||
wallet.walletId,
|
||||
wallet.info.coin,
|
||||
widget.accountLite,
|
||||
),
|
||||
);
|
||||
|
@ -85,10 +85,9 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
|
|||
),
|
||||
);
|
||||
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
|
||||
|
||||
final wallet = manager.wallet as PaynymWalletInterface;
|
||||
final wallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as PaynymInterface;
|
||||
final coin = ref.read(pWalletCoin(widget.walletId));
|
||||
|
||||
if (await wallet.hasConnected(widget.accountLite.code)) {
|
||||
canPop = true;
|
||||
|
@ -97,9 +96,9 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
|
|||
return;
|
||||
}
|
||||
|
||||
final rates = await manager.fees;
|
||||
final rates = await ref.read(pWallets).getWallet(widget.walletId).fees;
|
||||
|
||||
Map<String, dynamic> preparedTx;
|
||||
TxData preparedTx;
|
||||
|
||||
try {
|
||||
preparedTx = await wallet.prepareNotificationTx(
|
||||
|
@ -148,32 +147,22 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
|
|||
nymName: widget.accountLite.nymName,
|
||||
locale: ref.read(localeServiceChangeNotifierProvider).locale,
|
||||
onConfirmPressed: () {
|
||||
//
|
||||
print("CONFIRM NOTIF TX: $preparedTx");
|
||||
|
||||
Navigator.of(context).push(
|
||||
RouteGenerator.getRoute(
|
||||
builder: (_) => ConfirmTransactionView(
|
||||
walletId: manager.walletId,
|
||||
walletId: widget.walletId,
|
||||
routeOnSuccessName: PaynymHomeView.routeName,
|
||||
isPaynymNotificationTransaction: true,
|
||||
transactionInfo: {
|
||||
"hex": preparedTx["hex"],
|
||||
"address": preparedTx["recipientPaynym"],
|
||||
"recipientAmt": preparedTx["amount"],
|
||||
"fee": preparedTx["fee"],
|
||||
"vSize": preparedTx["vSize"],
|
||||
"note": "PayNym connect"
|
||||
txData: preparedTx,
|
||||
onSuccess: () {
|
||||
// do nothing extra
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
amount: (preparedTx["amount"] as Amount) +
|
||||
(preparedTx["fee"] as int).toAmountAsRaw(
|
||||
fractionDigits: manager.coin.decimals,
|
||||
),
|
||||
coin: manager.coin,
|
||||
amount: preparedTx.amount! + preparedTx.fee!,
|
||||
coin: coin,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -181,10 +170,8 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final manager = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId)));
|
||||
|
||||
final wallet = manager.wallet as PaynymWalletInterface;
|
||||
final wallet =
|
||||
ref.watch(pWallets).getWallet(widget.walletId) as PaynymInterface;
|
||||
|
||||
return DesktopDialog(
|
||||
maxWidth: MediaQuery.of(context).size.width - 32,
|
||||
|
@ -316,7 +303,7 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
|
|||
"Adding a PayNym to your contacts requires a one-time "
|
||||
"transaction fee for creating the record on the "
|
||||
"blockchain. Please deposit more "
|
||||
"${ref.read(walletsChangeNotifierProvider).getManager(widget.walletId).wallet.coin.ticker} "
|
||||
"${ref.watch(pWalletCoin(widget.walletId)).ticker} "
|
||||
"into your wallet and try again.",
|
||||
style: STextStyles.infoSmall(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
|
|
|
@ -20,11 +20,11 @@ import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
|
|||
import 'package:stackwallet/providers/global/paynym_api_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/paynym_interface.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_app_bar.dart';
|
||||
|
@ -47,11 +47,8 @@ class PaynymClaimView extends ConsumerStatefulWidget {
|
|||
|
||||
class _PaynymClaimViewState extends ConsumerState<PaynymClaimView> {
|
||||
Future<bool> _addSegwitCode(PaynymAccount myAccount) async {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
|
||||
|
||||
// get wallet to access paynym calls
|
||||
final wallet = manager.wallet as PaynymWalletInterface;
|
||||
final wallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as PaynymInterface;
|
||||
|
||||
final token = await ref
|
||||
.read(paynymAPIProvider)
|
||||
|
@ -190,12 +187,8 @@ class _PaynymClaimViewState extends ConsumerState<PaynymClaimView> {
|
|||
).then((value) => shouldCancel = value == true),
|
||||
);
|
||||
|
||||
final manager = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId);
|
||||
|
||||
// get wallet to access paynym calls
|
||||
final wallet = manager.wallet as PaynymWalletInterface;
|
||||
final wallet = ref.read(pWallets).getWallet(widget.walletId)
|
||||
as PaynymInterface;
|
||||
|
||||
if (shouldCancel) return;
|
||||
|
||||
|
|
|
@ -24,12 +24,13 @@ import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart';
|
|||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/paynym/desktop_paynym_send_dialog.dart';
|
||||
import 'package:stackwallet/providers/global/locale_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/models/tx_data.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/paynym_follow_toggle_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||
|
@ -70,10 +71,8 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
|||
),
|
||||
);
|
||||
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
|
||||
|
||||
final wallet = manager.wallet as PaynymWalletInterface;
|
||||
final wallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as PaynymInterface;
|
||||
|
||||
if (await wallet.hasConnected(widget.accountLite.code)) {
|
||||
canPop = true;
|
||||
|
@ -82,9 +81,9 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
|||
return;
|
||||
}
|
||||
|
||||
final rates = await manager.fees;
|
||||
final rates = await ref.read(pWallets).getWallet(widget.walletId).fees;
|
||||
|
||||
Map<String, dynamic> preparedTx;
|
||||
TxData preparedTx;
|
||||
|
||||
try {
|
||||
preparedTx = await wallet.prepareNotificationTx(
|
||||
|
@ -121,18 +120,14 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
|||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => DesktopDialog(
|
||||
maxHeight: double.infinity,
|
||||
maxHeight: MediaQuery.of(context).size.height - 64,
|
||||
maxWidth: 580,
|
||||
child: ConfirmTransactionView(
|
||||
walletId: manager.walletId,
|
||||
walletId: widget.walletId,
|
||||
isPaynymNotificationTransaction: true,
|
||||
transactionInfo: {
|
||||
"hex": preparedTx["hex"],
|
||||
"address": preparedTx["recipientPaynym"],
|
||||
"recipientAmt": preparedTx["amount"],
|
||||
"fee": preparedTx["fee"],
|
||||
"vSize": preparedTx["vSize"],
|
||||
"note": "PayNym connect"
|
||||
txData: preparedTx,
|
||||
onSuccess: () {
|
||||
// do nothing extra
|
||||
},
|
||||
onSuccessInsteadOfRouteOnSuccess: () {
|
||||
Navigator.of(context, rootNavigator: true).pop();
|
||||
|
@ -152,11 +147,8 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
|||
),
|
||||
);
|
||||
},
|
||||
amount: (preparedTx["amount"] as Amount) +
|
||||
(preparedTx["fee"] as int).toAmountAsRaw(
|
||||
fractionDigits: manager.coin.decimals,
|
||||
),
|
||||
coin: manager.coin,
|
||||
amount: preparedTx.amount! + preparedTx.fee!,
|
||||
coin: ref.read(pWalletCoin(widget.walletId)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -174,10 +166,9 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final manager = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId)));
|
||||
final wallet = ref.watch(pWallets).getWallet(widget.walletId);
|
||||
|
||||
final wallet = manager.wallet as PaynymWalletInterface;
|
||||
final paynymWallet = wallet as PaynymInterface;
|
||||
|
||||
return RoundedWhiteContainer(
|
||||
padding: const EdgeInsets.all(0),
|
||||
|
@ -205,7 +196,8 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
|||
style: STextStyles.desktopTextSmall(context),
|
||||
),
|
||||
FutureBuilder(
|
||||
future: wallet.hasConnected(widget.accountLite.code),
|
||||
future: paynymWallet
|
||||
.hasConnected(widget.accountLite.code),
|
||||
builder: (context, AsyncSnapshot<bool> snapshot) {
|
||||
if (snapshot.connectionState ==
|
||||
ConnectionState.done &&
|
||||
|
@ -243,7 +235,8 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
|||
children: [
|
||||
Expanded(
|
||||
child: FutureBuilder(
|
||||
future: wallet.hasConnected(widget.accountLite.code),
|
||||
future:
|
||||
paynymWallet.hasConnected(widget.accountLite.code),
|
||||
builder: (context, AsyncSnapshot<bool> snapshot) {
|
||||
if (snapshot.connectionState ==
|
||||
ConnectionState.done &&
|
||||
|
@ -315,7 +308,7 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
|
|||
"Adding a PayNym to your contacts requires a one-time "
|
||||
"transaction fee for creating the record on the "
|
||||
"blockchain. Please deposit more "
|
||||
"${ref.read(walletsChangeNotifierProvider).getManager(widget.walletId).wallet.coin.ticker} "
|
||||
"${ref.watch(pWalletCoin(widget.walletId)).ticker} "
|
||||
"into your wallet and try again.",
|
||||
style: STextStyles.desktopTextExtraExtraSmall(context)
|
||||
.copyWith(
|
||||
|
|
|
@ -16,12 +16,12 @@ import 'package:stackwallet/pages/paynym/subwidgets/paynym_card_button.dart';
|
|||
import 'package:stackwallet/providers/global/paynym_api_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart';
|
||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
|
@ -75,12 +75,8 @@ class _PaynymFollowersListState extends ConsumerState<PaynymFollowersList> {
|
|||
child: child,
|
||||
onRefresh: () async {
|
||||
try {
|
||||
final manager = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId);
|
||||
|
||||
// get wallet to access paynym calls
|
||||
final wallet = manager.wallet as PaynymWalletInterface;
|
||||
final wallet = ref.read(pWallets).getWallet(widget.walletId)
|
||||
as PaynymInterface;
|
||||
|
||||
// get payment code
|
||||
final pCode = await wallet.getPaymentCode(
|
||||
|
|
|
@ -16,12 +16,12 @@ import 'package:stackwallet/pages/paynym/subwidgets/paynym_card_button.dart';
|
|||
import 'package:stackwallet/providers/global/paynym_api_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart';
|
||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart';
|
||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
||||
|
@ -75,12 +75,8 @@ class _PaynymFollowingListState extends ConsumerState<PaynymFollowingList> {
|
|||
child: child,
|
||||
onRefresh: () async {
|
||||
try {
|
||||
final manager = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId);
|
||||
|
||||
// get wallet to access paynym calls
|
||||
final wallet = manager.wallet as PaynymWalletInterface;
|
||||
final wallet = ref.read(pWallets).getWallet(widget.walletId)
|
||||
as PaynymInterface;
|
||||
|
||||
// get payment code
|
||||
final pCode = await wallet.getPaymentCode(
|
||||
|
|
|
@ -32,7 +32,6 @@ import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
|||
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_pin_put/custom_pin_put.dart';
|
||||
import 'package:stackwallet/widgets/shake/shake.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class LockscreenView extends ConsumerStatefulWidget {
|
||||
const LockscreenView({
|
||||
|
@ -98,14 +97,13 @@ class _LockscreenViewState extends ConsumerState<LockscreenView> {
|
|||
if (loadIntoWallet) {
|
||||
final walletId = widget.routeOnSuccessArguments as String;
|
||||
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||
if (manager.coin == Coin.monero) {
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
if (wallet.info.coin == Coin.monero) {
|
||||
await showLoading(
|
||||
opaqueBG: true,
|
||||
whileFuture: manager.initializeExisting(),
|
||||
whileFuture: wallet.init(),
|
||||
context: context,
|
||||
message: "Loading ${manager.coin.prettyName} wallet...",
|
||||
message: "Loading ${wallet.info.coin.prettyName} wallet...",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -124,12 +122,7 @@ class _LockscreenViewState extends ConsumerState<LockscreenView> {
|
|||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
WalletView.routeName,
|
||||
arguments: Tuple2(
|
||||
walletId,
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManagerProvider(walletId),
|
||||
),
|
||||
arguments: walletId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import 'package:stackwallet/utilities/address_utils.dart';
|
|||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.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';
|
||||
|
@ -95,9 +96,7 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
key: _qrKey,
|
||||
child: QrImageView(
|
||||
data: AddressUtils.buildUriString(
|
||||
ref.watch(walletsChangeNotifierProvider.select(
|
||||
(value) =>
|
||||
value.getManager(widget.walletId).coin)),
|
||||
ref.watch(pWalletCoin(widget.walletId)),
|
||||
address.value,
|
||||
{},
|
||||
),
|
||||
|
@ -151,8 +150,7 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final coin = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).coin));
|
||||
final coin = ref.watch(pWalletCoin(widget.walletId));
|
||||
return ConditionalParent(
|
||||
condition: !isDesktop,
|
||||
builder: (child) => Background(
|
||||
|
@ -266,8 +264,11 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
borderColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.backgroundAppBar,
|
||||
child: coin == Coin.bitcoincash ||
|
||||
coin == Coin.bitcoincashTestnet
|
||||
child: ref
|
||||
.watch(pWallets)
|
||||
.getWallet(widget.walletId)
|
||||
.isarTransactionVersion ==
|
||||
2
|
||||
? _AddressDetailsTxV2List(
|
||||
walletId: widget.walletId,
|
||||
address: address,
|
||||
|
@ -292,9 +293,7 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
key: _qrKey,
|
||||
child: QrImageView(
|
||||
data: AddressUtils.buildUriString(
|
||||
ref.watch(walletsChangeNotifierProvider.select(
|
||||
(value) =>
|
||||
value.getManager(widget.walletId).coin)),
|
||||
coin,
|
||||
address.value,
|
||||
{},
|
||||
),
|
||||
|
@ -357,6 +356,16 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
data: address.derivationPath!.value,
|
||||
button: Container(),
|
||||
),
|
||||
if (address.type == AddressType.spark)
|
||||
const _Div(
|
||||
height: 12,
|
||||
),
|
||||
if (address.type == AddressType.spark)
|
||||
_Item(
|
||||
title: "Diversifier",
|
||||
data: address.derivationIndex.toString(),
|
||||
button: Container(),
|
||||
),
|
||||
const _Div(
|
||||
height: 12,
|
||||
),
|
||||
|
|
|
@ -16,11 +16,11 @@ import 'package:stackwallet/db/isar/main_db.dart';
|
|||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/pages/receive_view/addresses/address_card.dart';
|
||||
import 'package:stackwallet/pages/receive_view/addresses/address_details_view.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.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';
|
||||
|
@ -135,8 +135,8 @@ class _WalletAddressesViewState extends ConsumerState<WalletAddressesView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final coin = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).coin));
|
||||
final coin = ref.watch(pWalletCoin(widget.walletId));
|
||||
|
||||
return ConditionalParent(
|
||||
condition: !isDesktop,
|
||||
builder: (child) => Background(
|
||||
|
|
|
@ -10,15 +10,18 @@
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/receive_view/addresses/wallet_addresses_view.dart';
|
||||
import 'package:stackwallet/pages/receive_view/generate_receiving_uri_qr_code_view.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
|
@ -28,7 +31,11 @@ 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/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/multi_address_interface.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/spark_interface.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/custom_buttons/blue_text_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
|
||||
|
@ -56,8 +63,16 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
|||
late final Coin coin;
|
||||
late final String walletId;
|
||||
late final ClipboardInterface clipboard;
|
||||
late final bool supportsSpark;
|
||||
|
||||
String? _sparkAddress;
|
||||
String? _qrcodeContent;
|
||||
bool _showSparkAddress = true;
|
||||
|
||||
Future<void> generateNewAddress() async {
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
|
||||
if (wallet is MultiAddressInterface) {
|
||||
bool shouldPop = false;
|
||||
unawaited(
|
||||
showDialog(
|
||||
|
@ -80,10 +95,7 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
|||
),
|
||||
);
|
||||
|
||||
await ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.generateNewAddress();
|
||||
await wallet.generateNewReceivingAddress();
|
||||
|
||||
shouldPop = true;
|
||||
|
||||
|
@ -92,45 +104,108 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
|||
.popUntil(ModalRoute.withName(ReceiveView.routeName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String receivingAddress = "";
|
||||
Future<void> generateNewSparkAddress() async {
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
if (wallet is SparkInterface) {
|
||||
bool shouldPop = false;
|
||||
unawaited(
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
return WillPopScope(
|
||||
onWillPop: () async => shouldPop,
|
||||
child: Container(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.overlay
|
||||
.withOpacity(0.5),
|
||||
child: const CustomLoadingOverlay(
|
||||
message: "Generating address",
|
||||
eventBus: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
final address = await wallet.generateNextSparkAddress();
|
||||
await ref.read(mainDBProvider).isar.writeTxn(() async {
|
||||
await ref.read(mainDBProvider).isar.addresses.put(address);
|
||||
});
|
||||
|
||||
shouldPop = true;
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context, rootNavigator: true).pop();
|
||||
if (_sparkAddress != address.value) {
|
||||
setState(() {
|
||||
_sparkAddress = address.value;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StreamSubscription<Address?>? _streamSub;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
walletId = widget.walletId;
|
||||
coin = ref.read(walletsChangeNotifierProvider).getManager(walletId).coin;
|
||||
coin = ref.read(pWalletCoin(walletId));
|
||||
clipboard = widget.clipboard;
|
||||
supportsSpark = ref.read(pWallets).getWallet(walletId) is SparkInterface;
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
final address = await ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.currentReceivingAddress;
|
||||
if (supportsSpark) {
|
||||
_streamSub = ref
|
||||
.read(mainDBProvider)
|
||||
.isar
|
||||
.addresses
|
||||
.where()
|
||||
.walletIdEqualTo(walletId)
|
||||
.filter()
|
||||
.typeEqualTo(AddressType.spark)
|
||||
.sortByDerivationIndexDesc()
|
||||
.findFirst()
|
||||
.asStream()
|
||||
.listen((event) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
receivingAddress = address;
|
||||
_sparkAddress = event?.value;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_streamSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
|
||||
ref.listen(
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManagerProvider(walletId)
|
||||
.select((value) => value.currentReceivingAddress),
|
||||
(previous, next) {
|
||||
if (next is Future<String>) {
|
||||
next.then((value) => setState(() => receivingAddress = value));
|
||||
}
|
||||
});
|
||||
|
||||
final ticker = widget.tokenContract?.symbol ?? coin.ticker;
|
||||
|
||||
if (supportsSpark) {
|
||||
if (_showSparkAddress) {
|
||||
_qrcodeContent = _sparkAddress;
|
||||
} else {
|
||||
_qrcodeContent = ref.watch(pWalletReceivingAddress(walletId));
|
||||
}
|
||||
} else {
|
||||
_qrcodeContent = ref.watch(pWalletReceivingAddress(walletId));
|
||||
}
|
||||
|
||||
return Background(
|
||||
child: Scaffold(
|
||||
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
||||
|
@ -243,11 +318,166 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
ConditionalParent(
|
||||
condition: supportsSpark,
|
||||
builder: (child) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
DropdownButtonHideUnderline(
|
||||
child: DropdownButton2<bool>(
|
||||
value: _showSparkAddress,
|
||||
items: [
|
||||
DropdownMenuItem(
|
||||
value: true,
|
||||
child: Text(
|
||||
"Spark address",
|
||||
style: STextStyles.desktopTextMedium(context),
|
||||
),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: false,
|
||||
child: Text(
|
||||
"Transparent address",
|
||||
style: STextStyles.desktopTextMedium(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
if (value is bool && value != _showSparkAddress) {
|
||||
setState(() {
|
||||
_showSparkAddress = value;
|
||||
});
|
||||
}
|
||||
},
|
||||
isExpanded: true,
|
||||
iconStyleData: IconStyleData(
|
||||
icon: Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: SvgPicture.asset(
|
||||
Assets.svg.chevronDown,
|
||||
width: 12,
|
||||
height: 6,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldActiveSearchIconRight,
|
||||
),
|
||||
),
|
||||
),
|
||||
dropdownStyleData: DropdownStyleData(
|
||||
offset: const Offset(0, -10),
|
||||
elevation: 0,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultBG,
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
),
|
||||
),
|
||||
menuItemStyleData: const MenuItemStyleData(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (_showSparkAddress)
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
clipboard.setData(
|
||||
ClipboardData(text: _sparkAddress ?? "Error"),
|
||||
);
|
||||
showFloatingFlushBar(
|
||||
type: FlushBarType.info,
|
||||
message: "Copied to clipboard",
|
||||
iconAsset: Assets.svg.copy,
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.backgroundAppBar,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
),
|
||||
),
|
||||
child: RoundedWhiteContainer(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
"Your ${coin.ticker} SPARK address",
|
||||
style:
|
||||
STextStyles.itemSubtitle(context),
|
||||
),
|
||||
const Spacer(),
|
||||
Row(
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
Assets.svg.copy,
|
||||
width: 15,
|
||||
height: 15,
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.infoItemIcons,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
Text(
|
||||
"Copy",
|
||||
style: STextStyles.link2(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
_sparkAddress ?? "Error",
|
||||
style: STextStyles
|
||||
.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!_showSparkAddress) child,
|
||||
],
|
||||
),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
HapticFeedback.lightImpact();
|
||||
clipboard.setData(
|
||||
ClipboardData(text: receivingAddress),
|
||||
ClipboardData(
|
||||
text:
|
||||
ref.watch(pWalletReceivingAddress(walletId))),
|
||||
);
|
||||
showFloatingFlushBar(
|
||||
type: FlushBarType.info,
|
||||
|
@ -294,7 +524,8 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
|||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
receivingAddress,
|
||||
ref.watch(
|
||||
pWalletReceivingAddress(walletId)),
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
),
|
||||
|
@ -304,25 +535,22 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
|||
),
|
||||
),
|
||||
),
|
||||
if (coin != Coin.epicCash &&
|
||||
coin != Coin.ethereum &&
|
||||
coin != Coin.banano &&
|
||||
coin != Coin.nano &&
|
||||
coin != Coin.stellar &&
|
||||
coin != Coin.stellarTestnet &&
|
||||
coin != Coin.tezos)
|
||||
),
|
||||
if (ref.watch(pWallets
|
||||
.select((value) => value.getWallet(walletId)))
|
||||
is MultiAddressInterface ||
|
||||
supportsSpark)
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (coin != Coin.epicCash &&
|
||||
coin != Coin.ethereum &&
|
||||
coin != Coin.banano &&
|
||||
coin != Coin.nano &&
|
||||
coin != Coin.stellar &&
|
||||
coin != Coin.stellarTestnet &&
|
||||
coin != Coin.tezos)
|
||||
if (ref.watch(pWallets
|
||||
.select((value) => value.getWallet(walletId)))
|
||||
is MultiAddressInterface ||
|
||||
supportsSpark)
|
||||
TextButton(
|
||||
onPressed: generateNewAddress,
|
||||
onPressed: supportsSpark && _showSparkAddress
|
||||
? generateNewSparkAddress
|
||||
: generateNewAddress,
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.getSecondaryEnabledButtonStyle(context),
|
||||
|
@ -346,7 +574,7 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
|||
QrImageView(
|
||||
data: AddressUtils.buildUriString(
|
||||
coin,
|
||||
receivingAddress,
|
||||
_qrcodeContent ?? "",
|
||||
{},
|
||||
),
|
||||
size: MediaQuery.of(context).size.width / 2,
|
||||
|
@ -365,7 +593,7 @@ class _ReceiveViewState extends ConsumerState<ReceiveView> {
|
|||
RouteGenerator.useMaterialPageRoute,
|
||||
builder: (_) => GenerateUriQrCodeView(
|
||||
coin: coin,
|
||||
receivingAddress: receivingAddress,
|
||||
receivingAddress: _qrcodeContent ?? "",
|
||||
),
|
||||
settings: const RouteSettings(
|
||||
name: GenerateUriQrCodeView.routeName,
|
||||
|
|
|
@ -13,22 +13,20 @@ import 'dart:io';
|
|||
|
||||
import 'package:decimal/decimal.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_libepiccash/lib.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
|
||||
import 'package:stackwallet/models/isar/models/transaction_note.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
|
||||
import 'package:stackwallet/pages/send_view/sub_widgets/sending_transaction_dialog.dart';
|
||||
import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/theme_providers.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
|
@ -37,6 +35,11 @@ import 'package:stackwallet/utilities/constants.dart';
|
|||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/models/tx_data.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/paynym_interface.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';
|
||||
|
@ -53,8 +56,9 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart';
|
|||
class ConfirmTransactionView extends ConsumerStatefulWidget {
|
||||
const ConfirmTransactionView({
|
||||
Key? key,
|
||||
required this.transactionInfo,
|
||||
required this.txData,
|
||||
required this.walletId,
|
||||
required this.onSuccess,
|
||||
this.routeOnSuccessName = WalletView.routeName,
|
||||
this.isTradeTransaction = false,
|
||||
this.isPaynymTransaction = false,
|
||||
|
@ -65,7 +69,7 @@ class ConfirmTransactionView extends ConsumerStatefulWidget {
|
|||
|
||||
static const String routeName = "/confirmTransactionView";
|
||||
|
||||
final Map<String, dynamic> transactionInfo;
|
||||
final TxData txData;
|
||||
final String walletId;
|
||||
final String routeOnSuccessName;
|
||||
final bool isTradeTransaction;
|
||||
|
@ -73,6 +77,7 @@ class ConfirmTransactionView extends ConsumerStatefulWidget {
|
|||
final bool isPaynymNotificationTransaction;
|
||||
final bool isTokenTx;
|
||||
final VoidCallback? onSuccessInsteadOfRouteOnSuccess;
|
||||
final VoidCallback onSuccess;
|
||||
|
||||
@override
|
||||
ConsumerState<ConfirmTransactionView> createState() =>
|
||||
|
@ -81,7 +86,6 @@ class ConfirmTransactionView extends ConsumerStatefulWidget {
|
|||
|
||||
class _ConfirmTransactionViewState
|
||||
extends ConsumerState<ConfirmTransactionView> {
|
||||
late final Map<String, dynamic> transactionInfo;
|
||||
late final String walletId;
|
||||
late final String routeOnSuccessName;
|
||||
late final bool isDesktop;
|
||||
|
@ -89,14 +93,12 @@ class _ConfirmTransactionViewState
|
|||
late final FocusNode _noteFocusNode;
|
||||
late final TextEditingController noteController;
|
||||
|
||||
|
||||
late final FocusNode _onChainNoteFocusNode;
|
||||
late final TextEditingController onChainNoteController;
|
||||
|
||||
|
||||
Future<void> _attemptSend(BuildContext context) async {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
final coin = wallet.info.coin;
|
||||
|
||||
final sendProgressController = ProgressAndSuccessController();
|
||||
|
||||
|
@ -107,7 +109,7 @@ class _ConfirmTransactionViewState
|
|||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return SendingTransactionDialog(
|
||||
coin: manager.coin,
|
||||
coin: coin,
|
||||
controller: sendProgressController,
|
||||
);
|
||||
},
|
||||
|
@ -120,58 +122,88 @@ class _ConfirmTransactionViewState
|
|||
),
|
||||
);
|
||||
|
||||
late String txid;
|
||||
Future<String> txidFuture;
|
||||
final List<String> txids = [];
|
||||
Future<TxData> txDataFuture;
|
||||
|
||||
final note = noteController.text;
|
||||
|
||||
try {
|
||||
if (widget.isTokenTx) {
|
||||
txidFuture = ref
|
||||
.read(tokenServiceProvider)!
|
||||
.confirmSend(txData: transactionInfo);
|
||||
txDataFuture =
|
||||
ref.read(pCurrentTokenWallet)!.confirmSend(txData: widget.txData);
|
||||
} else if (widget.isPaynymNotificationTransaction) {
|
||||
txidFuture = (manager.wallet as PaynymWalletInterface)
|
||||
.broadcastNotificationTx(preparedTx: transactionInfo);
|
||||
txDataFuture = (wallet as PaynymInterface)
|
||||
.broadcastNotificationTx(txData: widget.txData);
|
||||
} else if (widget.isPaynymTransaction) {
|
||||
txidFuture = manager.confirmSend(txData: transactionInfo);
|
||||
txDataFuture = wallet.confirmSend(txData: widget.txData);
|
||||
} else {
|
||||
final coin = manager.coin;
|
||||
if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state !=
|
||||
"Private") {
|
||||
txidFuture = (manager.wallet as FiroWallet)
|
||||
.confirmSendPublic(txData: transactionInfo);
|
||||
if (wallet is FiroWallet) {
|
||||
switch (ref.read(publicPrivateBalanceStateProvider.state).state) {
|
||||
case FiroType.public:
|
||||
if (widget.txData.sparkMints == null) {
|
||||
txDataFuture = wallet.confirmSend(txData: widget.txData);
|
||||
} else {
|
||||
txDataFuture =
|
||||
wallet.confirmSparkMintTransactions(txData: widget.txData);
|
||||
}
|
||||
break;
|
||||
|
||||
case FiroType.lelantus:
|
||||
txDataFuture = wallet.confirmSendLelantus(txData: widget.txData);
|
||||
break;
|
||||
|
||||
case FiroType.spark:
|
||||
txDataFuture = wallet.confirmSendSpark(txData: widget.txData);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (coin == Coin.epicCash) {
|
||||
transactionInfo["onChainNote"] = onChainNoteController.text;
|
||||
txDataFuture = wallet.confirmSend(
|
||||
txData: widget.txData.copyWith(
|
||||
noteOnChain: onChainNoteController.text,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
txDataFuture = wallet.confirmSend(txData: widget.txData);
|
||||
}
|
||||
txidFuture = manager.confirmSend(txData: transactionInfo);
|
||||
}
|
||||
}
|
||||
|
||||
final results = await Future.wait([
|
||||
txidFuture,
|
||||
txDataFuture,
|
||||
time,
|
||||
]);
|
||||
|
||||
sendProgressController.triggerSuccess?.call();
|
||||
await Future<void>.delayed(const Duration(seconds: 5));
|
||||
|
||||
txid = results.first as String;
|
||||
if (wallet is FiroWallet &&
|
||||
(results.first as TxData).sparkMints != null) {
|
||||
txids.addAll((results.first as TxData).sparkMints!.map((e) => e.txid!));
|
||||
} else {
|
||||
txids.add((results.first as TxData).txid!);
|
||||
}
|
||||
ref.refresh(desktopUseUTXOs);
|
||||
|
||||
// save note
|
||||
await ref
|
||||
.read(notesServiceChangeNotifierProvider(walletId))
|
||||
.editOrAddNote(txid: txid, note: note);
|
||||
for (final txid in txids) {
|
||||
await ref.read(mainDBProvider).putTransactionNote(
|
||||
TransactionNote(
|
||||
walletId: walletId,
|
||||
txid: txid,
|
||||
value: note,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (widget.isTokenTx) {
|
||||
unawaited(ref.read(tokenServiceProvider)!.refresh());
|
||||
unawaited(ref.read(pCurrentTokenWallet)!.refresh());
|
||||
} else {
|
||||
unawaited(manager.refresh());
|
||||
unawaited(wallet.refresh());
|
||||
}
|
||||
|
||||
widget.onSuccess.call();
|
||||
|
||||
// pop back to wallet
|
||||
if (mounted) {
|
||||
if (widget.onSuccessInsteadOfRouteOnSuccess == null) {
|
||||
|
@ -222,10 +254,14 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
Text(
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
child: SelectableText(
|
||||
e.toString(),
|
||||
style: STextStyles.smallMed14(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 56,
|
||||
),
|
||||
|
@ -274,16 +310,15 @@ class _ConfirmTransactionViewState
|
|||
@override
|
||||
void initState() {
|
||||
isDesktop = Util.isDesktop;
|
||||
transactionInfo = widget.transactionInfo;
|
||||
walletId = widget.walletId;
|
||||
routeOnSuccessName = widget.routeOnSuccessName;
|
||||
_noteFocusNode = FocusNode();
|
||||
noteController = TextEditingController();
|
||||
noteController.text = transactionInfo["note"] as String? ?? "";
|
||||
noteController.text = widget.txData.note ?? "";
|
||||
|
||||
_onChainNoteFocusNode = FocusNode();
|
||||
onChainNoteController = TextEditingController();
|
||||
onChainNoteController.text = transactionInfo["onChainNote"] as String? ?? "";
|
||||
onChainNoteController.text = widget.txData.noteOnChain ?? "";
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
@ -300,20 +335,57 @@ class _ConfirmTransactionViewState
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final managerProvider = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManagerProvider(walletId)));
|
||||
|
||||
final coin = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(walletId).coin));
|
||||
final coin = ref.watch(pWalletCoin(walletId));
|
||||
|
||||
final String unit;
|
||||
if (widget.isTokenTx) {
|
||||
unit = ref.watch(
|
||||
tokenServiceProvider.select((value) => value!.tokenContract.symbol));
|
||||
pCurrentTokenWallet.select((value) => value!.tokenContract.symbol));
|
||||
} else {
|
||||
unit = coin.ticker;
|
||||
}
|
||||
|
||||
final Amount? fee;
|
||||
final Amount amountWithoutChange;
|
||||
|
||||
final wallet = ref.watch(pWallets).getWallet(walletId);
|
||||
|
||||
if (wallet is FiroWallet) {
|
||||
switch (ref.read(publicPrivateBalanceStateProvider.state).state) {
|
||||
case FiroType.public:
|
||||
if (widget.txData.sparkMints != null) {
|
||||
fee = widget.txData.sparkMints!
|
||||
.map((e) => e.fee!)
|
||||
.reduce((value, element) => value += element);
|
||||
amountWithoutChange = widget.txData.sparkMints!
|
||||
.map((e) => e.amountSpark!)
|
||||
.reduce((value, element) => value += element);
|
||||
} else {
|
||||
fee = widget.txData.fee;
|
||||
amountWithoutChange = widget.txData.amountWithoutChange!;
|
||||
}
|
||||
break;
|
||||
|
||||
case FiroType.lelantus:
|
||||
fee = widget.txData.fee;
|
||||
amountWithoutChange = widget.txData.amountWithoutChange!;
|
||||
break;
|
||||
|
||||
case FiroType.spark:
|
||||
fee = widget.txData.fee;
|
||||
amountWithoutChange = (widget.txData.amountWithoutChange ??
|
||||
Amount.zeroWith(
|
||||
fractionDigits: wallet.cryptoCurrency.fractionDigits)) +
|
||||
(widget.txData.amountSparkWithoutChange ??
|
||||
Amount.zeroWith(
|
||||
fractionDigits: wallet.cryptoCurrency.fractionDigits));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
fee = widget.txData.fee;
|
||||
amountWithoutChange = widget.txData.amountWithoutChange!;
|
||||
}
|
||||
|
||||
return ConditionalParent(
|
||||
condition: !isDesktop,
|
||||
builder: (child) => Background(
|
||||
|
@ -385,7 +457,11 @@ class _ConfirmTransactionViewState
|
|||
),
|
||||
],
|
||||
),
|
||||
child,
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
|
@ -418,10 +494,9 @@ class _ConfirmTransactionViewState
|
|||
),
|
||||
Text(
|
||||
widget.isPaynymTransaction
|
||||
? (transactionInfo["paynymAccountLite"]
|
||||
as PaynymAccountLite)
|
||||
.nymName
|
||||
: "${transactionInfo["address"] ?? "ERROR"}",
|
||||
? widget.txData.paynymAccountLite!.nymName
|
||||
: widget.txData.recipients?.first.address ??
|
||||
widget.txData.sparkRecipients!.first.address,
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
],
|
||||
|
@ -438,11 +513,11 @@ class _ConfirmTransactionViewState
|
|||
"Amount",
|
||||
style: STextStyles.smallMed12(context),
|
||||
),
|
||||
Text(
|
||||
SelectableText(
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
transactionInfo["recipientAmt"] as Amount,
|
||||
amountWithoutChange,
|
||||
ethContract: ref
|
||||
.watch(tokenServiceProvider)
|
||||
.watch(pCurrentTokenWallet)
|
||||
?.tokenContract,
|
||||
),
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
|
@ -464,32 +539,19 @@ class _ConfirmTransactionViewState
|
|||
"Transaction fee",
|
||||
style: STextStyles.smallMed12(context),
|
||||
),
|
||||
Text(
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
(transactionInfo["fee"] is Amount
|
||||
? transactionInfo["fee"] as Amount
|
||||
: (transactionInfo["fee"] as int)
|
||||
.toAmountAsRaw(
|
||||
fractionDigits: ref.watch(
|
||||
managerProvider.select(
|
||||
(value) => value.coin.decimals,
|
||||
),
|
||||
),
|
||||
)),
|
||||
),
|
||||
SelectableText(
|
||||
ref.watch(pAmountFormatter(coin)).format(fee!),
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
textAlign: TextAlign.right,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (transactionInfo["fee"] is int &&
|
||||
transactionInfo["vSize"] is int)
|
||||
if (widget.txData.fee != null && widget.txData.vSize != null)
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (transactionInfo["fee"] is int &&
|
||||
transactionInfo["vSize"] is int)
|
||||
if (widget.txData.fee != null && widget.txData.vSize != null)
|
||||
RoundedWhiteContainer(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
@ -501,20 +563,20 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
"~${(transactionInfo["fee"] / transactionInfo["vSize"]).toInt()}",
|
||||
SelectableText(
|
||||
"~${fee!.raw.toInt() ~/ widget.txData.vSize!}",
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (coin == Coin.epicCash &&
|
||||
(transactionInfo["onChainNote"] as String).isNotEmpty)
|
||||
widget.txData.noteOnChain!.isNotEmpty)
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (coin == Coin.epicCash &&
|
||||
(transactionInfo["onChainNote"] as String).isNotEmpty)
|
||||
widget.txData.noteOnChain!.isNotEmpty)
|
||||
RoundedWhiteContainer(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
|
@ -526,18 +588,18 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
transactionInfo["onChainNote"] as String,
|
||||
SelectableText(
|
||||
widget.txData.noteOnChain!,
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if ((transactionInfo["note"] as String).isNotEmpty)
|
||||
if (widget.txData.note!.isNotEmpty)
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if ((transactionInfo["note"] as String).isNotEmpty)
|
||||
if (widget.txData.note!.isNotEmpty)
|
||||
RoundedWhiteContainer(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
|
@ -549,8 +611,8 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
Text(
|
||||
transactionInfo["note"] as String,
|
||||
SelectableText(
|
||||
widget.txData.note!,
|
||||
style: STextStyles.itemSubtitle12(context),
|
||||
),
|
||||
],
|
||||
|
@ -633,13 +695,6 @@ class _ConfirmTransactionViewState
|
|||
),
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final coin = ref.watch(
|
||||
managerProvider.select(
|
||||
(value) => value.coin,
|
||||
),
|
||||
);
|
||||
final amount =
|
||||
transactionInfo["recipientAmt"] as Amount;
|
||||
final externalCalls = ref.watch(
|
||||
prefsChangeNotifierProvider.select(
|
||||
(value) => value.externalCalls));
|
||||
|
@ -652,7 +707,7 @@ class _ConfirmTransactionViewState
|
|||
priceAnd24hChangeNotifierProvider)
|
||||
.getTokenPrice(
|
||||
ref
|
||||
.read(tokenServiceProvider)!
|
||||
.read(pCurrentTokenWallet)!
|
||||
.tokenContract
|
||||
.address,
|
||||
)
|
||||
|
@ -663,7 +718,8 @@ class _ConfirmTransactionViewState
|
|||
.getPrice(coin)
|
||||
.item1;
|
||||
if (price > Decimal.zero) {
|
||||
fiatAmount = (amount.decimal * price)
|
||||
fiatAmount =
|
||||
(amountWithoutChange.decimal * price)
|
||||
.toAmount(fractionDigits: 2)
|
||||
.fiatString(
|
||||
locale: ref
|
||||
|
@ -676,11 +732,11 @@ class _ConfirmTransactionViewState
|
|||
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
SelectableText(
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
amount,
|
||||
amountWithoutChange,
|
||||
ethContract: ref
|
||||
.read(tokenServiceProvider)
|
||||
.read(pCurrentTokenWallet)
|
||||
?.tokenContract),
|
||||
style: STextStyles
|
||||
.desktopTextExtraExtraSmall(
|
||||
|
@ -699,7 +755,7 @@ class _ConfirmTransactionViewState
|
|||
context),
|
||||
),
|
||||
if (externalCalls)
|
||||
Text(
|
||||
SelectableText(
|
||||
"~$fiatAmount ${ref.watch(prefsChangeNotifierProvider.select(
|
||||
(value) => value.currency,
|
||||
))}",
|
||||
|
@ -736,12 +792,13 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
Text(
|
||||
SelectableText(
|
||||
// TODO: [prio=med] spark transaction specifics - better handling
|
||||
widget.isPaynymTransaction
|
||||
? (transactionInfo["paynymAccountLite"]
|
||||
as PaynymAccountLite)
|
||||
.nymName
|
||||
: "${transactionInfo["address"] ?? "ERROR"}",
|
||||
? widget.txData.paynymAccountLite!.nymName
|
||||
: widget.txData.recipients?.first.address ??
|
||||
widget.txData.sparkRecipients!.first
|
||||
.address,
|
||||
style: STextStyles.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
.copyWith(
|
||||
|
@ -775,35 +832,15 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 2,
|
||||
),
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final coin = ref
|
||||
.watch(walletsChangeNotifierProvider
|
||||
.select((value) =>
|
||||
value.getManager(walletId)))
|
||||
.coin;
|
||||
|
||||
final fee = transactionInfo["fee"] is Amount
|
||||
? transactionInfo["fee"] as Amount
|
||||
: (transactionInfo["fee"] as int)
|
||||
.toAmountAsRaw(
|
||||
fractionDigits: coin.decimals,
|
||||
);
|
||||
|
||||
return Text(
|
||||
ref
|
||||
.watch(pAmountFormatter(coin))
|
||||
.format(fee),
|
||||
style:
|
||||
STextStyles.desktopTextExtraExtraSmall(
|
||||
SelectableText(
|
||||
ref.watch(pAmountFormatter(coin)).format(fee!),
|
||||
style: STextStyles.desktopTextExtraExtraSmall(
|
||||
context)
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textDark,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -885,8 +922,7 @@ class _ConfirmTransactionViewState
|
|||
).copyWith(
|
||||
suffixIcon: onChainNoteController.text.isNotEmpty
|
||||
? Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: 0),
|
||||
padding: const EdgeInsets.only(right: 0),
|
||||
child: UnconstrainedBox(
|
||||
child: Row(
|
||||
children: [
|
||||
|
@ -910,8 +946,9 @@ class _ConfirmTransactionViewState
|
|||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Text(
|
||||
(coin == Coin.epicCash) ? "Local Note (optional)"
|
||||
SelectableText(
|
||||
(coin == Coin.epicCash)
|
||||
? "Local Note (optional)"
|
||||
: "Note (optional)",
|
||||
style:
|
||||
STextStyles.desktopTextExtraSmall(context).copyWith(
|
||||
|
@ -1008,31 +1045,16 @@ class _ConfirmTransactionViewState
|
|||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultBG,
|
||||
child: Builder(
|
||||
builder: (context) {
|
||||
final coin = ref
|
||||
.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(walletId)))
|
||||
.coin;
|
||||
|
||||
final fee = transactionInfo["fee"] is Amount
|
||||
? transactionInfo["fee"] as Amount
|
||||
: (transactionInfo["fee"] as int).toAmountAsRaw(
|
||||
fractionDigits: coin.decimals,
|
||||
);
|
||||
|
||||
return Text(
|
||||
ref.watch(pAmountFormatter(coin)).format(fee),
|
||||
child: SelectableText(
|
||||
ref.watch(pAmountFormatter(coin)).format(fee!),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isDesktop &&
|
||||
!widget.isPaynymTransaction &&
|
||||
transactionInfo["fee"] is int &&
|
||||
transactionInfo["vSize"] is int)
|
||||
widget.txData.fee != null &&
|
||||
widget.txData.vSize != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 32,
|
||||
|
@ -1044,8 +1066,8 @@ class _ConfirmTransactionViewState
|
|||
),
|
||||
if (isDesktop &&
|
||||
!widget.isPaynymTransaction &&
|
||||
transactionInfo["fee"] is int &&
|
||||
transactionInfo["vSize"] is int)
|
||||
widget.txData.fee != null &&
|
||||
widget.txData.vSize != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
|
@ -1060,8 +1082,8 @@ class _ConfirmTransactionViewState
|
|||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.textFieldDefaultBG,
|
||||
child: Text(
|
||||
"~${(transactionInfo["fee"] / transactionInfo["vSize"]).toInt()}",
|
||||
child: SelectableText(
|
||||
"~${fee!.raw.toInt() ~/ widget.txData.vSize!}",
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
),
|
||||
|
@ -1105,21 +1127,10 @@ class _ConfirmTransactionViewState
|
|||
.textConfirmTotalAmount,
|
||||
),
|
||||
),
|
||||
Builder(builder: (context) {
|
||||
final coin = ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value.getManager(walletId).coin));
|
||||
final fee = transactionInfo["fee"] is Amount
|
||||
? transactionInfo["fee"] as Amount
|
||||
: (transactionInfo["fee"] as int)
|
||||
.toAmountAsRaw(fractionDigits: coin.decimals);
|
||||
|
||||
final amount =
|
||||
transactionInfo["recipientAmt"] as Amount;
|
||||
return Text(
|
||||
SelectableText(
|
||||
ref
|
||||
.watch(pAmountFormatter(coin))
|
||||
.format(amount + fee),
|
||||
.format(amountWithoutChange + fee!),
|
||||
style: isDesktop
|
||||
? STextStyles.desktopTextExtraExtraSmall(context)
|
||||
.copyWith(
|
||||
|
@ -1133,8 +1144,7 @@ class _ConfirmTransactionViewState
|
|||
.textConfirmTotalAmount,
|
||||
),
|
||||
textAlign: TextAlign.right,
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1154,11 +1164,6 @@ class _ConfirmTransactionViewState
|
|||
onPressed: () async {
|
||||
final dynamic unlocked;
|
||||
|
||||
final coin = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.coin;
|
||||
|
||||
if (isDesktop) {
|
||||
unlocked = await showDialog<bool?>(
|
||||
context: context,
|
||||
|
@ -1168,9 +1173,9 @@ class _ConfirmTransactionViewState
|
|||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
const Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: const [
|
||||
children: [
|
||||
DesktopDialogCloseButton(),
|
||||
],
|
||||
),
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,11 +12,11 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.dart';
|
||||
|
||||
class FiroBalanceSelectionSheet extends ConsumerStatefulWidget {
|
||||
const FiroBalanceSelectionSheet({
|
||||
|
@ -35,13 +35,6 @@ class _FiroBalanceSelectionSheetState
|
|||
extends ConsumerState<FiroBalanceSelectionSheet> {
|
||||
late final String walletId;
|
||||
|
||||
final stringsToLoopThrough = [
|
||||
"Loading balance",
|
||||
"Loading balance.",
|
||||
"Loading balance..",
|
||||
"Loading balance...",
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
walletId = widget.walletId;
|
||||
|
@ -52,9 +45,11 @@ class _FiroBalanceSelectionSheetState
|
|||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
|
||||
final manager = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(walletId)));
|
||||
final firoWallet = manager.wallet as FiroWallet;
|
||||
final wallet =
|
||||
ref.watch(pWallets.select((value) => value.getWallet(walletId)));
|
||||
final firoWallet = wallet as FiroWallet;
|
||||
|
||||
final coin = wallet.info.coin;
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
|
@ -106,9 +101,9 @@ class _FiroBalanceSelectionSheetState
|
|||
onTap: () {
|
||||
final state =
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state;
|
||||
if (state != "Private") {
|
||||
if (state != FiroType.spark) {
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state =
|
||||
"Private";
|
||||
FiroType.spark;
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -127,7 +122,7 @@ class _FiroBalanceSelectionSheetState
|
|||
activeColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.radioButtonIconEnabled,
|
||||
value: "Private",
|
||||
value: FiroType.spark,
|
||||
groupValue: ref
|
||||
.watch(
|
||||
publicPrivateBalanceStateProvider.state)
|
||||
|
@ -136,7 +131,7 @@ class _FiroBalanceSelectionSheetState
|
|||
ref
|
||||
.read(publicPrivateBalanceStateProvider
|
||||
.state)
|
||||
.state = "Private";
|
||||
.state = FiroType.spark;
|
||||
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -154,7 +149,7 @@ class _FiroBalanceSelectionSheetState
|
|||
// Row(
|
||||
// children: [
|
||||
Text(
|
||||
"Private balance",
|
||||
"Spark balance",
|
||||
style: STextStyles.titleBold12(context),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
|
@ -162,10 +157,9 @@ class _FiroBalanceSelectionSheetState
|
|||
width: 2,
|
||||
),
|
||||
Text(
|
||||
ref
|
||||
.watch(pAmountFormatter(manager.coin))
|
||||
.format(
|
||||
firoWallet.availablePrivateBalance(),
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
firoWallet
|
||||
.info.cachedBalanceTertiary.spendable,
|
||||
),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
textAlign: TextAlign.left,
|
||||
|
@ -186,9 +180,88 @@ class _FiroBalanceSelectionSheetState
|
|||
onTap: () {
|
||||
final state =
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state;
|
||||
if (state != "Public") {
|
||||
if (state != FiroType.lelantus) {
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state =
|
||||
"Public";
|
||||
FiroType.lelantus;
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: Radio(
|
||||
activeColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.radioButtonIconEnabled,
|
||||
value: FiroType.lelantus,
|
||||
groupValue: ref
|
||||
.watch(
|
||||
publicPrivateBalanceStateProvider.state)
|
||||
.state,
|
||||
onChanged: (x) {
|
||||
ref
|
||||
.read(publicPrivateBalanceStateProvider
|
||||
.state)
|
||||
.state = FiroType.lelantus;
|
||||
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
width: 12,
|
||||
),
|
||||
Flexible(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Row(
|
||||
// children: [
|
||||
Text(
|
||||
"Lelantus balance",
|
||||
style: STextStyles.titleBold12(context),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 2,
|
||||
),
|
||||
Text(
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
firoWallet.info.cachedBalanceSecondary
|
||||
.spendable,
|
||||
),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
],
|
||||
),
|
||||
// ],
|
||||
// ),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
final state =
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state;
|
||||
if (state != FiroType.public) {
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state =
|
||||
FiroType.public;
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -206,7 +279,7 @@ class _FiroBalanceSelectionSheetState
|
|||
activeColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.radioButtonIconEnabled,
|
||||
value: "Public",
|
||||
value: FiroType.public,
|
||||
groupValue: ref
|
||||
.watch(
|
||||
publicPrivateBalanceStateProvider.state)
|
||||
|
@ -215,7 +288,7 @@ class _FiroBalanceSelectionSheetState
|
|||
ref
|
||||
.read(publicPrivateBalanceStateProvider
|
||||
.state)
|
||||
.state = "Public";
|
||||
.state = FiroType.public;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
|
@ -240,10 +313,8 @@ class _FiroBalanceSelectionSheetState
|
|||
width: 2,
|
||||
),
|
||||
Text(
|
||||
ref
|
||||
.watch(pAmountFormatter(manager.coin))
|
||||
.format(
|
||||
firoWallet.availablePublicBalance(),
|
||||
ref.watch(pAmountFormatter(coin)).format(
|
||||
firoWallet.info.cachedBalance.spendable,
|
||||
),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
textAlign: TextAlign.left,
|
||||
|
|
|
@ -12,11 +12,9 @@ import 'package:cw_core/monero_transaction_priority.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||
import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/providers/ui/fee_rate_type_state_provider.dart';
|
||||
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||
|
@ -25,6 +23,9 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
|||
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/firo_wallet.dart';
|
||||
import 'package:stackwallet/widgets/animated_text.dart';
|
||||
|
||||
final feeSheetSessionCacheProvider =
|
||||
|
@ -83,26 +84,34 @@ class _TransactionFeeSelectionSheetState
|
|||
case FeeRateType.fast:
|
||||
if (ref.read(feeSheetSessionCacheProvider).fast[amount] == null) {
|
||||
if (widget.isToken == false) {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
|
||||
if (coin == Coin.monero || coin == Coin.wownero) {
|
||||
final fee = await manager.estimateFeeFor(
|
||||
final fee = await wallet.estimateFeeFor(
|
||||
amount, MoneroTransactionPriority.fast.raw!);
|
||||
ref.read(feeSheetSessionCacheProvider).fast[amount] = fee;
|
||||
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state !=
|
||||
"Private") {
|
||||
ref.read(feeSheetSessionCacheProvider).fast[amount] =
|
||||
await (manager.wallet as FiroWallet)
|
||||
.estimateFeeForPublic(amount, feeRate);
|
||||
} else if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
||||
final Amount fee;
|
||||
switch (ref.read(publicPrivateBalanceStateProvider.state).state) {
|
||||
case FiroType.spark:
|
||||
fee =
|
||||
await (wallet as FiroWallet).estimateFeeForSpark(amount);
|
||||
case FiroType.lelantus:
|
||||
fee = await (wallet as FiroWallet)
|
||||
.estimateFeeForLelantus(amount);
|
||||
case FiroType.public:
|
||||
fee = await (wallet as FiroWallet)
|
||||
.estimateFeeFor(amount, feeRate);
|
||||
}
|
||||
|
||||
ref.read(feeSheetSessionCacheProvider).fast[amount] = fee;
|
||||
} else {
|
||||
ref.read(feeSheetSessionCacheProvider).fast[amount] =
|
||||
await manager.estimateFeeFor(amount, feeRate);
|
||||
await wallet.estimateFeeFor(amount, feeRate);
|
||||
}
|
||||
} else {
|
||||
final tokenWallet = ref.read(tokenServiceProvider)!;
|
||||
final fee = tokenWallet.estimateFeeFor(feeRate);
|
||||
final tokenWallet = ref.read(pCurrentTokenWallet)!;
|
||||
final fee = await tokenWallet.estimateFeeFor(amount, feeRate);
|
||||
ref.read(feeSheetSessionCacheProvider).fast[amount] = fee;
|
||||
}
|
||||
}
|
||||
|
@ -111,25 +120,32 @@ class _TransactionFeeSelectionSheetState
|
|||
case FeeRateType.average:
|
||||
if (ref.read(feeSheetSessionCacheProvider).average[amount] == null) {
|
||||
if (widget.isToken == false) {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
if (coin == Coin.monero || coin == Coin.wownero) {
|
||||
final fee = await manager.estimateFeeFor(
|
||||
final fee = await wallet.estimateFeeFor(
|
||||
amount, MoneroTransactionPriority.regular.raw!);
|
||||
ref.read(feeSheetSessionCacheProvider).average[amount] = fee;
|
||||
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state !=
|
||||
"Private") {
|
||||
ref.read(feeSheetSessionCacheProvider).average[amount] =
|
||||
await (manager.wallet as FiroWallet)
|
||||
.estimateFeeForPublic(amount, feeRate);
|
||||
} else if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
||||
final Amount fee;
|
||||
switch (ref.read(publicPrivateBalanceStateProvider.state).state) {
|
||||
case FiroType.spark:
|
||||
fee =
|
||||
await (wallet as FiroWallet).estimateFeeForSpark(amount);
|
||||
case FiroType.lelantus:
|
||||
fee = await (wallet as FiroWallet)
|
||||
.estimateFeeForLelantus(amount);
|
||||
case FiroType.public:
|
||||
fee = await (wallet as FiroWallet)
|
||||
.estimateFeeFor(amount, feeRate);
|
||||
}
|
||||
ref.read(feeSheetSessionCacheProvider).average[amount] = fee;
|
||||
} else {
|
||||
ref.read(feeSheetSessionCacheProvider).average[amount] =
|
||||
await manager.estimateFeeFor(amount, feeRate);
|
||||
await wallet.estimateFeeFor(amount, feeRate);
|
||||
}
|
||||
} else {
|
||||
final tokenWallet = ref.read(tokenServiceProvider)!;
|
||||
final fee = tokenWallet.estimateFeeFor(feeRate);
|
||||
final tokenWallet = ref.read(pCurrentTokenWallet)!;
|
||||
final fee = await tokenWallet.estimateFeeFor(amount, feeRate);
|
||||
ref.read(feeSheetSessionCacheProvider).average[amount] = fee;
|
||||
}
|
||||
}
|
||||
|
@ -138,25 +154,32 @@ class _TransactionFeeSelectionSheetState
|
|||
case FeeRateType.slow:
|
||||
if (ref.read(feeSheetSessionCacheProvider).slow[amount] == null) {
|
||||
if (widget.isToken == false) {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
if (coin == Coin.monero || coin == Coin.wownero) {
|
||||
final fee = await manager.estimateFeeFor(
|
||||
final fee = await wallet.estimateFeeFor(
|
||||
amount, MoneroTransactionPriority.slow.raw!);
|
||||
ref.read(feeSheetSessionCacheProvider).slow[amount] = fee;
|
||||
} else if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||
ref.read(publicPrivateBalanceStateProvider.state).state !=
|
||||
"Private") {
|
||||
ref.read(feeSheetSessionCacheProvider).slow[amount] =
|
||||
await (manager.wallet as FiroWallet)
|
||||
.estimateFeeForPublic(amount, feeRate);
|
||||
} else if (coin == Coin.firo || coin == Coin.firoTestNet) {
|
||||
final Amount fee;
|
||||
switch (ref.read(publicPrivateBalanceStateProvider.state).state) {
|
||||
case FiroType.spark:
|
||||
fee =
|
||||
await (wallet as FiroWallet).estimateFeeForSpark(amount);
|
||||
case FiroType.lelantus:
|
||||
fee = await (wallet as FiroWallet)
|
||||
.estimateFeeForLelantus(amount);
|
||||
case FiroType.public:
|
||||
fee = await (wallet as FiroWallet)
|
||||
.estimateFeeFor(amount, feeRate);
|
||||
}
|
||||
ref.read(feeSheetSessionCacheProvider).slow[amount] = fee;
|
||||
} else {
|
||||
ref.read(feeSheetSessionCacheProvider).slow[amount] =
|
||||
await manager.estimateFeeFor(amount, feeRate);
|
||||
await wallet.estimateFeeFor(amount, feeRate);
|
||||
}
|
||||
} else {
|
||||
final tokenWallet = ref.read(tokenServiceProvider)!;
|
||||
final fee = tokenWallet.estimateFeeFor(feeRate);
|
||||
final tokenWallet = ref.read(pCurrentTokenWallet)!;
|
||||
final fee = await tokenWallet.estimateFeeFor(amount, feeRate);
|
||||
ref.read(feeSheetSessionCacheProvider).slow[amount] = fee;
|
||||
}
|
||||
}
|
||||
|
@ -203,8 +226,9 @@ class _TransactionFeeSelectionSheetState
|
|||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
|
||||
final manager = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(walletId)));
|
||||
final wallet = ref.watch(pWallets).getWallet(walletId);
|
||||
|
||||
final coin = ref.watch(pWalletCoin(walletId));
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
|
@ -243,8 +267,8 @@ class _TransactionFeeSelectionSheetState
|
|||
),
|
||||
FutureBuilder(
|
||||
future: widget.isToken
|
||||
? ref.read(tokenServiceProvider)!.fees
|
||||
: manager.fees,
|
||||
? ref.read(pCurrentTokenWallet)!.fees
|
||||
: wallet.fees,
|
||||
builder: (context, AsyncSnapshot<FeeObject> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasData) {
|
||||
|
@ -270,7 +294,8 @@ class _TransactionFeeSelectionSheetState
|
|||
ref.read(feeRateTypeStateProvider.state).state =
|
||||
FeeRateType.fast;
|
||||
}
|
||||
String? fee = getAmount(FeeRateType.fast, manager.coin);
|
||||
String? fee =
|
||||
getAmount(FeeRateType.fast, wallet.info.coin);
|
||||
if (fee != null) {
|
||||
widget.updateChosen(fee);
|
||||
}
|
||||
|
@ -333,7 +358,7 @@ class _TransactionFeeSelectionSheetState
|
|||
if (feeObject != null)
|
||||
FutureBuilder(
|
||||
future: feeFor(
|
||||
coin: manager.coin,
|
||||
coin: coin,
|
||||
feeRateType: FeeRateType.fast,
|
||||
feeRate: feeObject!.fast,
|
||||
amount: amount,
|
||||
|
@ -346,7 +371,7 @@ class _TransactionFeeSelectionSheetState
|
|||
return Text(
|
||||
"(~${ref.watch(
|
||||
pAmountFormatter(
|
||||
manager.coin,
|
||||
coin,
|
||||
),
|
||||
).format(
|
||||
snapshot.data!,
|
||||
|
@ -373,18 +398,18 @@ class _TransactionFeeSelectionSheetState
|
|||
height: 2,
|
||||
),
|
||||
if (feeObject == null &&
|
||||
manager.coin != Coin.ethereum)
|
||||
coin != Coin.ethereum)
|
||||
AnimatedText(
|
||||
stringsToLoopThrough:
|
||||
stringsToLoopThrough,
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
if (feeObject != null &&
|
||||
manager.coin != Coin.ethereum)
|
||||
coin != Coin.ethereum)
|
||||
Text(
|
||||
estimatedTimeToBeIncludedInNextBlock(
|
||||
Constants.targetBlockTimeInSeconds(
|
||||
manager.coin),
|
||||
coin),
|
||||
feeObject!.numberOfBlocksFast,
|
||||
),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
|
@ -408,8 +433,7 @@ class _TransactionFeeSelectionSheetState
|
|||
ref.read(feeRateTypeStateProvider.state).state =
|
||||
FeeRateType.average;
|
||||
}
|
||||
String? fee =
|
||||
getAmount(FeeRateType.average, manager.coin);
|
||||
String? fee = getAmount(FeeRateType.average, coin);
|
||||
if (fee != null) {
|
||||
widget.updateChosen(fee);
|
||||
}
|
||||
|
@ -470,7 +494,7 @@ class _TransactionFeeSelectionSheetState
|
|||
if (feeObject != null)
|
||||
FutureBuilder(
|
||||
future: feeFor(
|
||||
coin: manager.coin,
|
||||
coin: coin,
|
||||
feeRateType: FeeRateType.average,
|
||||
feeRate: feeObject!.medium,
|
||||
amount: amount,
|
||||
|
@ -483,7 +507,7 @@ class _TransactionFeeSelectionSheetState
|
|||
return Text(
|
||||
"(~${ref.watch(
|
||||
pAmountFormatter(
|
||||
manager.coin,
|
||||
coin,
|
||||
),
|
||||
).format(
|
||||
snapshot.data!,
|
||||
|
@ -510,18 +534,18 @@ class _TransactionFeeSelectionSheetState
|
|||
height: 2,
|
||||
),
|
||||
if (feeObject == null &&
|
||||
manager.coin != Coin.ethereum)
|
||||
coin != Coin.ethereum)
|
||||
AnimatedText(
|
||||
stringsToLoopThrough:
|
||||
stringsToLoopThrough,
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
if (feeObject != null &&
|
||||
manager.coin != Coin.ethereum)
|
||||
coin != Coin.ethereum)
|
||||
Text(
|
||||
estimatedTimeToBeIncludedInNextBlock(
|
||||
Constants.targetBlockTimeInSeconds(
|
||||
manager.coin),
|
||||
coin),
|
||||
feeObject!.numberOfBlocksAverage,
|
||||
),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
|
@ -545,7 +569,7 @@ class _TransactionFeeSelectionSheetState
|
|||
ref.read(feeRateTypeStateProvider.state).state =
|
||||
FeeRateType.slow;
|
||||
}
|
||||
String? fee = getAmount(FeeRateType.slow, manager.coin);
|
||||
String? fee = getAmount(FeeRateType.slow, coin);
|
||||
if (fee != null) {
|
||||
widget.updateChosen(fee);
|
||||
}
|
||||
|
@ -606,7 +630,7 @@ class _TransactionFeeSelectionSheetState
|
|||
if (feeObject != null)
|
||||
FutureBuilder(
|
||||
future: feeFor(
|
||||
coin: manager.coin,
|
||||
coin: coin,
|
||||
feeRateType: FeeRateType.slow,
|
||||
feeRate: feeObject!.slow,
|
||||
amount: amount,
|
||||
|
@ -619,7 +643,7 @@ class _TransactionFeeSelectionSheetState
|
|||
return Text(
|
||||
"(~${ref.watch(
|
||||
pAmountFormatter(
|
||||
manager.coin,
|
||||
coin,
|
||||
),
|
||||
).format(
|
||||
snapshot.data!,
|
||||
|
@ -646,18 +670,18 @@ class _TransactionFeeSelectionSheetState
|
|||
height: 2,
|
||||
),
|
||||
if (feeObject == null &&
|
||||
manager.coin != Coin.ethereum)
|
||||
coin != Coin.ethereum)
|
||||
AnimatedText(
|
||||
stringsToLoopThrough:
|
||||
stringsToLoopThrough,
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
if (feeObject != null &&
|
||||
manager.coin != Coin.ethereum)
|
||||
coin != Coin.ethereum)
|
||||
Text(
|
||||
estimatedTimeToBeIncludedInNextBlock(
|
||||
Constants.targetBlockTimeInSeconds(
|
||||
manager.coin),
|
||||
coin),
|
||||
feeObject!.numberOfBlocksSlow,
|
||||
),
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
|
@ -673,7 +697,7 @@ class _TransactionFeeSelectionSheetState
|
|||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
if (manager.coin.isElectrumXCoin)
|
||||
if (coin.isElectrumXCoin)
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
final state =
|
||||
|
@ -742,7 +766,7 @@ class _TransactionFeeSelectionSheetState
|
|||
),
|
||||
),
|
||||
),
|
||||
if (manager.coin.isElectrumXCoin)
|
||||
if (coin.isElectrumXCoin)
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
|
|
|
@ -21,12 +21,10 @@ import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
|
|||
import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart';
|
||||
import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dialog.dart';
|
||||
import 'package:stackwallet/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart';
|
||||
import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/providers/ui/fee_rate_type_state_provider.dart';
|
||||
import 'package:stackwallet/providers/ui/preview_tx_button_state_provider.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||
|
@ -42,6 +40,10 @@ import 'package:stackwallet/utilities/logger.dart';
|
|||
import 'package:stackwallet/utilities/prefs.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/eth/token_balance_provider.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/models/tx_data.dart';
|
||||
import 'package:stackwallet/widgets/animated_text.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
|
@ -193,8 +195,9 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
|
||||
// now check for non standard encoded basic address
|
||||
} else if (ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.read(pWallets)
|
||||
.getWallet(walletId)
|
||||
.cryptoCurrency
|
||||
.validateAddress(qrResult.rawContent)) {
|
||||
_address = qrResult.rawContent.trim();
|
||||
sendToController.text = _address ?? "";
|
||||
|
@ -325,11 +328,16 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
});
|
||||
}
|
||||
|
||||
String? _updateInvalidAddressText(String address, Manager manager) {
|
||||
String? _updateInvalidAddressText(String address) {
|
||||
if (_data != null && _data!.contactLabel == address) {
|
||||
return null;
|
||||
}
|
||||
if (address.isNotEmpty && !manager.validateAddress(address)) {
|
||||
if (address.isNotEmpty &&
|
||||
!ref
|
||||
.read(pWallets)
|
||||
.getWallet(walletId)
|
||||
.cryptoCurrency
|
||||
.validateAddress(address)) {
|
||||
return "Invalid address";
|
||||
}
|
||||
return null;
|
||||
|
@ -337,15 +345,16 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
|
||||
void _updatePreviewButtonState(String? address, Amount? amount) {
|
||||
final isValidAddress = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.read(pWallets)
|
||||
.getWallet(walletId)
|
||||
.cryptoCurrency
|
||||
.validateAddress(address ?? "");
|
||||
ref.read(previewTxButtonStateProvider.state).state =
|
||||
ref.read(previewTokenTxButtonStateProvider.state).state =
|
||||
(isValidAddress && amount != null && amount > Amount.zero);
|
||||
}
|
||||
|
||||
Future<String> calculateFees() async {
|
||||
final wallet = ref.read(tokenServiceProvider)!;
|
||||
final wallet = ref.read(pCurrentTokenWallet)!;
|
||||
final feeObject = await wallet.fees;
|
||||
|
||||
late final int feeRate;
|
||||
|
@ -364,7 +373,7 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
feeRate = -1;
|
||||
}
|
||||
|
||||
final Amount fee = wallet.estimateFeeFor(feeRate);
|
||||
final Amount fee = await wallet.estimateFeeFor(Amount.zero, feeRate);
|
||||
cachedFees = ref.read(pAmountFormatter(coin)).format(
|
||||
fee,
|
||||
withUnitName: true,
|
||||
|
@ -380,9 +389,8 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
await Future<void>.delayed(
|
||||
const Duration(milliseconds: 100),
|
||||
);
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId);
|
||||
final tokenWallet = ref.read(tokenServiceProvider)!;
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
final tokenWallet = ref.read(pCurrentTokenWallet)!;
|
||||
|
||||
final Amount amount = _amountToSend!;
|
||||
|
||||
|
@ -448,7 +456,7 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return BuildingTransactionDialog(
|
||||
coin: manager.coin,
|
||||
coin: wallet.info.coin,
|
||||
onCancel: () {
|
||||
wasCancelled = true;
|
||||
|
||||
|
@ -466,15 +474,21 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> txData;
|
||||
Future<Map<String, dynamic>> txDataFuture;
|
||||
TxData txData;
|
||||
Future<TxData> txDataFuture;
|
||||
|
||||
txDataFuture = tokenWallet.prepareSend(
|
||||
txData: TxData(
|
||||
recipients: [
|
||||
(
|
||||
address: _address!,
|
||||
amount: amount,
|
||||
args: {
|
||||
"feeRate": ref.read(feeRateTypeStateProvider),
|
||||
},
|
||||
isChange: false,
|
||||
)
|
||||
],
|
||||
feeRateType: ref.read(feeRateTypeStateProvider),
|
||||
note: noteController.text,
|
||||
),
|
||||
);
|
||||
|
||||
final results = await Future.wait([
|
||||
|
@ -482,22 +496,20 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
time,
|
||||
]);
|
||||
|
||||
txData = results.first as Map<String, dynamic>;
|
||||
txData = results.first as TxData;
|
||||
|
||||
if (!wasCancelled && mounted) {
|
||||
// pop building dialog
|
||||
Navigator.of(context).pop();
|
||||
txData["note"] = noteController.text;
|
||||
|
||||
txData["address"] = _address;
|
||||
|
||||
unawaited(Navigator.of(context).push(
|
||||
RouteGenerator.getRoute(
|
||||
shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute,
|
||||
builder: (_) => ConfirmTransactionView(
|
||||
transactionInfo: txData,
|
||||
txData: txData,
|
||||
walletId: walletId,
|
||||
isTokenTx: true,
|
||||
onSuccess: clearSendForm,
|
||||
),
|
||||
settings: const RouteSettings(
|
||||
name: ConfirmTransactionView.routeName,
|
||||
|
@ -510,7 +522,8 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
// pop building dialog
|
||||
Navigator.of(context).pop();
|
||||
|
||||
unawaited(showDialog<dynamic>(
|
||||
unawaited(
|
||||
showDialog<dynamic>(
|
||||
context: context,
|
||||
useSafeArea: false,
|
||||
barrierDismissible: true,
|
||||
|
@ -535,11 +548,25 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
),
|
||||
);
|
||||
},
|
||||
));
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clearSendForm() {
|
||||
sendToController.text = "";
|
||||
cryptoAmountController.text = "";
|
||||
baseAmountController.text = "";
|
||||
noteController.text = "";
|
||||
feeController.text = "";
|
||||
_address = "";
|
||||
_addressToggleFlag = false;
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
ref.refresh(feeSheetSessionCacheProvider);
|
||||
|
@ -598,8 +625,6 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
debugPrint("BUILD: $runtimeType");
|
||||
final provider = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManagerProvider(walletId)));
|
||||
final String locale = ref.watch(
|
||||
localeServiceChangeNotifierProvider.select((value) => value.locale));
|
||||
|
||||
|
@ -667,8 +692,7 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
ref.watch(provider.select(
|
||||
(value) => value.walletName)),
|
||||
ref.watch(pWalletName(walletId)),
|
||||
style: STextStyles.titleBold12(context)
|
||||
.copyWith(fontSize: 14),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -688,8 +712,11 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
.watch(pAmountFormatter(coin))
|
||||
.format(
|
||||
ref
|
||||
.read(tokenServiceProvider)!
|
||||
.balance
|
||||
.read(pTokenBalance((
|
||||
walletId: widget.walletId,
|
||||
contractAddress:
|
||||
tokenContract.address,
|
||||
)))
|
||||
.spendable,
|
||||
ethContract: tokenContract,
|
||||
withUnitName: false,
|
||||
|
@ -706,18 +733,16 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
ref
|
||||
.watch(pAmountFormatter(coin))
|
||||
.format(
|
||||
ref.watch(
|
||||
tokenServiceProvider.select(
|
||||
(value) => value!
|
||||
.balance.spendable,
|
||||
),
|
||||
),
|
||||
ethContract: ref.watch(
|
||||
tokenServiceProvider.select(
|
||||
(value) =>
|
||||
value!.tokenContract,
|
||||
),
|
||||
),
|
||||
ref
|
||||
.watch(pTokenBalance((
|
||||
walletId:
|
||||
widget.walletId,
|
||||
contractAddress:
|
||||
tokenContract
|
||||
.address,
|
||||
)))
|
||||
.spendable,
|
||||
ethContract: tokenContract,
|
||||
),
|
||||
style:
|
||||
STextStyles.titleBold12(context)
|
||||
|
@ -727,7 +752,13 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
textAlign: TextAlign.right,
|
||||
),
|
||||
Text(
|
||||
"${(ref.watch(tokenServiceProvider.select((value) => value!.balance.spendable.decimal)) * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getTokenPrice(tokenContract.address).item1))).toAmount(
|
||||
"${(ref.watch(pTokenBalance((
|
||||
walletId:
|
||||
widget.walletId,
|
||||
contractAddress:
|
||||
tokenContract
|
||||
.address,
|
||||
))).spendable.decimal * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getTokenPrice(tokenContract.address).item1))).toAmount(
|
||||
fractionDigits: 2,
|
||||
).fiatString(
|
||||
locale: locale,
|
||||
|
@ -860,9 +891,6 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
builder: (_) {
|
||||
final error = _updateInvalidAddressText(
|
||||
_address ?? "",
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId),
|
||||
);
|
||||
|
||||
if (error == null || error.isEmpty) {
|
||||
|
@ -1224,12 +1252,14 @@ class _TokenSendViewState extends ConsumerState<TokenSendView> {
|
|||
),
|
||||
TextButton(
|
||||
onPressed: ref
|
||||
.watch(previewTxButtonStateProvider.state)
|
||||
.watch(
|
||||
previewTokenTxButtonStateProvider.state)
|
||||
.state
|
||||
? _previewTransaction
|
||||
: null,
|
||||
style: ref
|
||||
.watch(previewTxButtonStateProvider.state)
|
||||
.watch(
|
||||
previewTokenTxButtonStateProvider.state)
|
||||
.state
|
||||
? Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
|
|
|
@ -525,6 +525,32 @@ class AboutView extends ConsumerWidget {
|
|||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
RoundedWhiteContainer(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Tezos functionality",
|
||||
style: STextStyles.titleBold12(context),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
CustomTextButton(
|
||||
text: "Powered by TzKT API",
|
||||
onTap: () {
|
||||
launchUrl(
|
||||
Uri.parse("https://tzkt.io"),
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
const Spacer(),
|
||||
RichText(
|
||||
textAlign: TextAlign.center,
|
||||
|
|
|
@ -9,27 +9,18 @@
|
|||
*/
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bitbox/bitbox.dart' as bb;
|
||||
import 'package:bitcoindart/bitcoindart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/providers/global/debug_service_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
|
||||
import 'package:stackwallet/services/mixins/electrum_x_parsing.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.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';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
|
@ -224,98 +215,7 @@ class HiddenSettings extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}),
|
||||
// const SizedBox(
|
||||
// height: 12,
|
||||
// ),
|
||||
// Consumer(builder: (_, ref, __) {
|
||||
// return GestureDetector(
|
||||
// onTap: () async {
|
||||
// final x =
|
||||
// await MajesticBankAPI.instance.getRates();
|
||||
// print(x);
|
||||
// },
|
||||
// child: RoundedWhiteContainer(
|
||||
// child: Text(
|
||||
// "Click me",
|
||||
// style: STextStyles.button(context).copyWith(
|
||||
// color: Theme.of(context)
|
||||
// .extension<StackColors>()!
|
||||
// .accentColorDark),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }),
|
||||
// const SizedBox(
|
||||
// height: 12,
|
||||
// ),
|
||||
// Consumer(builder: (_, ref, __) {
|
||||
// return GestureDetector(
|
||||
// onTap: () async {
|
||||
// ref
|
||||
// .read(priceAnd24hChangeNotifierProvider)
|
||||
// .tokenContractAddressesToCheck
|
||||
// .add(
|
||||
// "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
|
||||
// ref
|
||||
// .read(priceAnd24hChangeNotifierProvider)
|
||||
// .tokenContractAddressesToCheck
|
||||
// .add(
|
||||
// "0xdAC17F958D2ee523a2206206994597C13D831ec7");
|
||||
// await ref
|
||||
// .read(priceAnd24hChangeNotifierProvider)
|
||||
// .updatePrice();
|
||||
//
|
||||
// final x = ref
|
||||
// .read(priceAnd24hChangeNotifierProvider)
|
||||
// .getTokenPrice(
|
||||
// "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48");
|
||||
//
|
||||
// print(
|
||||
// "PRICE 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48: $x");
|
||||
// },
|
||||
// child: RoundedWhiteContainer(
|
||||
// child: Text(
|
||||
// "Click me",
|
||||
// style: STextStyles.button(context).copyWith(
|
||||
// color: Theme.of(context)
|
||||
// .extension<StackColors>()!
|
||||
// .accentColorDark),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }),
|
||||
// const SizedBox(
|
||||
// height: 12,
|
||||
// ),
|
||||
// Consumer(builder: (_, ref, __) {
|
||||
// return GestureDetector(
|
||||
// onTap: () async {
|
||||
// // final erc20 = Erc20ContractInfo(
|
||||
// // contractAddress: 'some con',
|
||||
// // name: "loonamsn",
|
||||
// // symbol: "DD",
|
||||
// // decimals: 19,
|
||||
// // );
|
||||
// //
|
||||
// // final json = erc20.toJson();
|
||||
// //
|
||||
// // print(json);
|
||||
// //
|
||||
// // final ee = EthContractInfo.fromJson(json);
|
||||
// //
|
||||
// // print(ee);
|
||||
// },
|
||||
// child: RoundedWhiteContainer(
|
||||
// child: Text(
|
||||
// "Click me",
|
||||
// style: STextStyles.button(context).copyWith(
|
||||
// color: Theme.of(context)
|
||||
// .extension<StackColors>()!
|
||||
// .accentColorDark),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }),
|
||||
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
|
@ -352,82 +252,15 @@ class HiddenSettings extends StatelessWidget {
|
|||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Consumer(
|
||||
builder: (_, ref, __) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
try {
|
||||
final p = TT();
|
||||
|
||||
final n = ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.getPrimaryNodeFor(
|
||||
coin: Coin.bitcoincash)!;
|
||||
|
||||
final e = ElectrumX.from(
|
||||
node: ElectrumXNode(
|
||||
address: n.host,
|
||||
port: n.port,
|
||||
name: n.name,
|
||||
id: n.id,
|
||||
useSSL: n.useSSL,
|
||||
),
|
||||
prefs:
|
||||
ref.read(prefsChangeNotifierProvider),
|
||||
failovers: [],
|
||||
);
|
||||
|
||||
final ce =
|
||||
CachedElectrumX(electrumXClient: e);
|
||||
|
||||
final txids = [
|
||||
"", // cashTokenTxid
|
||||
"6a0444358bc41913c5b04a8dc06896053184b3641bc62502d18f954865b6ce1e", // normalTxid
|
||||
"67f13c375f9be897036cac77b7900dc74312c4ba6fe22f419f5cb21d4151678c", // fusionTxid
|
||||
"c0ac3f88b238a023d2a87226dc90c3b0f9abc3eeb227e2730087b0b95ee5b3f9", // slpTokenSendTxid
|
||||
"7a427a156fe70f83d3ccdd17e75804cc0df8c95c64ce04d256b3851385002a0b", // slpTokenGenesisTxid
|
||||
];
|
||||
|
||||
// final json =
|
||||
// await e.getTransaction(txHash: txids[1]);
|
||||
// await p.parseBchTx(json, "NORMAL TXID:");
|
||||
//
|
||||
// final json2 =
|
||||
// await e.getTransaction(txHash: txids[2]);
|
||||
// await p.parseBchTx(json2, "FUSION TXID:");
|
||||
//
|
||||
// // print("CASH TOKEN TXID:");
|
||||
// // final json3 =
|
||||
// // await e.getTransaction(txHash: txids[2]);
|
||||
// // await p.parseBchTx(json3);
|
||||
//
|
||||
await p.getTransaction(
|
||||
txids[3],
|
||||
Coin.bitcoincash,
|
||||
"lol",
|
||||
ce,
|
||||
"SLP TOKEN SEND TXID:");
|
||||
await p.getTransaction(
|
||||
"009d31380d2dbfb5c91500c861d55b531a8b762b0abb19353db884548dbac8b6",
|
||||
Coin.bitcoincash,
|
||||
"lol",
|
||||
ce,
|
||||
"COINBASE TXID:");
|
||||
|
||||
// final json5 =
|
||||
// await e.getTransaction(txHash: txids[4]);
|
||||
// await p.parseBchTx(
|
||||
// json5, "SLP TOKEN GENESIS TXID:");
|
||||
} catch (e, s) {
|
||||
print("$e\n$s");
|
||||
}
|
||||
},
|
||||
child: RoundedWhiteContainer(
|
||||
child: Text(
|
||||
"Parse BCH tx test",
|
||||
"Do nothing",
|
||||
style: STextStyles.button(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
|
@ -437,125 +270,6 @@ class HiddenSettings extends StatelessWidget {
|
|||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Consumer(
|
||||
builder: (_, ref, __) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
try {
|
||||
final p = TT();
|
||||
|
||||
final n = ref
|
||||
.read(nodeServiceChangeNotifierProvider)
|
||||
.getPrimaryNodeFor(
|
||||
coin: Coin.bitcoincash)!;
|
||||
|
||||
final e = ElectrumX.from(
|
||||
node: ElectrumXNode(
|
||||
address: n.host,
|
||||
port: n.port,
|
||||
name: n.name,
|
||||
id: n.id,
|
||||
useSSL: n.useSSL,
|
||||
),
|
||||
prefs:
|
||||
ref.read(prefsChangeNotifierProvider),
|
||||
failovers: [],
|
||||
);
|
||||
|
||||
final address =
|
||||
"qzmd5vxgh9m22m6fgvm57yd6kjnjl9qnwyztz2p80d";
|
||||
|
||||
List<int> _base32Decode(String string) {
|
||||
final data = Uint8List(string.length);
|
||||
for (int i = 0; i < string.length; i++) {
|
||||
final value = string[i];
|
||||
if (!_CHARSET_INVERSE_INDEX
|
||||
.containsKey(value))
|
||||
throw FormatException(
|
||||
"Invalid character '$value'");
|
||||
data[i] =
|
||||
_CHARSET_INVERSE_INDEX[string[i]]!;
|
||||
}
|
||||
|
||||
return data.sublist(1);
|
||||
}
|
||||
|
||||
final dec = _base32Decode(address);
|
||||
|
||||
final pd = PaymentData(
|
||||
pubkey: Uint8List.fromList(dec));
|
||||
|
||||
final p2pkh =
|
||||
P2PKH(data: pd, network: bitcoincash);
|
||||
|
||||
// final addr = p2pkh.data.address!;
|
||||
|
||||
final addr = bb.Address.toLegacyAddress(
|
||||
"bitcoincash:qp352c2skpdxwzzd090mec3v37au5dmfwgwfw686sz",
|
||||
);
|
||||
|
||||
final scripthash =
|
||||
AddressUtils.convertToScriptHash(
|
||||
addr, bitcoincash);
|
||||
|
||||
final utxos =
|
||||
await e.getUTXOs(scripthash: scripthash);
|
||||
|
||||
Util.printJson(utxos, "UTXOS for $address");
|
||||
|
||||
final hist = await e.getTransaction(
|
||||
txHash: utxos.first["tx_hash"] as String,
|
||||
);
|
||||
|
||||
Util.printJson(hist, "HISTORY for $address");
|
||||
} catch (e, s) {
|
||||
print("$e\n$s");
|
||||
}
|
||||
},
|
||||
child: RoundedWhiteContainer(
|
||||
child: Text(
|
||||
"UTXOs",
|
||||
style: STextStyles.button(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.accentColorDark),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
// const SizedBox(
|
||||
// height: 12,
|
||||
// ),
|
||||
// GestureDetector(
|
||||
// onTap: () async {
|
||||
// showDialog<void>(
|
||||
// context: context,
|
||||
// builder: (_) {
|
||||
// return StackDialogBase(
|
||||
// child: SizedBox(
|
||||
// width: 300,
|
||||
// child: Lottie.asset(
|
||||
// Assets.lottie.plain(Coin.bitcoincash),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// );
|
||||
// },
|
||||
// child: RoundedWhiteContainer(
|
||||
// child: Text(
|
||||
// "Lottie test",
|
||||
// style: STextStyles.button(context).copyWith(
|
||||
// color: Theme.of(context)
|
||||
// .extension<StackColors>()!
|
||||
// .accentColorDark),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -568,38 +282,3 @@ class HiddenSettings extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
const _CHARSET_INVERSE_INDEX = {
|
||||
'q': 0,
|
||||
'p': 1,
|
||||
'z': 2,
|
||||
'r': 3,
|
||||
'y': 4,
|
||||
'9': 5,
|
||||
'x': 6,
|
||||
'8': 7,
|
||||
'g': 8,
|
||||
'f': 9,
|
||||
'2': 10,
|
||||
't': 11,
|
||||
'v': 12,
|
||||
'd': 13,
|
||||
'w': 14,
|
||||
'0': 15,
|
||||
's': 16,
|
||||
'3': 17,
|
||||
'j': 18,
|
||||
'n': 19,
|
||||
'5': 20,
|
||||
'4': 21,
|
||||
'k': 22,
|
||||
'h': 23,
|
||||
'c': 24,
|
||||
'e': 25,
|
||||
'6': 26,
|
||||
'm': 27,
|
||||
'u': 28,
|
||||
'a': 29,
|
||||
'7': 30,
|
||||
'l': 31,
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx_client.dart';
|
||||
import 'package:stackwallet/models/node_model.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
|
@ -30,6 +30,7 @@ import 'package:stackwallet/utilities/test_monero_node_connection.dart';
|
|||
import 'package:stackwallet/utilities/test_stellar_node_connection.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/api/tezos/tezos_rpc_api.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';
|
||||
|
@ -170,7 +171,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
|
|||
case Coin.bitcoincashTestnet:
|
||||
case Coin.firoTestNet:
|
||||
case Coin.dogecoinTestNet:
|
||||
final client = ElectrumX(
|
||||
final client = ElectrumXClient(
|
||||
host: formData.host!,
|
||||
port: formData.port!,
|
||||
useSSL: formData.useSSL!,
|
||||
|
@ -205,9 +206,15 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
|
|||
|
||||
case Coin.nano:
|
||||
case Coin.banano:
|
||||
case Coin.tezos:
|
||||
throw UnimplementedError();
|
||||
//TODO: check network/node
|
||||
case Coin.tezos:
|
||||
try {
|
||||
testPassed = await TezosRpcAPI.testNetworkConnection(
|
||||
nodeInfo: (host: formData.host!, port: formData.port!),
|
||||
);
|
||||
} catch (_) {}
|
||||
break;
|
||||
}
|
||||
|
||||
if (showFlushBar && mounted) {
|
||||
|
|
|
@ -13,7 +13,7 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
|
||||
import 'package:stackwallet/electrumx_rpc/electrumx_client.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
|
@ -29,6 +29,7 @@ import 'package:stackwallet/utilities/test_monero_node_connection.dart';
|
|||
import 'package:stackwallet/utilities/test_stellar_node_connection.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/api/tezos/tezos_rpc_api.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';
|
||||
|
@ -147,7 +148,7 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
|
|||
case Coin.litecoinTestNet:
|
||||
case Coin.bitcoincashTestnet:
|
||||
case Coin.eCash:
|
||||
final client = ElectrumX(
|
||||
final client = ElectrumXClient(
|
||||
host: node!.host,
|
||||
port: node.port,
|
||||
useSSL: node.useSSL,
|
||||
|
@ -173,9 +174,16 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
|
|||
|
||||
case Coin.nano:
|
||||
case Coin.banano:
|
||||
case Coin.tezos:
|
||||
// TODO: fix this lacking code
|
||||
throw UnimplementedError();
|
||||
//TODO: check network/node
|
||||
case Coin.tezos:
|
||||
try {
|
||||
testPassed = await TezosRpcAPI.testNetworkConnection(
|
||||
nodeInfo: (host: node!.host, port: node!.port),
|
||||
);
|
||||
} catch (_) {}
|
||||
break;
|
||||
case Coin.stellar:
|
||||
case Coin.stellarTestnet:
|
||||
try {
|
||||
|
|
|
@ -13,26 +13,24 @@ import 'dart:convert';
|
|||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stack_wallet_backup/stack_wallet_backup.dart';
|
||||
import 'package:stackwallet/db/hive/db.dart';
|
||||
import 'package:stackwallet/db/isar/main_db.dart';
|
||||
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
|
||||
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
|
||||
import 'package:stackwallet/models/isar/models/contact_entry.dart';
|
||||
import 'package:stackwallet/models/isar/models/transaction_note.dart';
|
||||
import 'package:stackwallet/models/node_model.dart';
|
||||
import 'package:stackwallet/models/stack_restoring_ui_state.dart';
|
||||
import 'package:stackwallet/models/trade_wallet_lookup.dart';
|
||||
import 'package:stackwallet/models/wallet_restore_state.dart';
|
||||
import 'package:stackwallet/services/address_book_service.dart';
|
||||
import 'package:stackwallet/services/coins/coin_service.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/services/node_service.dart';
|
||||
import 'package:stackwallet/services/notes_service.dart';
|
||||
import 'package:stackwallet/services/trade_notes_service.dart';
|
||||
import 'package:stackwallet/services/trade_sent_from_stack_service.dart';
|
||||
import 'package:stackwallet/services/trade_service.dart';
|
||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/services/wallets.dart';
|
||||
import 'package:stackwallet/services/wallets_service.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -43,6 +41,10 @@ import 'package:stackwallet/utilities/format.dart';
|
|||
import 'package:stackwallet/utilities/logger.dart';
|
||||
import 'package:stackwallet/utilities/prefs.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/private_key_interface.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import 'package:wakelock/wakelock.dart';
|
||||
|
@ -285,27 +287,39 @@ abstract class SWB {
|
|||
);
|
||||
|
||||
List<dynamic> backupWallets = [];
|
||||
for (var manager in _wallets.managers) {
|
||||
for (var wallet in _wallets.wallets) {
|
||||
Map<String, dynamic> backupWallet = {};
|
||||
backupWallet['name'] = manager.walletName;
|
||||
backupWallet['id'] = manager.walletId;
|
||||
backupWallet['isFavorite'] = manager.isFavorite;
|
||||
backupWallet['mnemonic'] = await manager.mnemonic;
|
||||
backupWallet['mnemonicPassphrase'] = await manager.mnemonicPassphrase;
|
||||
backupWallet['coinName'] = manager.coin.name;
|
||||
backupWallet['storedChainHeight'] = DB.instance
|
||||
.get<dynamic>(boxName: manager.walletId, key: 'storedChainHeight');
|
||||
backupWallet['name'] = wallet.info.name;
|
||||
backupWallet['id'] = wallet.walletId;
|
||||
backupWallet['isFavorite'] = wallet.info.isFavourite;
|
||||
backupWallet['otherDataJsonString'] = wallet.info.otherDataJsonString;
|
||||
|
||||
backupWallet['txidList'] = DB.instance.get<dynamic>(
|
||||
boxName: manager.walletId, key: "cachedTxids") as List?;
|
||||
if (wallet is MnemonicInterface) {
|
||||
backupWallet['mnemonic'] = await wallet.getMnemonic();
|
||||
backupWallet['mnemonicPassphrase'] =
|
||||
await wallet.getMnemonicPassphrase();
|
||||
} else if (wallet is PrivateKeyInterface) {
|
||||
backupWallet['privateKey'] = await wallet.getPrivateKey();
|
||||
}
|
||||
backupWallet['coinName'] = wallet.info.coin.name;
|
||||
backupWallet['storedChainHeight'] = wallet.info.cachedChainHeight;
|
||||
|
||||
// backupWallet['txidList'] = DB.instance.get<dynamic>(
|
||||
// boxName: wallet.walletId, key: "cachedTxids") as List?;
|
||||
// the following can cause a deadlock
|
||||
// (await manager.transactionData).getAllTransactions().keys.toList();
|
||||
|
||||
backupWallet['restoreHeight'] = DB.instance
|
||||
.get<dynamic>(boxName: manager.walletId, key: 'restoreHeight');
|
||||
backupWallet['restoreHeight'] = wallet.info.restoreHeight;
|
||||
|
||||
final isarNotes = await MainDB.instance.isar.transactionNotes
|
||||
.where()
|
||||
.walletIdEqualTo(wallet.walletId)
|
||||
.findAll();
|
||||
|
||||
final notes = isarNotes
|
||||
.asMap()
|
||||
.map((key, value) => MapEntry(value.txid, value.value));
|
||||
|
||||
NotesService notesService = NotesService(walletId: manager.walletId);
|
||||
var notes = await notesService.notes;
|
||||
backupWallet['notes'] = notes;
|
||||
|
||||
backupWallets.add(backupWallet);
|
||||
|
@ -355,92 +369,113 @@ abstract class SWB {
|
|||
}
|
||||
|
||||
static Future<bool> asyncRestore(
|
||||
Tuple2<dynamic, Manager> tuple,
|
||||
Tuple2<dynamic, WalletInfo> tuple,
|
||||
Prefs prefs,
|
||||
NodeService nodeService,
|
||||
SecureStorageInterface secureStorageInterface,
|
||||
StackRestoringUIState? uiState,
|
||||
WalletsService walletsService,
|
||||
) async {
|
||||
final manager = tuple.item2;
|
||||
final info = tuple.item2;
|
||||
final walletbackup = tuple.item1;
|
||||
|
||||
String? mnemonic, mnemonicPassphrase, privateKey;
|
||||
|
||||
if (walletbackup['mnemonic'] == null) {
|
||||
// probably private key based
|
||||
privateKey = walletbackup['privateKey'] as String;
|
||||
} else {
|
||||
if (walletbackup['mnemonic'] is List) {
|
||||
List<String> mnemonicList = (walletbackup['mnemonic'] as List<dynamic>)
|
||||
.map<String>((e) => e as String)
|
||||
.toList();
|
||||
final String mnemonic = mnemonicList.join(" ").trim();
|
||||
final String mnemonicPassphrase =
|
||||
walletbackup['mnemonicPassphrase'] as String? ?? "";
|
||||
mnemonic = mnemonicList.join(" ").trim();
|
||||
} else {
|
||||
mnemonic = walletbackup['mnemonic'] as String;
|
||||
}
|
||||
|
||||
mnemonicPassphrase = walletbackup['mnemonicPassphrase'] as String? ?? "";
|
||||
}
|
||||
|
||||
uiState?.update(
|
||||
walletId: manager.walletId,
|
||||
walletId: info.walletId,
|
||||
restoringStatus: StackRestoringStatus.restoring,
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
|
||||
if (_shouldCancelRestore) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
int restoreHeight = 0;
|
||||
final wallet = await Wallet.create(
|
||||
walletInfo: info,
|
||||
mainDB: MainDB.instance,
|
||||
secureStorageInterface: secureStorageInterface,
|
||||
nodeService: nodeService,
|
||||
prefs: prefs,
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
privateKey: privateKey,
|
||||
);
|
||||
|
||||
restoreHeight = walletbackup['restoreHeight'] as int? ?? 0;
|
||||
await wallet.init();
|
||||
|
||||
int restoreHeight = walletbackup['restoreHeight'] as int? ?? 0;
|
||||
if (restoreHeight <= 0) {
|
||||
restoreHeight = walletbackup['storedChainHeight'] as int? ?? 0;
|
||||
}
|
||||
|
||||
manager.isFavorite = walletbackup['isFavorite'] == "false" ? false : true;
|
||||
uiState?.update(
|
||||
walletId: info.walletId,
|
||||
restoringStatus: StackRestoringStatus.restoring,
|
||||
wallet: wallet,
|
||||
);
|
||||
|
||||
if (_shouldCancelRestore) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// restore notes
|
||||
NotesService notesService = NotesService(walletId: manager.walletId);
|
||||
final notes = walletbackup["notes"] as Map?;
|
||||
if (notes != null) {
|
||||
for (final note in notes.entries) {
|
||||
await notesService.editOrAddNote(
|
||||
txid: note.key as String, note: note.value as String);
|
||||
}
|
||||
}
|
||||
final notesMap =
|
||||
Map<String, String>.from(walletbackup["notes"] as Map? ?? {});
|
||||
final List<TransactionNote> notes = [];
|
||||
|
||||
if (_shouldCancelRestore) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO GUI option to set maxUnusedAddressGap?
|
||||
// default is 20 but it may miss some transactions if
|
||||
// the previous wallet software generated many addresses
|
||||
// without using them
|
||||
await manager.recoverFromMnemonic(
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
maxUnusedAddressGap: manager.coin == Coin.firo ? 50 : 20,
|
||||
maxNumberOfIndexesToCheck: 1000,
|
||||
height: restoreHeight,
|
||||
for (final key in notesMap.keys) {
|
||||
if (notesMap[key] != null && notesMap[key]!.isNotEmpty) {
|
||||
notes.add(
|
||||
TransactionNote(
|
||||
walletId: info.walletId,
|
||||
txid: key,
|
||||
value: notesMap[key]!,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (notes.isNotEmpty) {
|
||||
await MainDB.instance.isar.writeTxn(() async {
|
||||
await MainDB.instance.isar.transactionNotes.putAll(notes);
|
||||
});
|
||||
}
|
||||
|
||||
if (_shouldCancelRestore) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if mnemonic verified does not get set the wallet will be deleted on app restart
|
||||
await walletsService.setMnemonicVerified(walletId: manager.walletId);
|
||||
await wallet.info.setMnemonicVerified(isar: MainDB.instance.isar);
|
||||
|
||||
if (_shouldCancelRestore) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.instance.log(
|
||||
"SWB restored: ${manager.walletId} ${manager.walletName} ${manager.coin.prettyName}",
|
||||
"SWB restored: ${info.walletId} ${info.name} ${info.coin.prettyName}",
|
||||
level: LogLevel.Info);
|
||||
|
||||
final currentAddress = await manager.currentReceivingAddress;
|
||||
final currentAddress = await wallet.getCurrentReceivingAddress();
|
||||
uiState?.update(
|
||||
walletId: manager.walletId,
|
||||
walletId: info.walletId,
|
||||
restoringStatus: StackRestoringStatus.success,
|
||||
manager: manager,
|
||||
address: currentAddress,
|
||||
wallet: wallet,
|
||||
address: currentAddress?.value,
|
||||
height: restoreHeight,
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
|
@ -448,9 +483,8 @@ abstract class SWB {
|
|||
} catch (e, s) {
|
||||
Logging.instance.log("$e $s", level: LogLevel.Warning);
|
||||
uiState?.update(
|
||||
walletId: manager.walletId,
|
||||
walletId: info.walletId,
|
||||
restoringStatus: StackRestoringStatus.failed,
|
||||
manager: manager,
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
|
@ -578,13 +612,10 @@ abstract class SWB {
|
|||
level: LogLevel.Warning,
|
||||
);
|
||||
|
||||
List<String> _currentWalletIds = Map<String, dynamic>.from(DB.instance
|
||||
.get<dynamic>(
|
||||
boxName: DB.boxNameAllWalletsData, key: "names") as Map? ??
|
||||
{})
|
||||
.values
|
||||
.map((e) => e["id"] as String)
|
||||
.toList();
|
||||
List<String> _currentWalletIds = await MainDB.instance.isar.walletInfo
|
||||
.where()
|
||||
.walletIdProperty()
|
||||
.findAll();
|
||||
|
||||
final preRestoreState =
|
||||
PreRestoreState(_currentWalletIds.toSet(), preRestoreJSON);
|
||||
|
@ -634,13 +665,11 @@ abstract class SWB {
|
|||
final nodeService = NodeService(
|
||||
secureStorageInterface: secureStorageInterface,
|
||||
);
|
||||
final walletsService = WalletsService(
|
||||
secureStorageInterface: secureStorageInterface,
|
||||
);
|
||||
|
||||
final _prefs = Prefs.instance;
|
||||
await _prefs.init();
|
||||
|
||||
final List<Tuple2<dynamic, Manager>> managers = [];
|
||||
final List<Tuple2<dynamic, WalletInfo>> managers = [];
|
||||
|
||||
Map<String, WalletRestoreState> walletStates = {};
|
||||
|
||||
|
@ -653,26 +682,22 @@ abstract class SWB {
|
|||
return false;
|
||||
}
|
||||
|
||||
Coin coin = Coin.values
|
||||
final coin = Coin.values
|
||||
.firstWhere((element) => element.name == walletbackup['coinName']);
|
||||
String walletName = walletbackup['name'] as String;
|
||||
final walletName = walletbackup['name'] as String;
|
||||
final walletId = oldToNewWalletIdMap[walletbackup["id"] as String]!;
|
||||
|
||||
// TODO: use these for monero and possibly other coins later on?
|
||||
// final List<String> txidList = List<String>.from(walletbackup['txidList'] as List? ?? []);
|
||||
|
||||
const int sanityCheckMax = 100;
|
||||
int count = 0;
|
||||
while (await walletsService.checkForDuplicate(walletName) &&
|
||||
count < sanityCheckMax) {
|
||||
walletName += " (restored)";
|
||||
}
|
||||
|
||||
await walletsService.addExistingStackWallet(
|
||||
name: walletName,
|
||||
final info = WalletInfo(
|
||||
coinName: coin.name,
|
||||
walletId: walletId,
|
||||
coin: coin,
|
||||
shouldNotifyListeners: false,
|
||||
name: walletName,
|
||||
mainAddressType: coin.primaryAddressType,
|
||||
restoreHeight: walletbackup['restoreHeight'] as int? ?? 0,
|
||||
otherDataJsonString: walletbackup["otherDataJsonString"] as String?,
|
||||
cachedChainHeight: walletbackup['storedChainHeight'] as int? ?? 0,
|
||||
);
|
||||
|
||||
var node = nodeService.getPrimaryNodeFor(coin: coin);
|
||||
|
@ -682,9 +707,9 @@ abstract class SWB {
|
|||
await nodeService.setPrimaryNodeFor(coin: coin, node: node);
|
||||
}
|
||||
|
||||
final txTracker = TransactionNotificationTracker(walletId: walletId);
|
||||
|
||||
final failovers = nodeService.failoverNodesFor(coin: coin);
|
||||
// final txTracker = TransactionNotificationTracker(walletId: walletId);
|
||||
//
|
||||
// final failovers = nodeService.failoverNodesFor(coin: coin);
|
||||
|
||||
// check if cancel was requested and restore previous state
|
||||
if (_checkShouldCancel(
|
||||
|
@ -694,20 +719,7 @@ abstract class SWB {
|
|||
return false;
|
||||
}
|
||||
|
||||
final wallet = CoinServiceAPI.from(
|
||||
coin,
|
||||
walletId,
|
||||
walletName,
|
||||
secureStorageInterface,
|
||||
node,
|
||||
txTracker,
|
||||
_prefs,
|
||||
failovers,
|
||||
);
|
||||
|
||||
final manager = Manager(wallet);
|
||||
|
||||
managers.add(Tuple2(walletbackup, manager));
|
||||
managers.add(Tuple2(walletbackup, info));
|
||||
// check if cancel was requested and restore previous state
|
||||
if (_checkShouldCancel(
|
||||
preRestoreState,
|
||||
|
@ -721,7 +733,6 @@ abstract class SWB {
|
|||
restoringStatus: StackRestoringStatus.waiting,
|
||||
walletId: walletId,
|
||||
walletName: walletName,
|
||||
manager: manager,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -746,7 +757,13 @@ abstract class SWB {
|
|||
)) {
|
||||
return false;
|
||||
}
|
||||
final bools = await asyncRestore(tuple, uiState, walletsService);
|
||||
final bools = await asyncRestore(
|
||||
tuple,
|
||||
_prefs,
|
||||
nodeService,
|
||||
secureStorageInterface,
|
||||
uiState,
|
||||
);
|
||||
restoreStatuses.add(Future(() => bools));
|
||||
}
|
||||
|
||||
|
@ -781,7 +798,7 @@ abstract class SWB {
|
|||
Logging.instance.log("done with SWB restore", level: LogLevel.Warning);
|
||||
if (Util.isDesktop) {
|
||||
await Wallets.sharedInstance
|
||||
.loadAfterStackRestore(_prefs, managers.map((e) => e.item2).toList());
|
||||
.loadAfterStackRestore(_prefs, uiState?.wallets ?? []);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -984,14 +1001,16 @@ abstract class SWB {
|
|||
}
|
||||
|
||||
// finally remove any added wallets
|
||||
final walletsService =
|
||||
WalletsService(secureStorageInterface: secureStorageInterface);
|
||||
final namesData = await walletsService.walletNames;
|
||||
for (final entry in namesData.entries) {
|
||||
if (!revertToState.walletIds.contains(entry.value.walletId)) {
|
||||
await walletsService.deleteWallet(entry.key, true);
|
||||
}
|
||||
}
|
||||
final allWalletIds = (await MainDB.instance.isar.walletInfo
|
||||
.where()
|
||||
.walletIdProperty()
|
||||
.findAll())
|
||||
.toSet();
|
||||
final walletIdsToDelete = allWalletIds.difference(revertToState.walletIds);
|
||||
await MainDB.instance.isar.writeTxn(() async {
|
||||
await MainDB.instance.isar.walletInfo
|
||||
.deleteAllByWalletId(walletIdsToDelete.toList());
|
||||
});
|
||||
|
||||
_cancelCompleter!.complete();
|
||||
_shouldCancelRestore = false;
|
||||
|
|
|
@ -215,9 +215,9 @@ class _StackRestoreProgressViewState
|
|||
}
|
||||
|
||||
void _addWalletsToHomeView() {
|
||||
ref.read(walletsChangeNotifierProvider).loadAfterStackRestore(
|
||||
ref.read(pWallets).loadAfterStackRestore(
|
||||
ref.read(prefsChangeNotifierProvider),
|
||||
ref.read(stackRestoringUIStateProvider).managers,
|
||||
ref.read(stackRestoringUIStateProvider).wallets,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -105,49 +105,29 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
|
|||
),
|
||||
onRightTapped: restoringStatus == StackRestoringStatus.failed
|
||||
? () async {
|
||||
final manager = ref.read(provider).manager!;
|
||||
final wallet = ref.read(provider).wallet!;
|
||||
|
||||
ref.read(stackRestoringUIStateProvider).update(
|
||||
walletId: manager.walletId,
|
||||
walletId: wallet.walletId,
|
||||
restoringStatus: StackRestoringStatus.restoring);
|
||||
|
||||
try {
|
||||
final mnemonicList = await manager.mnemonic;
|
||||
int maxUnusedAddressGap = 20;
|
||||
if (coin == Coin.firo) {
|
||||
maxUnusedAddressGap = 50;
|
||||
}
|
||||
const maxNumberOfIndexesToCheck = 1000;
|
||||
|
||||
if (mnemonicList.isEmpty) {
|
||||
await manager.recoverFromMnemonic(
|
||||
mnemonic: ref.read(provider).mnemonic!,
|
||||
mnemonicPassphrase:
|
||||
ref.read(provider).mnemonicPassphrase!,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
height: ref.read(provider).height ?? 0,
|
||||
);
|
||||
} else {
|
||||
await manager.fullRescan(
|
||||
maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck,
|
||||
);
|
||||
}
|
||||
await wallet.recover(isRescan: true);
|
||||
|
||||
if (mounted) {
|
||||
final address = await manager.currentReceivingAddress;
|
||||
final address =
|
||||
await wallet.getCurrentReceivingAddress();
|
||||
|
||||
ref.read(stackRestoringUIStateProvider).update(
|
||||
walletId: manager.walletId,
|
||||
walletId: wallet.walletId,
|
||||
restoringStatus: StackRestoringStatus.success,
|
||||
address: address,
|
||||
address: address!.value,
|
||||
);
|
||||
}
|
||||
} catch (_) {
|
||||
if (mounted) {
|
||||
ref.read(stackRestoringUIStateProvider).update(
|
||||
walletId: manager.walletId,
|
||||
walletId: wallet.walletId,
|
||||
restoringStatus: StackRestoringStatus.failed,
|
||||
);
|
||||
}
|
||||
|
@ -223,7 +203,7 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
|
|||
: null,
|
||||
)
|
||||
: RoundedContainer(
|
||||
padding: EdgeInsets.all(0),
|
||||
padding: const EdgeInsets.all(0),
|
||||
color: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
borderColor: Theme.of(context).extension<StackColors>()!.background,
|
||||
child: RestoringItemCard(
|
||||
|
@ -250,50 +230,53 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
|
|||
),
|
||||
onRightTapped: restoringStatus == StackRestoringStatus.failed
|
||||
? () async {
|
||||
final manager = ref.read(provider).manager!;
|
||||
final wallet = ref.read(provider).wallet!;
|
||||
|
||||
ref.read(stackRestoringUIStateProvider).update(
|
||||
walletId: manager.walletId,
|
||||
walletId: wallet.walletId,
|
||||
restoringStatus: StackRestoringStatus.restoring);
|
||||
|
||||
try {
|
||||
final mnemonicList = await manager.mnemonic;
|
||||
int maxUnusedAddressGap = 20;
|
||||
if (coin == Coin.firo) {
|
||||
maxUnusedAddressGap = 50;
|
||||
}
|
||||
const maxNumberOfIndexesToCheck = 1000;
|
||||
// final mnemonicList = await manager.mnemonic;
|
||||
// int maxUnusedAddressGap = 20;
|
||||
// if (coin == Coin.firo) {
|
||||
// maxUnusedAddressGap = 50;
|
||||
// }
|
||||
// const maxNumberOfIndexesToCheck = 1000;
|
||||
//
|
||||
// if (mnemonicList.isEmpty) {
|
||||
// await manager.recoverFromMnemonic(
|
||||
// mnemonic: ref.read(provider).mnemonic!,
|
||||
// mnemonicPassphrase:
|
||||
// ref.read(provider).mnemonicPassphrase!,
|
||||
// maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
// maxNumberOfIndexesToCheck:
|
||||
// maxNumberOfIndexesToCheck,
|
||||
// height: ref.read(provider).height ?? 0,
|
||||
// );
|
||||
// } else {
|
||||
// await manager.fullRescan(
|
||||
// maxUnusedAddressGap,
|
||||
// maxNumberOfIndexesToCheck,
|
||||
// );
|
||||
// }
|
||||
|
||||
if (mnemonicList.isEmpty) {
|
||||
await manager.recoverFromMnemonic(
|
||||
mnemonic: ref.read(provider).mnemonic!,
|
||||
mnemonicPassphrase:
|
||||
ref.read(provider).mnemonicPassphrase!,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck:
|
||||
maxNumberOfIndexesToCheck,
|
||||
height: ref.read(provider).height ?? 0,
|
||||
);
|
||||
} else {
|
||||
await manager.fullRescan(
|
||||
maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck,
|
||||
);
|
||||
}
|
||||
await wallet.recover(isRescan: true);
|
||||
|
||||
if (mounted) {
|
||||
final address = await manager.currentReceivingAddress;
|
||||
final address =
|
||||
await wallet.getCurrentReceivingAddress();
|
||||
|
||||
ref.read(stackRestoringUIStateProvider).update(
|
||||
walletId: manager.walletId,
|
||||
walletId: wallet.walletId,
|
||||
restoringStatus: StackRestoringStatus.success,
|
||||
address: address,
|
||||
address: address!.value,
|
||||
);
|
||||
}
|
||||
} catch (_) {
|
||||
if (mounted) {
|
||||
ref.read(stackRestoringUIStateProvider).update(
|
||||
walletId: manager.walletId,
|
||||
walletId: wallet.walletId,
|
||||
restoringStatus: StackRestoringStatus.failed,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import 'package:stackwallet/themes/coin_icon_provider.dart';
|
|||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
@ -45,7 +46,7 @@ class _StartupPreferencesViewState
|
|||
// check if wallet exists (hasn't been deleted or otherwise missing)
|
||||
if (possibleWalletId != null) {
|
||||
try {
|
||||
ref.read(walletsChangeNotifierProvider).getManager(possibleWalletId);
|
||||
ref.read(pWallets).getWallet(possibleWalletId);
|
||||
} catch (_) {
|
||||
safe = false;
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
|
@ -252,19 +253,14 @@ class _StartupPreferencesViewState
|
|||
File(
|
||||
ref.watch(
|
||||
coinIconProvider(
|
||||
ref
|
||||
.watch(
|
||||
walletsChangeNotifierProvider
|
||||
.select(
|
||||
(value) =>
|
||||
value.getManager(
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select((value) => value.startupWalletId!),
|
||||
pWalletCoin(
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select((value) =>
|
||||
value.startupWalletId!),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.coin,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -273,21 +269,15 @@ class _StartupPreferencesViewState
|
|||
width: 10,
|
||||
),
|
||||
Text(
|
||||
ref
|
||||
.watch(
|
||||
walletsChangeNotifierProvider
|
||||
.select(
|
||||
(value) =>
|
||||
value
|
||||
.getManager(
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select((value) =>
|
||||
pWalletName(
|
||||
ref.watch(
|
||||
prefsChangeNotifierProvider.select(
|
||||
(value) =>
|
||||
value.startupWalletId!),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
.walletName,
|
||||
style: STextStyles
|
||||
.itemSubtitle(
|
||||
context),
|
||||
|
|
|
@ -18,6 +18,7 @@ import 'package:stackwallet/themes/coin_icon_provider.dart';
|
|||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
|
||||
|
@ -38,11 +39,10 @@ class _StartupWalletSelectionViewState
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final managers = ref
|
||||
.watch(walletsChangeNotifierProvider.select((value) => value.managers));
|
||||
final wallets = ref.watch(pWallets).wallets;
|
||||
|
||||
_controllers.clear();
|
||||
for (final manager in managers) {
|
||||
for (final manager in wallets) {
|
||||
_controllers[manager.walletId] = DSBController();
|
||||
}
|
||||
|
||||
|
@ -95,18 +95,21 @@ class _StartupWalletSelectionViewState
|
|||
padding: const EdgeInsets.all(0),
|
||||
child: Column(
|
||||
children: [
|
||||
...managers.map(
|
||||
(manager) => Padding(
|
||||
...wallets.map(
|
||||
(wallet) => Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
key: Key(
|
||||
"startupWalletSelectionGroupKey_${manager.walletId}"),
|
||||
"startupWalletSelectionGroupKey_${wallet.walletId}"),
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.colorForCoin(manager.coin)
|
||||
.colorForCoin(
|
||||
ref.watch(pWalletCoin(
|
||||
wallet.walletId)),
|
||||
)
|
||||
.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
|
@ -117,7 +120,10 @@ class _StartupWalletSelectionViewState
|
|||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
coinIconProvider(manager.coin),
|
||||
coinIconProvider(
|
||||
ref.watch(pWalletCoin(
|
||||
wallet.walletId)),
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 20,
|
||||
|
@ -136,7 +142,8 @@ class _StartupWalletSelectionViewState
|
|||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
manager.walletName,
|
||||
ref.watch(
|
||||
pWalletName(wallet.walletId)),
|
||||
style: STextStyles.titleBold12(
|
||||
context),
|
||||
),
|
||||
|
@ -184,7 +191,7 @@ class _StartupWalletSelectionViewState
|
|||
activeColor: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.radioButtonIconEnabled,
|
||||
value: manager.walletId,
|
||||
value: wallet.walletId,
|
||||
groupValue: ref.watch(
|
||||
prefsChangeNotifierProvider.select(
|
||||
(value) =>
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart';
|
||||
import 'package:stackwallet/providers/global/active_wallet_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
|
@ -95,11 +96,8 @@ class SyncingOptionsView extends ConsumerWidget {
|
|||
SyncingType.currentWalletOnly;
|
||||
|
||||
// disable auto sync on all wallets that aren't active/current
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.managers
|
||||
.forEach((e) {
|
||||
if (!e.isActiveWallet) {
|
||||
ref.read(pWallets).wallets.forEach((e) {
|
||||
if (e.walletId != ref.read(currentWalletIdProvider)) {
|
||||
e.shouldAutoSync = false;
|
||||
}
|
||||
});
|
||||
|
@ -178,8 +176,8 @@ class SyncingOptionsView extends ConsumerWidget {
|
|||
|
||||
// enable auto sync on all wallets
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.managers
|
||||
.read(pWallets)
|
||||
.wallets
|
||||
.forEach((e) => e.shouldAutoSync = true);
|
||||
}
|
||||
},
|
||||
|
@ -259,11 +257,8 @@ class SyncingOptionsView extends ConsumerWidget {
|
|||
.walletIdsSyncOnStartup;
|
||||
|
||||
// enable auto sync on selected wallets only
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.managers
|
||||
.forEach((e) =>
|
||||
e.shouldAutoSync = ids.contains(e.walletId));
|
||||
ref.read(pWallets).wallets.forEach(
|
||||
(e) => e.shouldAutoSync = ids.contains(e.walletId));
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'dart:io';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/providers/global/active_wallet_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/coin_icon_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
|
@ -21,6 +22,7 @@ import 'package:stackwallet/utilities/constants.dart';
|
|||
import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.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';
|
||||
|
@ -34,8 +36,7 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final managers = ref
|
||||
.watch(walletsChangeNotifierProvider.select((value) => value.managers));
|
||||
final walletInfos = ref.watch(pWallets).wallets.map((e) => e.info);
|
||||
|
||||
final isDesktop = Util.isDesktop;
|
||||
return ConditionalParent(
|
||||
|
@ -74,7 +75,7 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
|||
condition: isDesktop,
|
||||
builder: (child) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 32),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 32),
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
|
@ -109,18 +110,18 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
|||
.background,
|
||||
child: Column(
|
||||
children: [
|
||||
...managers.map(
|
||||
(manager) => Padding(
|
||||
...walletInfos.map(
|
||||
(info) => Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
key: Key(
|
||||
"syncingPrefsSelectedWalletIdGroupKey_${manager.walletId}"),
|
||||
"syncingPrefsSelectedWalletIdGroupKey_${info.walletId}"),
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
.colorForCoin(manager.coin)
|
||||
.colorForCoin(info.coin)
|
||||
.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
|
@ -131,7 +132,7 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
|||
child: SvgPicture.file(
|
||||
File(
|
||||
ref.watch(
|
||||
coinIconProvider(manager.coin),
|
||||
coinIconProvider(info.coin),
|
||||
),
|
||||
),
|
||||
width: 20,
|
||||
|
@ -149,7 +150,7 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
|||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
manager.walletName,
|
||||
info.name,
|
||||
style:
|
||||
STextStyles.titleBold12(context),
|
||||
),
|
||||
|
@ -158,9 +159,12 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
|||
),
|
||||
Text(
|
||||
ref
|
||||
.watch(pAmountFormatter(
|
||||
manager.coin))
|
||||
.format(manager.balance.total),
|
||||
.watch(
|
||||
pAmountFormatter(info.coin))
|
||||
.format(ref
|
||||
.watch(pWalletBalance(
|
||||
info.walletId))
|
||||
.total),
|
||||
style:
|
||||
STextStyles.itemSubtitle(context),
|
||||
)
|
||||
|
@ -175,7 +179,7 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
|||
.watch(prefsChangeNotifierProvider
|
||||
.select((value) => value
|
||||
.walletIdsSyncOnStartup))
|
||||
.contains(manager.walletId),
|
||||
.contains(info.walletId),
|
||||
onValueChanged: (value) {
|
||||
final syncType = ref
|
||||
.read(prefsChangeNotifierProvider)
|
||||
|
@ -185,22 +189,28 @@ class WalletSyncingOptionsView extends ConsumerWidget {
|
|||
.walletIdsSyncOnStartup
|
||||
.toList();
|
||||
if (value) {
|
||||
ids.add(manager.walletId);
|
||||
ids.add(info.walletId);
|
||||
} else {
|
||||
ids.remove(manager.walletId);
|
||||
ids.remove(info.walletId);
|
||||
}
|
||||
|
||||
final wallet = ref
|
||||
.read(pWallets)
|
||||
.getWallet(info.walletId);
|
||||
|
||||
switch (syncType) {
|
||||
case SyncingType.currentWalletOnly:
|
||||
if (manager.isActiveWallet) {
|
||||
manager.shouldAutoSync = value;
|
||||
if (info.walletId ==
|
||||
ref.read(
|
||||
currentWalletIdProvider)) {
|
||||
wallet.shouldAutoSync = value;
|
||||
}
|
||||
break;
|
||||
case SyncingType
|
||||
.selectedWalletsAtStartup:
|
||||
case SyncingType
|
||||
.allWalletsOnStartup:
|
||||
manager.shouldAutoSync = value;
|
||||
wallet.shouldAutoSync = value;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,13 +17,13 @@ import 'package:flutter_svg/svg.dart';
|
|||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/clipboard_interface.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||
|
@ -98,10 +98,7 @@ class WalletBackupView extends ConsumerWidget {
|
|||
height: 4,
|
||||
),
|
||||
Text(
|
||||
ref
|
||||
.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(walletId)))
|
||||
.walletName,
|
||||
ref.watch(pWalletName(walletId)),
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.label(context).copyWith(
|
||||
fontSize: 12,
|
||||
|
|
|
@ -70,7 +70,7 @@ class _RescanningDialogState extends State<RescanningDialog>
|
|||
child: ConditionalParent(
|
||||
condition: isDesktop,
|
||||
builder: (child) => DesktopDialog(
|
||||
maxHeight: 200,
|
||||
maxHeight: 150,
|
||||
maxWidth: 500,
|
||||
child: child,
|
||||
),
|
||||
|
|
|
@ -22,9 +22,6 @@ import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_net
|
|||
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/sub_widgets/rescanning_dialog.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/monero/monero_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/blocks_remaining_event.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/refresh_percent_changed_event.dart';
|
||||
|
@ -38,11 +35,16 @@ import 'package:stackwallet/utilities/constants.dart';
|
|||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/monero_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/wownero_wallet.dart';
|
||||
import 'package:stackwallet/widgets/animated_text.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/custom_buttons/blue_text_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||
import 'package:stackwallet/widgets/expandable.dart';
|
||||
import 'package:stackwallet/widgets/progress_bar.dart';
|
||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||
|
@ -122,10 +124,8 @@ class _WalletNetworkSettingsViewState
|
|||
Future<void> _attemptRescan() async {
|
||||
if (!Platform.isLinux) await Wakelock.enable();
|
||||
|
||||
int maxUnusedAddressGap = 20;
|
||||
|
||||
const int maxNumberOfIndexesToCheck = 1000;
|
||||
|
||||
try {
|
||||
if (mounted) {
|
||||
unawaited(
|
||||
showDialog<dynamic>(
|
||||
context: context,
|
||||
|
@ -136,19 +136,10 @@ class _WalletNetworkSettingsViewState
|
|||
);
|
||||
|
||||
try {
|
||||
if (ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.coin ==
|
||||
Coin.firo) {
|
||||
maxUnusedAddressGap = 50;
|
||||
}
|
||||
await ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.fullRescan(
|
||||
maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck,
|
||||
final wallet = ref.read(pWallets).getWallet(widget.walletId);
|
||||
|
||||
await wallet.recover(
|
||||
isRescan: true,
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
|
@ -160,7 +151,14 @@ class _WalletNetworkSettingsViewState
|
|||
context: context,
|
||||
useSafeArea: false,
|
||||
barrierDismissible: true,
|
||||
builder: (context) => StackDialog(
|
||||
builder: (context) => ConditionalParent(
|
||||
condition: isDesktop,
|
||||
builder: (child) => DesktopDialog(
|
||||
maxHeight: 150,
|
||||
maxWidth: 500,
|
||||
child: child,
|
||||
),
|
||||
child: StackDialog(
|
||||
title: "Rescan completed",
|
||||
rightButton: TextButton(
|
||||
style: Theme.of(context)
|
||||
|
@ -175,6 +173,7 @@ class _WalletNetworkSettingsViewState
|
|||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
|
@ -208,9 +207,11 @@ class _WalletNetworkSettingsViewState
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} finally {
|
||||
if (!Platform.isLinux) await Wakelock.disable();
|
||||
}
|
||||
}
|
||||
|
||||
String _percentString(double value) {
|
||||
double realPercent = (value * 10000).ceil().clamp(0, 10000) / 100.0;
|
||||
|
@ -257,10 +258,7 @@ class _WalletNetworkSettingsViewState
|
|||
},
|
||||
);
|
||||
|
||||
final coin = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.coin;
|
||||
final coin = ref.read(pWalletCoin(widget.walletId));
|
||||
|
||||
if (coin == Coin.monero || coin == Coin.wownero || coin == Coin.epicCash) {
|
||||
_blocksRemainingSubscription = eventBus.on<BlocksRemainingEvent>().listen(
|
||||
|
@ -319,34 +317,25 @@ class _WalletNetworkSettingsViewState
|
|||
? 430.0
|
||||
: screenWidth - (_padding * 2) - (_boxPadding * 3) - _iconSize;
|
||||
|
||||
final coin = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.coin;
|
||||
final coin = ref.watch(pWalletCoin(widget.walletId));
|
||||
|
||||
if (coin == Coin.monero) {
|
||||
double highestPercent = (ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as MoneroWallet)
|
||||
double highestPercent =
|
||||
(ref.read(pWallets).getWallet(widget.walletId) as MoneroWallet)
|
||||
.highestPercentCached;
|
||||
if (_percent < highestPercent) {
|
||||
_percent = highestPercent.clamp(0.0, 1.0);
|
||||
}
|
||||
} else if (coin == Coin.wownero) {
|
||||
double highestPercent = (ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as WowneroWallet)
|
||||
double highestPercent =
|
||||
(ref.watch(pWallets).getWallet(widget.walletId) as WowneroWallet)
|
||||
.highestPercentCached;
|
||||
if (_percent < highestPercent) {
|
||||
_percent = highestPercent.clamp(0.0, 1.0);
|
||||
}
|
||||
} else if (coin == Coin.epicCash) {
|
||||
double highestPercent = (ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as EpicCashWallet)
|
||||
double highestPercent =
|
||||
(ref.watch(pWallets).getWallet(widget.walletId) as EpiccashWallet)
|
||||
.highestPercent;
|
||||
if (_percent < highestPercent) {
|
||||
_percent = highestPercent.clamp(0.0, 1.0);
|
||||
|
@ -371,11 +360,7 @@ class _WalletNetworkSettingsViewState
|
|||
style: STextStyles.navBarTitle(context),
|
||||
),
|
||||
actions: [
|
||||
if (ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.coin !=
|
||||
Coin.epicCash)
|
||||
if (ref.watch(pWalletCoin(widget.walletId)) != Coin.epicCash)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 10,
|
||||
|
@ -499,10 +484,7 @@ class _WalletNetworkSettingsViewState
|
|||
CustomTextButton(
|
||||
text: "Resync",
|
||||
onTap: () {
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.refresh();
|
||||
ref.read(pWallets).getWallet(widget.walletId).refresh();
|
||||
},
|
||||
),
|
||||
],
|
||||
|
@ -905,7 +887,7 @@ class _WalletNetworkSettingsViewState
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"${ref.watch(walletsChangeNotifierProvider.select((value) => value.getManager(widget.walletId).coin)).prettyName} nodes",
|
||||
"${ref.watch(pWalletCoin(widget.walletId)).prettyName} nodes",
|
||||
textAlign: TextAlign.left,
|
||||
style: isDesktop
|
||||
? STextStyles.desktopTextExtraExtraSmall(context)
|
||||
|
@ -918,10 +900,7 @@ class _WalletNetworkSettingsViewState
|
|||
AddEditNodeView.routeName,
|
||||
arguments: Tuple4(
|
||||
AddEditNodeViewType.add,
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.coin,
|
||||
ref.read(pWalletCoin(widget.walletId)),
|
||||
null,
|
||||
WalletNetworkSettingsView.routeName,
|
||||
),
|
||||
|
@ -934,25 +913,16 @@ class _WalletNetworkSettingsViewState
|
|||
height: isDesktop ? 12 : 8,
|
||||
),
|
||||
NodesList(
|
||||
coin: ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId).coin)),
|
||||
coin: ref.watch(pWalletCoin(widget.walletId)),
|
||||
popBackToRoute: WalletNetworkSettingsView.routeName,
|
||||
),
|
||||
if (isDesktop &&
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.coin !=
|
||||
Coin.epicCash)
|
||||
ref.watch(pWalletCoin(widget.walletId)) != Coin.epicCash)
|
||||
const SizedBox(
|
||||
height: 32,
|
||||
),
|
||||
if (isDesktop &&
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.coin !=
|
||||
Coin.epicCash)
|
||||
ref.watch(pWalletCoin(widget.walletId)) != Coin.epicCash)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 12,
|
||||
|
@ -969,11 +939,7 @@ class _WalletNetworkSettingsViewState
|
|||
),
|
||||
),
|
||||
if (isDesktop &&
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.coin !=
|
||||
Coin.epicCash)
|
||||
ref.watch(pWalletCoin(widget.walletId)) != Coin.epicCash)
|
||||
RoundedWhiteContainer(
|
||||
borderColor: isDesktop
|
||||
? Theme.of(context).extension<StackColors>()!.background
|
||||
|
|
|
@ -30,7 +30,6 @@ import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_set
|
|||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_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';
|
||||
|
@ -40,6 +39,8 @@ 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/wallets/wallet/impl/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
|
||||
|
@ -88,8 +89,9 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
|
|||
void initState() {
|
||||
walletId = widget.walletId;
|
||||
coin = widget.coin;
|
||||
xPubEnabled =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId).hasXPub;
|
||||
// TODO: [prio=low] xpubs
|
||||
// xPubEnabled = ref.read(pWallets).getWallet(walletId).hasXPub;
|
||||
xPubEnabled = false;
|
||||
xpub = "";
|
||||
|
||||
_currentSyncStatus = widget.initialSyncStatus;
|
||||
|
@ -230,10 +232,13 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
|
|||
iconSize: 16,
|
||||
title: "Wallet backup",
|
||||
onPressed: () async {
|
||||
final mnemonic = await ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.mnemonic;
|
||||
final wallet = ref
|
||||
.read(pWallets)
|
||||
.getWallet(widget.walletId);
|
||||
// TODO: [prio=frost] take wallets that don't have a mnemonic into account
|
||||
if (wallet is MnemonicInterface) {
|
||||
final mnemonic =
|
||||
await wallet.getMnemonicAsWords();
|
||||
|
||||
if (mounted) {
|
||||
await Navigator.push(
|
||||
|
@ -244,10 +249,12 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
|
|||
.useMaterialPageRoute,
|
||||
builder: (_) => LockscreenView(
|
||||
routeOnSuccessArguments:
|
||||
Tuple2(walletId, mnemonic),
|
||||
Tuple2(
|
||||
walletId, mnemonic),
|
||||
showBackButton: true,
|
||||
routeOnSuccess:
|
||||
WalletBackupView.routeName,
|
||||
WalletBackupView
|
||||
.routeName,
|
||||
biometricsCancelButtonString:
|
||||
"CANCEL",
|
||||
biometricsLocalizedReason:
|
||||
|
@ -261,6 +268,7 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
|
|||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
|
@ -406,10 +414,11 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
|
|||
builder: (_, ref, __) {
|
||||
return TextButton(
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.isActiveWallet = false;
|
||||
// TODO: [prio=med] needs more thought if this is still required
|
||||
// ref
|
||||
// .read(pWallets)
|
||||
// .getWallet(walletId)
|
||||
// .isActiveWallet = false;
|
||||
ref
|
||||
.read(transactionFilterProvider.state)
|
||||
.state = null;
|
||||
|
@ -461,14 +470,11 @@ class _EpiBoxInfoFormState extends ConsumerState<EpicBoxInfoForm> {
|
|||
final hostController = TextEditingController();
|
||||
final portController = TextEditingController();
|
||||
|
||||
late EpicCashWallet wallet;
|
||||
late EpiccashWallet wallet;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
wallet = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as EpicCashWallet;
|
||||
wallet = ref.read(pWallets).getWallet(widget.walletId) as EpiccashWallet;
|
||||
|
||||
wallet.getEpicBoxConfig().then((EpicBoxConfigModel epicBoxConfig) {
|
||||
hostController.text = epicBoxConfig.host;
|
||||
|
|
|
@ -16,16 +16,14 @@ 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/wallets/wallet/wallet_mixin_interfaces/nano_interface.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';
|
||||
|
@ -51,10 +49,12 @@ class ChangeRepresentativeView extends ConsumerStatefulWidget {
|
|||
static const String routeName = "/changeRepresentative";
|
||||
|
||||
@override
|
||||
ConsumerState<ChangeRepresentativeView> createState() => _XPubViewState();
|
||||
ConsumerState<ChangeRepresentativeView> createState() =>
|
||||
_ChangeRepresentativeViewState();
|
||||
}
|
||||
|
||||
class _XPubViewState extends ConsumerState<ChangeRepresentativeView> {
|
||||
class _ChangeRepresentativeViewState
|
||||
extends ConsumerState<ChangeRepresentativeView> {
|
||||
final _textController = TextEditingController();
|
||||
final _textFocusNode = FocusNode();
|
||||
final bool isDesktop = Util.isDesktop;
|
||||
|
@ -64,24 +64,20 @@ class _XPubViewState extends ConsumerState<ChangeRepresentativeView> {
|
|||
String? representative;
|
||||
|
||||
Future<String> loadRepresentative() async {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
|
||||
final wallet = ref.read(pWallets).getWallet(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();
|
||||
}
|
||||
if (wallet is NanoInterface) {
|
||||
return wallet.getCurrentRepresentative();
|
||||
} else {
|
||||
throw Exception("Unsupported wallet attempted to show representative!");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _save() async {
|
||||
final manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
|
||||
final wallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId) as NanoInterface;
|
||||
|
||||
final changeFuture = manager.coin == Coin.nano
|
||||
? (manager.wallet as NanoWallet).changeRepresentative
|
||||
: (manager.wallet as BananoWallet).changeRepresentative;
|
||||
final changeFuture = wallet.changeRepresentative;
|
||||
|
||||
final result = await showLoading(
|
||||
whileFuture: changeFuture(_textController.text),
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
@ -15,13 +17,14 @@ import 'package:flutter_svg/svg.dart';
|
|||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart';
|
||||
import 'package:stackwallet/pages/home_view/home_view.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/services/coins/manager.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.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/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/stack_dialog.dart';
|
||||
|
@ -29,14 +32,14 @@ import 'package:stackwallet/widgets/stack_dialog.dart';
|
|||
class DeleteWalletRecoveryPhraseView extends ConsumerStatefulWidget {
|
||||
const DeleteWalletRecoveryPhraseView({
|
||||
Key? key,
|
||||
required this.manager,
|
||||
required this.walletId,
|
||||
required this.mnemonic,
|
||||
this.clipboardInterface = const ClipboardWrapper(),
|
||||
}) : super(key: key);
|
||||
|
||||
static const routeName = "/deleteWalletRecoveryPhrase";
|
||||
|
||||
final Manager manager;
|
||||
final String walletId;
|
||||
final List<String> mnemonic;
|
||||
|
||||
final ClipboardInterface clipboardInterface;
|
||||
|
@ -48,13 +51,11 @@ class DeleteWalletRecoveryPhraseView extends ConsumerStatefulWidget {
|
|||
|
||||
class _DeleteWalletRecoveryPhraseViewState
|
||||
extends ConsumerState<DeleteWalletRecoveryPhraseView> {
|
||||
late Manager _manager;
|
||||
late List<String> _mnemonic;
|
||||
late ClipboardInterface _clipboardInterface;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_manager = widget.manager;
|
||||
_mnemonic = widget.mnemonic;
|
||||
_clipboardInterface = widget.clipboardInterface;
|
||||
super.initState();
|
||||
|
@ -90,15 +91,18 @@ class _DeleteWalletRecoveryPhraseViewState
|
|||
.topNavIconPrimary,
|
||||
),
|
||||
onPressed: () async {
|
||||
final words = await _manager.mnemonic;
|
||||
await _clipboardInterface
|
||||
.setData(ClipboardData(text: words.join(" ")));
|
||||
.setData(ClipboardData(text: _mnemonic.join(" ")));
|
||||
if (mounted) {
|
||||
unawaited(
|
||||
showFloatingFlushBar(
|
||||
type: FlushBarType.info,
|
||||
message: "Copied to clipboard",
|
||||
iconAsset: Assets.svg.copy,
|
||||
context: context,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@ -114,7 +118,7 @@ class _DeleteWalletRecoveryPhraseViewState
|
|||
height: 4,
|
||||
),
|
||||
Text(
|
||||
_manager.walletName,
|
||||
ref.watch(pWalletName(widget.walletId)),
|
||||
textAlign: TextAlign.center,
|
||||
style: STextStyles.label(context).copyWith(
|
||||
fontSize: 12,
|
||||
|
@ -192,22 +196,15 @@ class _DeleteWalletRecoveryPhraseViewState
|
|||
.extension<StackColors>()!
|
||||
.getPrimaryEnabledButtonStyle(context),
|
||||
onPressed: () async {
|
||||
final walletId = _manager.walletId;
|
||||
final walletsInstance =
|
||||
ref.read(walletsChangeNotifierProvider);
|
||||
await ref
|
||||
.read(walletsServiceChangeNotifierProvider)
|
||||
.deleteWallet(_manager.walletName, true);
|
||||
await ref.read(pWallets).deleteWallet(
|
||||
ref.read(pWalletInfo(widget.walletId)),
|
||||
ref.read(secureStoreProvider),
|
||||
);
|
||||
|
||||
if (mounted) {
|
||||
Navigator.of(context).popUntil(
|
||||
ModalRoute.withName(HomeView.routeName));
|
||||
}
|
||||
|
||||
// wait for widget tree to dispose of any widgets watching the manager
|
||||
await Future<void>.delayed(
|
||||
const Duration(seconds: 1));
|
||||
walletsInstance.removeWallet(walletId: walletId);
|
||||
},
|
||||
child: Text(
|
||||
"Ok",
|
||||
|
|
|
@ -14,10 +14,10 @@ import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_set
|
|||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class DeleteWalletWarningView extends ConsumerWidget {
|
||||
const DeleteWalletWarningView({
|
||||
|
@ -99,17 +99,18 @@ class DeleteWalletWarningView extends ConsumerWidget {
|
|||
.extension<StackColors>()!
|
||||
.getPrimaryEnabledButtonStyle(context),
|
||||
onPressed: () async {
|
||||
final manager = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId);
|
||||
final mnemonic = await manager.mnemonic;
|
||||
Navigator.of(context).pushNamed(
|
||||
final wallet = ref.read(pWallets).getWallet(walletId);
|
||||
final mnemonic =
|
||||
await (wallet as MnemonicInterface).getMnemonicAsWords();
|
||||
if (context.mounted) {
|
||||
await Navigator.of(context).pushNamed(
|
||||
DeleteWalletRecoveryPhraseView.routeName,
|
||||
arguments: Tuple2(
|
||||
manager,
|
||||
mnemonic,
|
||||
arguments: (
|
||||
walletId: walletId,
|
||||
mnemonicWords: mnemonic,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
"View Backup Key",
|
||||
|
|
|
@ -8,14 +8,17 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||
|
@ -47,8 +50,7 @@ class _RenameWalletViewState extends ConsumerState<RenameWalletView> {
|
|||
void initState() {
|
||||
_controller = TextEditingController();
|
||||
walletId = widget.walletId;
|
||||
originalName =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(walletId).walletName;
|
||||
originalName = ref.read(pWalletName(walletId));
|
||||
_controller.text = originalName;
|
||||
super.initState();
|
||||
}
|
||||
|
@ -126,32 +128,43 @@ class _RenameWalletViewState extends ConsumerState<RenameWalletView> {
|
|||
.getPrimaryEnabledButtonStyle(context),
|
||||
onPressed: () async {
|
||||
final newName = _controller.text;
|
||||
final success = await ref
|
||||
.read(walletsServiceChangeNotifierProvider)
|
||||
.renameWallet(
|
||||
from: originalName,
|
||||
to: newName,
|
||||
shouldNotifyListeners: true,
|
||||
);
|
||||
|
||||
if (success) {
|
||||
ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(walletId)
|
||||
.walletName = newName;
|
||||
String? errMessage;
|
||||
try {
|
||||
await ref.read(pWalletInfo(walletId)).updateName(
|
||||
newName: newName,
|
||||
isar: ref.read(mainDBProvider).isar,
|
||||
);
|
||||
} catch (e) {
|
||||
if (e
|
||||
.toString()
|
||||
.contains("Empty wallet name not allowed!")) {
|
||||
errMessage = "Empty wallet name not allowed.";
|
||||
} else {
|
||||
errMessage = e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
if (errMessage == null) {
|
||||
Navigator.of(context).pop();
|
||||
unawaited(
|
||||
showFloatingFlushBar(
|
||||
type: FlushBarType.success,
|
||||
message: "Wallet renamed",
|
||||
context: context,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
unawaited(
|
||||
showFloatingFlushBar(
|
||||
type: FlushBarType.warning,
|
||||
message: "Wallet named \"$newName\" already exists",
|
||||
context: context,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
"Save",
|
||||
|
|
|
@ -13,11 +13,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:stackwallet/pages/pinpad_views/lock_screen_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/providers/providers.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||
|
@ -111,7 +111,7 @@ class WalletSettingsWalletSettingsView extends ConsumerWidget {
|
|||
context: context,
|
||||
builder: (_) => StackDialog(
|
||||
title:
|
||||
"Do you want to delete ${ref.read(walletsChangeNotifierProvider).getManager(walletId).walletName}?",
|
||||
"Do you want to delete ${ref.read(pWalletName(walletId))}?",
|
||||
leftButton: TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
|
|
|
@ -17,12 +17,12 @@ import 'package:flutter_svg/svg.dart';
|
|||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
import 'package:stackwallet/notifications/show_flush_bar.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/coins/manager.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/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.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';
|
||||
|
@ -53,15 +53,14 @@ class _XPubViewState extends ConsumerState<XPubView> {
|
|||
final bool isDesktop = Util.isDesktop;
|
||||
|
||||
late ClipboardInterface _clipboardInterface;
|
||||
late final Manager manager;
|
||||
late final Wallet wallet;
|
||||
|
||||
String? xpub;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_clipboardInterface = widget.clipboardInterface;
|
||||
manager =
|
||||
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
|
||||
wallet = ref.read(pWallets).getWallet(widget.walletId);
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
@ -153,7 +152,7 @@ class _XPubViewState extends ConsumerState<XPubView> {
|
|||
left: 32,
|
||||
),
|
||||
child: Text(
|
||||
"${manager.walletName} xPub",
|
||||
"${wallet.info.name} xPub",
|
||||
style: STextStyles.desktopH2(context),
|
||||
),
|
||||
),
|
||||
|
@ -186,7 +185,8 @@ class _XPubViewState extends ConsumerState<XPubView> {
|
|||
child: child,
|
||||
),
|
||||
child: FutureBuilder(
|
||||
future: manager.xpub,
|
||||
future: Future(() => "fixme"),
|
||||
// future: wallet.xpub,
|
||||
builder: (context, AsyncSnapshot<String> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasData) {
|
||||
|
|
|
@ -12,6 +12,8 @@ import 'package:stackwallet/themes/stack_colors.dart';
|
|||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.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';
|
||||
|
@ -131,12 +133,13 @@ class _FiroRescanRecoveryErrorViewState
|
|||
.topNavIconPrimary,
|
||||
),
|
||||
onPressed: () async {
|
||||
final walletName =
|
||||
ref.read(pWalletName(widget.walletId));
|
||||
await showDialog<void>(
|
||||
barrierDismissible: true,
|
||||
context: context,
|
||||
builder: (_) => StackDialog(
|
||||
title:
|
||||
"Do you want to delete ${ref.read(walletsChangeNotifierProvider).getManager(widget.walletId).walletName}?",
|
||||
title: "Do you want to delete $walletName?",
|
||||
leftButton: TextButton(
|
||||
style: Theme.of(context)
|
||||
.extension<StackColors>()!
|
||||
|
@ -253,10 +256,11 @@ class _FiroRescanRecoveryErrorViewState
|
|||
),
|
||||
);
|
||||
} else {
|
||||
final mnemonic = await ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.mnemonic;
|
||||
final wallet =
|
||||
ref.read(pWallets).getWallet(widget.walletId);
|
||||
// TODO: [prio=low] take wallets that don't have a mnemonic into account
|
||||
if (wallet is MnemonicInterface) {
|
||||
final mnemonic = await wallet.getMnemonicAsWords();
|
||||
|
||||
if (mounted) {
|
||||
await Navigator.push(
|
||||
|
@ -281,6 +285,7 @@ class _FiroRescanRecoveryErrorViewState
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
|
|
|
@ -15,13 +15,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart';
|
||||
import 'package:stackwallet/pages/token_view/sub_widgets/my_tokens_list.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.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';
|
||||
|
@ -89,8 +88,7 @@ class _MyTokensViewState extends ConsumerState<MyTokensView> {
|
|||
),
|
||||
title: Text(
|
||||
"${ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value.getManager(widget.walletId).walletName),
|
||||
pWalletName(widget.walletId),
|
||||
)} Tokens",
|
||||
style: STextStyles.navBarTitle(context),
|
||||
),
|
||||
|
@ -233,11 +231,7 @@ class _MyTokensViewState extends ConsumerState<MyTokensView> {
|
|||
child: MyTokensList(
|
||||
walletId: widget.walletId,
|
||||
searchTerm: _searchString,
|
||||
tokenContracts: ref
|
||||
.watch(walletsChangeNotifierProvider.select((value) => value
|
||||
.getManager(widget.walletId)
|
||||
.wallet as EthereumWallet))
|
||||
.getWalletTokenContractAddresses(),
|
||||
tokenContracts: ref.watch(pWalletTokenAddresses(widget.walletId)),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -8,17 +8,16 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart';
|
||||
import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||
import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart';
|
||||
import 'package:stackwallet/providers/global/secure_store_provider.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
|
||||
import 'package:stackwallet/services/ethereum/cached_eth_token_balance.dart';
|
||||
import 'package:stackwallet/services/ethereum/ethereum_token_service.dart';
|
||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
|
@ -26,6 +25,12 @@ 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/wallets/isar/providers/eth/current_token_wallet_provider.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/eth/token_balance_provider.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/impl/sub_wallets/eth_token_wallet.dart';
|
||||
import 'package:stackwallet/wallets/wallet/wallet.dart';
|
||||
import 'package:stackwallet/widgets/desktop/primary_button.dart';
|
||||
import 'package:stackwallet/widgets/dialogs/basic_dialog.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/eth_token_icon.dart';
|
||||
|
@ -55,7 +60,7 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
|
|||
WidgetRef ref,
|
||||
) async {
|
||||
try {
|
||||
await ref.read(tokenServiceProvider)!.initialize();
|
||||
await ref.read(pCurrentTokenWallet)!.init();
|
||||
return true;
|
||||
} catch (_) {
|
||||
await showDialog<void>(
|
||||
|
@ -81,17 +86,14 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
|
|||
}
|
||||
|
||||
void _onPressed() async {
|
||||
ref.read(tokenServiceStateProvider.state).state = EthTokenWallet(
|
||||
token: widget.token,
|
||||
secureStore: ref.read(secureStoreProvider),
|
||||
ethWallet: ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as EthereumWallet,
|
||||
tracker: TransactionNotificationTracker(
|
||||
walletId: widget.walletId,
|
||||
),
|
||||
);
|
||||
final old = ref.read(tokenServiceStateProvider);
|
||||
// exit previous if there is one
|
||||
unawaited(old?.exit());
|
||||
ref.read(tokenServiceStateProvider.state).state = Wallet.loadTokenWallet(
|
||||
ethWallet:
|
||||
ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet,
|
||||
contract: widget.token,
|
||||
) as EthTokenWallet;
|
||||
|
||||
final success = await showLoading<bool>(
|
||||
whileFuture: _loadTokenWallet(context, ref),
|
||||
|
@ -105,6 +107,7 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
|
|||
}
|
||||
|
||||
if (mounted) {
|
||||
unawaited(ref.read(pCurrentTokenWallet)!.refresh());
|
||||
await Navigator.of(context).pushNamed(
|
||||
isDesktop ? DesktopTokenView.routeName : TokenView.routeName,
|
||||
arguments: widget.walletId,
|
||||
|
@ -117,14 +120,14 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
|
|||
cachedBalance = CachedEthTokenBalance(widget.walletId, widget.token);
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
final address = await ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.currentReceivingAddress;
|
||||
await cachedBalance.fetchAndUpdateCachedBalance(address);
|
||||
if (mounted) {
|
||||
final address = ref.read(pWalletReceivingAddress(widget.walletId));
|
||||
await cachedBalance.fetchAndUpdateCachedBalance(
|
||||
address, ref.read(mainDBProvider));
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
super.initState();
|
||||
|
@ -176,7 +179,14 @@ class _MyTokenSelectItemState extends ConsumerState<MyTokenSelectItem> {
|
|||
const Spacer(),
|
||||
Text(
|
||||
ref.watch(pAmountFormatter(Coin.ethereum)).format(
|
||||
cachedBalance.getCachedBalance().total,
|
||||
ref
|
||||
.watch(pTokenBalance(
|
||||
(
|
||||
walletId: widget.walletId,
|
||||
contractAddress: widget.token.address
|
||||
),
|
||||
))
|
||||
.total,
|
||||
ethContract: widget.token,
|
||||
),
|
||||
style: isDesktop
|
||||
|
|
|
@ -19,12 +19,10 @@ import 'package:stackwallet/pages/buy_view/buy_in_wallet_view.dart';
|
|||
import 'package:stackwallet/pages/exchange_view/wallet_initiated_exchange_view.dart';
|
||||
import 'package:stackwallet/pages/receive_view/receive_view.dart';
|
||||
import 'package:stackwallet/pages/send_view/token_send_view.dart';
|
||||
import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_refresh_button.dart';
|
||||
import 'package:stackwallet/providers/global/locale_provider.dart';
|
||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||
import 'package:stackwallet/providers/global/price_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/themes/theme_providers.dart';
|
||||
|
@ -34,6 +32,9 @@ 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';
|
||||
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/eth/token_balance_provider.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
|
||||
import 'package:stackwallet/widgets/conditional_parent.dart';
|
||||
import 'package:stackwallet/widgets/rounded_container.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
@ -51,9 +52,9 @@ class TokenSummary extends ConsumerWidget {
|
|||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final token =
|
||||
ref.watch(tokenServiceProvider.select((value) => value!.tokenContract));
|
||||
final balance =
|
||||
ref.watch(tokenServiceProvider.select((value) => value!.balance));
|
||||
ref.watch(pCurrentTokenWallet.select((value) => value!.tokenContract));
|
||||
final balance = ref.watch(
|
||||
pTokenBalance((walletId: walletId, contractAddress: token.address)));
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
|
@ -78,9 +79,7 @@ class TokenSummary extends ConsumerWidget {
|
|||
),
|
||||
Text(
|
||||
ref.watch(
|
||||
walletsChangeNotifierProvider.select(
|
||||
(value) => value.getManager(walletId).walletName,
|
||||
),
|
||||
pWalletName(walletId),
|
||||
),
|
||||
style: STextStyles.w500_12(context).copyWith(
|
||||
color: Theme.of(context)
|
||||
|
@ -159,7 +158,7 @@ class TokenSummary extends ConsumerWidget {
|
|||
walletId: walletId,
|
||||
initialSyncStatus: initialSyncStatus,
|
||||
tokenContractAddress: ref.watch(
|
||||
tokenServiceProvider.select(
|
||||
pCurrentTokenWallet.select(
|
||||
(value) => value!.tokenContract.address,
|
||||
),
|
||||
),
|
||||
|
@ -366,10 +365,11 @@ class CoinTickerTag extends ConsumerWidget {
|
|||
radiusMultiplier: 0.25,
|
||||
color: Theme.of(context).extension<StackColors>()!.ethTagBG,
|
||||
child: Text(
|
||||
ref.watch(
|
||||
walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(walletId).coin.ticker),
|
||||
),
|
||||
ref
|
||||
.watch(
|
||||
pWalletCoin(walletId),
|
||||
)
|
||||
.ticker,
|
||||
style: STextStyles.w600_12(context).copyWith(
|
||||
color: Theme.of(context).extension<StackColors>()!.ethTagText,
|
||||
),
|
||||
|
|
|
@ -12,24 +12,18 @@ import 'dart:async';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||
import 'package:stackwallet/pages/exchange_view/trade_details_view.dart';
|
||||
import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
|
||||
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/sub_widgets/no_transactions_found.dart';
|
||||
import 'package:stackwallet/providers/global/trades_service_provider.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/transaction_views/tx_v2/transaction_v2_list_item.dart';
|
||||
import 'package:stackwallet/providers/db/main_db_provider.dart';
|
||||
import 'package:stackwallet/providers/global/wallets_provider.dart';
|
||||
import 'package:stackwallet/route_generator.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/utilities/util.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
|
||||
import 'package:stackwallet/widgets/loading_indicator.dart';
|
||||
import 'package:stackwallet/widgets/trade_card.dart';
|
||||
import 'package:stackwallet/widgets/transaction_card.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class TokenTransactionsList extends ConsumerStatefulWidget {
|
||||
const TokenTransactionsList({
|
||||
|
@ -45,9 +39,13 @@ class TokenTransactionsList extends ConsumerStatefulWidget {
|
|||
}
|
||||
|
||||
class _TransactionsListState extends ConsumerState<TokenTransactionsList> {
|
||||
//
|
||||
late final int minConfirms;
|
||||
|
||||
bool _hasLoaded = false;
|
||||
List<Transaction> _transactions2 = [];
|
||||
List<TransactionV2> _transactions = [];
|
||||
|
||||
late final StreamSubscription<List<TransactionV2>> _subscription;
|
||||
late final QueryBuilder<TransactionV2, TransactionV2, QAfterSortBy> _query;
|
||||
|
||||
BorderRadius get _borderRadiusFirst {
|
||||
return BorderRadius.only(
|
||||
|
@ -71,157 +69,54 @@ class _TransactionsListState extends ConsumerState<TokenTransactionsList> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget itemBuilder(
|
||||
BuildContext context,
|
||||
Transaction tx,
|
||||
BorderRadius? radius,
|
||||
Coin coin,
|
||||
) {
|
||||
final matchingTrades = ref
|
||||
.read(tradesServiceProvider)
|
||||
.trades
|
||||
.where((e) => e.payInTxid == tx.txid || e.payOutTxid == tx.txid);
|
||||
@override
|
||||
void initState() {
|
||||
minConfirms = ref
|
||||
.read(pWallets)
|
||||
.getWallet(widget.walletId)
|
||||
.cryptoCurrency
|
||||
.minConfirms;
|
||||
|
||||
if (tx.type == TransactionType.outgoing && matchingTrades.isNotEmpty) {
|
||||
final trade = matchingTrades.first;
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
borderRadius: radius,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TransactionCard(
|
||||
// this may mess with combined firo transactions
|
||||
key: tx.isConfirmed(
|
||||
ref.watch(walletsChangeNotifierProvider.select((value) =>
|
||||
value.getManager(widget.walletId).currentHeight)),
|
||||
coin.requiredConfirmations)
|
||||
? Key(tx.txid + tx.type.name + tx.address.value.toString())
|
||||
: UniqueKey(), //
|
||||
transaction: tx,
|
||||
walletId: widget.walletId,
|
||||
),
|
||||
TradeCard(
|
||||
// this may mess with combined firo transactions
|
||||
key: Key(tx.txid +
|
||||
tx.type.name +
|
||||
tx.address.value.toString() +
|
||||
trade.uuid), //
|
||||
trade: trade,
|
||||
onTap: () async {
|
||||
final walletName = ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.walletName;
|
||||
if (Util.isDesktop) {
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
builder: (context) => Navigator(
|
||||
initialRoute: TradeDetailsView.routeName,
|
||||
onGenerateRoute: RouteGenerator.generateRoute,
|
||||
onGenerateInitialRoutes: (_, __) {
|
||||
return [
|
||||
FadePageRoute(
|
||||
DesktopDialog(
|
||||
maxHeight: null,
|
||||
maxWidth: 580,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 32,
|
||||
bottom: 16,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Trade details",
|
||||
style: STextStyles.desktopH3(context),
|
||||
),
|
||||
DesktopDialogCloseButton(
|
||||
onPressedOverride: Navigator.of(
|
||||
context,
|
||||
rootNavigator: true,
|
||||
).pop,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: TradeDetailsView(
|
||||
tradeId: trade.tradeId,
|
||||
transactionIfSentFromStack: tx,
|
||||
walletName: walletName,
|
||||
walletId: widget.walletId,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const RouteSettings(
|
||||
name: TradeDetailsView.routeName,
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
unawaited(
|
||||
Navigator.of(context).pushNamed(
|
||||
TradeDetailsView.routeName,
|
||||
arguments: Tuple4(
|
||||
trade.tradeId,
|
||||
tx,
|
||||
widget.walletId,
|
||||
walletName,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).extension<StackColors>()!.popupBG,
|
||||
borderRadius: radius,
|
||||
),
|
||||
child: TransactionCard(
|
||||
// this may mess with combined firo transactions
|
||||
key: tx.isConfirmed(
|
||||
ref.watch(walletsChangeNotifierProvider.select((value) =>
|
||||
value.getManager(widget.walletId).currentHeight)),
|
||||
coin.requiredConfirmations)
|
||||
? Key(tx.txid + tx.type.name + tx.address.value.toString())
|
||||
: UniqueKey(),
|
||||
transaction: tx,
|
||||
walletId: widget.walletId,
|
||||
),
|
||||
);
|
||||
_query = ref
|
||||
.read(mainDBProvider)
|
||||
.isar
|
||||
.transactionV2s
|
||||
.where()
|
||||
.walletIdEqualTo(widget.walletId)
|
||||
.filter()
|
||||
.subTypeEqualTo(TransactionSubType.ethToken)
|
||||
.and()
|
||||
.contractAddressEqualTo(
|
||||
ref.read(pCurrentTokenWallet)!.tokenContract.address)
|
||||
.sortByTimestampDesc();
|
||||
|
||||
_subscription = _query.watch().listen((event) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
setState(() {
|
||||
_transactions = event;
|
||||
});
|
||||
});
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_subscription.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final manager = ref.watch(walletsChangeNotifierProvider
|
||||
.select((value) => value.getManager(widget.walletId)));
|
||||
final wallet =
|
||||
ref.watch(pWallets.select((value) => value.getWallet(widget.walletId)));
|
||||
|
||||
return FutureBuilder(
|
||||
future: ref
|
||||
.watch(tokenServiceProvider.select((value) => value!.transactions)),
|
||||
builder: (fbContext, AsyncSnapshot<List<Transaction>> snapshot) {
|
||||
future: _query.findAll(),
|
||||
builder: (fbContext, AsyncSnapshot<List<TransactionV2>> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasData) {
|
||||
_transactions2 = snapshot.data!;
|
||||
_transactions = snapshot.data!;
|
||||
_hasLoaded = true;
|
||||
}
|
||||
if (!_hasLoaded) {
|
||||
|
@ -240,31 +135,35 @@ class _TransactionsListState extends ConsumerState<TokenTransactionsList> {
|
|||
],
|
||||
);
|
||||
}
|
||||
if (_transactions2.isEmpty) {
|
||||
if (_transactions.isEmpty) {
|
||||
return const NoTransActionsFound();
|
||||
} else {
|
||||
_transactions2.sort((a, b) => b.timestamp - a.timestamp);
|
||||
_transactions.sort((a, b) => b.timestamp - a.timestamp);
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
if (!ref.read(tokenServiceProvider)!.isRefreshing) {
|
||||
unawaited(ref.read(tokenServiceProvider)!.refresh());
|
||||
if (!ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked) {
|
||||
unawaited(ref.read(pCurrentTokenWallet)!.refresh());
|
||||
}
|
||||
},
|
||||
child: Util.isDesktop
|
||||
? ListView.separated(
|
||||
itemBuilder: (context, index) {
|
||||
BorderRadius? radius;
|
||||
if (_transactions2.length == 1) {
|
||||
if (_transactions.length == 1) {
|
||||
radius = BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
);
|
||||
} else if (index == _transactions2.length - 1) {
|
||||
} else if (index == _transactions.length - 1) {
|
||||
radius = _borderRadiusLast;
|
||||
} else if (index == 0) {
|
||||
radius = _borderRadiusFirst;
|
||||
}
|
||||
final tx = _transactions2[index];
|
||||
return itemBuilder(context, tx, radius, manager.coin);
|
||||
final tx = _transactions[index];
|
||||
return TxListItem(
|
||||
tx: tx,
|
||||
coin: wallet.info.coin,
|
||||
radius: radius,
|
||||
);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return Container(
|
||||
|
@ -275,23 +174,27 @@ class _TransactionsListState extends ConsumerState<TokenTransactionsList> {
|
|||
.background,
|
||||
);
|
||||
},
|
||||
itemCount: _transactions2.length,
|
||||
itemCount: _transactions.length,
|
||||
)
|
||||
: ListView.builder(
|
||||
itemCount: _transactions2.length,
|
||||
itemCount: _transactions.length,
|
||||
itemBuilder: (context, index) {
|
||||
BorderRadius? radius;
|
||||
if (_transactions2.length == 1) {
|
||||
if (_transactions.length == 1) {
|
||||
radius = BorderRadius.circular(
|
||||
Constants.size.circularBorderRadius,
|
||||
);
|
||||
} else if (index == _transactions2.length - 1) {
|
||||
} else if (index == _transactions.length - 1) {
|
||||
radius = _borderRadiusLast;
|
||||
} else if (index == 0) {
|
||||
radius = _borderRadiusFirst;
|
||||
}
|
||||
final tx = _transactions2[index];
|
||||
return itemBuilder(context, tx, radius, manager.coin);
|
||||
final tx = _transactions[index];
|
||||
return TxListItem(
|
||||
tx: tx,
|
||||
coin: wallet.info.coin,
|
||||
radius: radius,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
@ -15,23 +15,19 @@ import 'package:flutter_svg/svg.dart';
|
|||
import 'package:stackwallet/pages/token_view/sub_widgets/token_summary.dart';
|
||||
import 'package:stackwallet/pages/token_view/sub_widgets/token_transaction_list_widget.dart';
|
||||
import 'package:stackwallet/pages/token_view/token_contract_details_view.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/transaction_views/all_transactions_view.dart';
|
||||
import 'package:stackwallet/services/ethereum/ethereum_token_service.dart';
|
||||
import 'package:stackwallet/pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
|
||||
import 'package:stackwallet/themes/stack_colors.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/text_styles.dart';
|
||||
import 'package:stackwallet/wallets/isar/providers/eth/current_token_wallet_provider.dart';
|
||||
import 'package:stackwallet/widgets/background.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||
import 'package:stackwallet/widgets/icon_widgets/eth_token_icon.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
final tokenServiceStateProvider = StateProvider<EthTokenWallet?>((ref) => null);
|
||||
final tokenServiceProvider = ChangeNotifierProvider<EthTokenWallet?>(
|
||||
(ref) => ref.watch(tokenServiceStateProvider));
|
||||
|
||||
/// [eventBus] should only be set during testing
|
||||
class TokenView extends ConsumerStatefulWidget {
|
||||
const TokenView({
|
||||
|
@ -56,7 +52,7 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
|||
|
||||
@override
|
||||
void initState() {
|
||||
initialSyncStatus = ref.read(tokenServiceProvider)!.isRefreshing
|
||||
initialSyncStatus = ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked
|
||||
? WalletSyncStatus.syncing
|
||||
: WalletSyncStatus.synced;
|
||||
super.initState();
|
||||
|
@ -105,7 +101,7 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
|||
children: [
|
||||
EthTokenIcon(
|
||||
contractAddress: ref.watch(
|
||||
tokenServiceProvider.select(
|
||||
pCurrentTokenWallet.select(
|
||||
(value) => value!.tokenContract.address,
|
||||
),
|
||||
),
|
||||
|
@ -116,7 +112,7 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
|||
),
|
||||
Flexible(
|
||||
child: Text(
|
||||
ref.watch(tokenServiceProvider
|
||||
ref.watch(pCurrentTokenWallet
|
||||
.select((value) => value!.tokenContract.name)),
|
||||
style: STextStyles.navBarTitle(context),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
|
@ -145,7 +141,7 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
|||
Navigator.of(context).pushNamed(
|
||||
TokenContractDetailsView.routeName,
|
||||
arguments: Tuple2(
|
||||
ref.watch(tokenServiceProvider
|
||||
ref.watch(pCurrentTokenWallet
|
||||
.select((value) => value!.tokenContract.address)),
|
||||
widget.walletId,
|
||||
),
|
||||
|
@ -190,10 +186,14 @@ class _TokenViewState extends ConsumerState<TokenView> {
|
|||
text: "See all",
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
AllTransactionsView.routeName,
|
||||
AllTransactionsV2View.routeName,
|
||||
arguments: (
|
||||
walletId: widget.walletId,
|
||||
isTokens: true,
|
||||
contractAddress: ref.watch(
|
||||
pCurrentTokenWallet.select(
|
||||
(value) => value!.tokenContract.address,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue