mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-21 06:38:52 +00:00
Merge pull request #527 from cypherstack/custom_block_explorers
Custom block explorers
This commit is contained in:
commit
58ce2fb357
14 changed files with 1254 additions and 1 deletions
|
@ -2,6 +2,7 @@ import 'package:decimal/decimal.dart';
|
||||||
import 'package:flutter_native_splash/cli_commands.dart';
|
import 'package:flutter_native_splash/cli_commands.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/exceptions/main_db/main_db_exception.dart';
|
import 'package:stackwallet/exceptions/main_db/main_db_exception.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/block_explorer.dart';
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
@ -33,6 +34,7 @@ class MainDB {
|
||||||
AddressSchema,
|
AddressSchema,
|
||||||
AddressLabelSchema,
|
AddressLabelSchema,
|
||||||
EthContractSchema,
|
EthContractSchema,
|
||||||
|
TransactionBlockExplorerSchema,
|
||||||
],
|
],
|
||||||
directory: (await StackFileSystem.applicationIsarDirectory()).path,
|
directory: (await StackFileSystem.applicationIsarDirectory()).path,
|
||||||
// inspector: kDebugMode,
|
// inspector: kDebugMode,
|
||||||
|
@ -43,6 +45,25 @@ class MainDB {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tx block explorers
|
||||||
|
TransactionBlockExplorer? getTransactionBlockExplorer({required Coin coin}) {
|
||||||
|
return isar.transactionBlockExplorers
|
||||||
|
.where()
|
||||||
|
.tickerEqualTo(coin.ticker)
|
||||||
|
.findFirstSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> putTransactionBlockExplorer(
|
||||||
|
TransactionBlockExplorer explorer) async {
|
||||||
|
try {
|
||||||
|
return await isar.writeTxn(() async {
|
||||||
|
return await isar.transactionBlockExplorers.put(explorer);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw MainDBException("failed putTransactionBlockExplorer: $explorer", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// addresses
|
// addresses
|
||||||
QueryBuilder<Address, Address, QAfterWhereClause> getAddresses(
|
QueryBuilder<Address, Address, QAfterWhereClause> getAddresses(
|
||||||
String walletId) =>
|
String walletId) =>
|
||||||
|
|
35
lib/models/isar/models/block_explorer.dart
Normal file
35
lib/models/isar/models/block_explorer.dart
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import 'package:isar/isar.dart';
|
||||||
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
|
||||||
|
part 'block_explorer.g.dart';
|
||||||
|
|
||||||
|
@collection
|
||||||
|
class TransactionBlockExplorer {
|
||||||
|
TransactionBlockExplorer({
|
||||||
|
required this.ticker,
|
||||||
|
required this.url,
|
||||||
|
});
|
||||||
|
|
||||||
|
Id id = Isar.autoIncrement;
|
||||||
|
|
||||||
|
@Index(unique: true, replace: true)
|
||||||
|
late final String ticker;
|
||||||
|
|
||||||
|
late final String url;
|
||||||
|
|
||||||
|
@ignore
|
||||||
|
Coin? get coin {
|
||||||
|
try {
|
||||||
|
return coinFromTickerCaseInsensitive(ticker);
|
||||||
|
} catch (_) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri? getUrlFor({required String txid}) => Uri.tryParse(
|
||||||
|
url.replaceFirst(
|
||||||
|
"%5BTXID%5D",
|
||||||
|
txid,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
764
lib/models/isar/models/block_explorer.g.dart
Normal file
764
lib/models/isar/models/block_explorer.g.dart
Normal file
|
@ -0,0 +1,764 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'block_explorer.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// IsarCollectionGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: duplicate_ignore, non_constant_identifier_names, constant_identifier_names, invalid_use_of_protected_member, unnecessary_cast, prefer_const_constructors, lines_longer_than_80_chars, require_trailing_commas, inference_failure_on_function_invocation, unnecessary_parenthesis, unnecessary_raw_strings, unnecessary_null_checks, join_return_with_assignment, prefer_final_locals, avoid_js_rounded_ints, avoid_positional_boolean_parameters
|
||||||
|
|
||||||
|
extension GetTransactionBlockExplorerCollection on Isar {
|
||||||
|
IsarCollection<TransactionBlockExplorer> get transactionBlockExplorers =>
|
||||||
|
this.collection();
|
||||||
|
}
|
||||||
|
|
||||||
|
const TransactionBlockExplorerSchema = CollectionSchema(
|
||||||
|
name: r'TransactionBlockExplorer',
|
||||||
|
id: 4209077296238413906,
|
||||||
|
properties: {
|
||||||
|
r'ticker': PropertySchema(
|
||||||
|
id: 0,
|
||||||
|
name: r'ticker',
|
||||||
|
type: IsarType.string,
|
||||||
|
),
|
||||||
|
r'url': PropertySchema(
|
||||||
|
id: 1,
|
||||||
|
name: r'url',
|
||||||
|
type: IsarType.string,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
estimateSize: _transactionBlockExplorerEstimateSize,
|
||||||
|
serialize: _transactionBlockExplorerSerialize,
|
||||||
|
deserialize: _transactionBlockExplorerDeserialize,
|
||||||
|
deserializeProp: _transactionBlockExplorerDeserializeProp,
|
||||||
|
idName: r'id',
|
||||||
|
indexes: {
|
||||||
|
r'ticker': IndexSchema(
|
||||||
|
id: -8264639257510259247,
|
||||||
|
name: r'ticker',
|
||||||
|
unique: true,
|
||||||
|
replace: true,
|
||||||
|
properties: [
|
||||||
|
IndexPropertySchema(
|
||||||
|
name: r'ticker',
|
||||||
|
type: IndexType.hash,
|
||||||
|
caseSensitive: true,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
},
|
||||||
|
links: {},
|
||||||
|
embeddedSchemas: {},
|
||||||
|
getId: _transactionBlockExplorerGetId,
|
||||||
|
getLinks: _transactionBlockExplorerGetLinks,
|
||||||
|
attach: _transactionBlockExplorerAttach,
|
||||||
|
version: '3.0.5',
|
||||||
|
);
|
||||||
|
|
||||||
|
int _transactionBlockExplorerEstimateSize(
|
||||||
|
TransactionBlockExplorer object,
|
||||||
|
List<int> offsets,
|
||||||
|
Map<Type, List<int>> allOffsets,
|
||||||
|
) {
|
||||||
|
var bytesCount = offsets.last;
|
||||||
|
bytesCount += 3 + object.ticker.length * 3;
|
||||||
|
bytesCount += 3 + object.url.length * 3;
|
||||||
|
return bytesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _transactionBlockExplorerSerialize(
|
||||||
|
TransactionBlockExplorer object,
|
||||||
|
IsarWriter writer,
|
||||||
|
List<int> offsets,
|
||||||
|
Map<Type, List<int>> allOffsets,
|
||||||
|
) {
|
||||||
|
writer.writeString(offsets[0], object.ticker);
|
||||||
|
writer.writeString(offsets[1], object.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionBlockExplorer _transactionBlockExplorerDeserialize(
|
||||||
|
Id id,
|
||||||
|
IsarReader reader,
|
||||||
|
List<int> offsets,
|
||||||
|
Map<Type, List<int>> allOffsets,
|
||||||
|
) {
|
||||||
|
final object = TransactionBlockExplorer(
|
||||||
|
ticker: reader.readString(offsets[0]),
|
||||||
|
url: reader.readString(offsets[1]),
|
||||||
|
);
|
||||||
|
object.id = id;
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
P _transactionBlockExplorerDeserializeProp<P>(
|
||||||
|
IsarReader reader,
|
||||||
|
int propertyId,
|
||||||
|
int offset,
|
||||||
|
Map<Type, List<int>> allOffsets,
|
||||||
|
) {
|
||||||
|
switch (propertyId) {
|
||||||
|
case 0:
|
||||||
|
return (reader.readString(offset)) as P;
|
||||||
|
case 1:
|
||||||
|
return (reader.readString(offset)) as P;
|
||||||
|
default:
|
||||||
|
throw IsarError('Unknown property with id $propertyId');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Id _transactionBlockExplorerGetId(TransactionBlockExplorer object) {
|
||||||
|
return object.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<IsarLinkBase<dynamic>> _transactionBlockExplorerGetLinks(
|
||||||
|
TransactionBlockExplorer object) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
void _transactionBlockExplorerAttach(
|
||||||
|
IsarCollection<dynamic> col, Id id, TransactionBlockExplorer object) {
|
||||||
|
object.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerByIndex
|
||||||
|
on IsarCollection<TransactionBlockExplorer> {
|
||||||
|
Future<TransactionBlockExplorer?> getByTicker(String ticker) {
|
||||||
|
return getByIndex(r'ticker', [ticker]);
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionBlockExplorer? getByTickerSync(String ticker) {
|
||||||
|
return getByIndexSync(r'ticker', [ticker]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> deleteByTicker(String ticker) {
|
||||||
|
return deleteByIndex(r'ticker', [ticker]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deleteByTickerSync(String ticker) {
|
||||||
|
return deleteByIndexSync(r'ticker', [ticker]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<TransactionBlockExplorer?>> getAllByTicker(
|
||||||
|
List<String> tickerValues) {
|
||||||
|
final values = tickerValues.map((e) => [e]).toList();
|
||||||
|
return getAllByIndex(r'ticker', values);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TransactionBlockExplorer?> getAllByTickerSync(
|
||||||
|
List<String> tickerValues) {
|
||||||
|
final values = tickerValues.map((e) => [e]).toList();
|
||||||
|
return getAllByIndexSync(r'ticker', values);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<int> deleteAllByTicker(List<String> tickerValues) {
|
||||||
|
final values = tickerValues.map((e) => [e]).toList();
|
||||||
|
return deleteAllByIndex(r'ticker', values);
|
||||||
|
}
|
||||||
|
|
||||||
|
int deleteAllByTickerSync(List<String> tickerValues) {
|
||||||
|
final values = tickerValues.map((e) => [e]).toList();
|
||||||
|
return deleteAllByIndexSync(r'ticker', values);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Id> putByTicker(TransactionBlockExplorer object) {
|
||||||
|
return putByIndex(r'ticker', object);
|
||||||
|
}
|
||||||
|
|
||||||
|
Id putByTickerSync(TransactionBlockExplorer object, {bool saveLinks = true}) {
|
||||||
|
return putByIndexSync(r'ticker', object, saveLinks: saveLinks);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<Id>> putAllByTicker(List<TransactionBlockExplorer> objects) {
|
||||||
|
return putAllByIndex(r'ticker', objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Id> putAllByTickerSync(List<TransactionBlockExplorer> objects,
|
||||||
|
{bool saveLinks = true}) {
|
||||||
|
return putAllByIndexSync(r'ticker', objects, saveLinks: saveLinks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerQueryWhereSort on QueryBuilder<
|
||||||
|
TransactionBlockExplorer, TransactionBlockExplorer, QWhere> {
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterWhere>
|
||||||
|
anyId() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addWhereClause(const IdWhereClause.any());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerQueryWhere on QueryBuilder<
|
||||||
|
TransactionBlockExplorer, TransactionBlockExplorer, QWhereClause> {
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterWhereClause> idEqualTo(Id id) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addWhereClause(IdWhereClause.between(
|
||||||
|
lower: id,
|
||||||
|
upper: id,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterWhereClause> idNotEqualTo(Id id) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
if (query.whereSort == Sort.asc) {
|
||||||
|
return query
|
||||||
|
.addWhereClause(
|
||||||
|
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
||||||
|
)
|
||||||
|
.addWhereClause(
|
||||||
|
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return query
|
||||||
|
.addWhereClause(
|
||||||
|
IdWhereClause.greaterThan(lower: id, includeLower: false),
|
||||||
|
)
|
||||||
|
.addWhereClause(
|
||||||
|
IdWhereClause.lessThan(upper: id, includeUpper: false),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterWhereClause> idGreaterThan(Id id, {bool include = false}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addWhereClause(
|
||||||
|
IdWhereClause.greaterThan(lower: id, includeLower: include),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterWhereClause> idLessThan(Id id, {bool include = false}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addWhereClause(
|
||||||
|
IdWhereClause.lessThan(upper: id, includeUpper: include),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterWhereClause> idBetween(
|
||||||
|
Id lowerId,
|
||||||
|
Id upperId, {
|
||||||
|
bool includeLower = true,
|
||||||
|
bool includeUpper = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addWhereClause(IdWhereClause.between(
|
||||||
|
lower: lowerId,
|
||||||
|
includeLower: includeLower,
|
||||||
|
upper: upperId,
|
||||||
|
includeUpper: includeUpper,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterWhereClause> tickerEqualTo(String ticker) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addWhereClause(IndexWhereClause.equalTo(
|
||||||
|
indexName: r'ticker',
|
||||||
|
value: [ticker],
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterWhereClause> tickerNotEqualTo(String ticker) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
if (query.whereSort == Sort.asc) {
|
||||||
|
return query
|
||||||
|
.addWhereClause(IndexWhereClause.between(
|
||||||
|
indexName: r'ticker',
|
||||||
|
lower: [],
|
||||||
|
upper: [ticker],
|
||||||
|
includeUpper: false,
|
||||||
|
))
|
||||||
|
.addWhereClause(IndexWhereClause.between(
|
||||||
|
indexName: r'ticker',
|
||||||
|
lower: [ticker],
|
||||||
|
includeLower: false,
|
||||||
|
upper: [],
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
return query
|
||||||
|
.addWhereClause(IndexWhereClause.between(
|
||||||
|
indexName: r'ticker',
|
||||||
|
lower: [ticker],
|
||||||
|
includeLower: false,
|
||||||
|
upper: [],
|
||||||
|
))
|
||||||
|
.addWhereClause(IndexWhereClause.between(
|
||||||
|
indexName: r'ticker',
|
||||||
|
lower: [],
|
||||||
|
upper: [ticker],
|
||||||
|
includeUpper: false,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerQueryFilter on QueryBuilder<
|
||||||
|
TransactionBlockExplorer, TransactionBlockExplorer, QFilterCondition> {
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> idEqualTo(Id value) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'id',
|
||||||
|
value: value,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> idGreaterThan(
|
||||||
|
Id value, {
|
||||||
|
bool include = false,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||||
|
include: include,
|
||||||
|
property: r'id',
|
||||||
|
value: value,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> idLessThan(
|
||||||
|
Id value, {
|
||||||
|
bool include = false,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.lessThan(
|
||||||
|
include: include,
|
||||||
|
property: r'id',
|
||||||
|
value: value,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> idBetween(
|
||||||
|
Id lower,
|
||||||
|
Id upper, {
|
||||||
|
bool includeLower = true,
|
||||||
|
bool includeUpper = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.between(
|
||||||
|
property: r'id',
|
||||||
|
lower: lower,
|
||||||
|
includeLower: includeLower,
|
||||||
|
upper: upper,
|
||||||
|
includeUpper: includeUpper,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> tickerEqualTo(
|
||||||
|
String value, {
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'ticker',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> tickerGreaterThan(
|
||||||
|
String value, {
|
||||||
|
bool include = false,
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||||
|
include: include,
|
||||||
|
property: r'ticker',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> tickerLessThan(
|
||||||
|
String value, {
|
||||||
|
bool include = false,
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.lessThan(
|
||||||
|
include: include,
|
||||||
|
property: r'ticker',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> tickerBetween(
|
||||||
|
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'ticker',
|
||||||
|
lower: lower,
|
||||||
|
includeLower: includeLower,
|
||||||
|
upper: upper,
|
||||||
|
includeUpper: includeUpper,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> tickerStartsWith(
|
||||||
|
String value, {
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.startsWith(
|
||||||
|
property: r'ticker',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> tickerEndsWith(
|
||||||
|
String value, {
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.endsWith(
|
||||||
|
property: r'ticker',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition>
|
||||||
|
tickerContains(String value, {bool caseSensitive = true}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.contains(
|
||||||
|
property: r'ticker',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition>
|
||||||
|
tickerMatches(String pattern, {bool caseSensitive = true}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.matches(
|
||||||
|
property: r'ticker',
|
||||||
|
wildcard: pattern,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> tickerIsEmpty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'ticker',
|
||||||
|
value: '',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> tickerIsNotEmpty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||||
|
property: r'ticker',
|
||||||
|
value: '',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> urlEqualTo(
|
||||||
|
String value, {
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'url',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> urlGreaterThan(
|
||||||
|
String value, {
|
||||||
|
bool include = false,
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||||
|
include: include,
|
||||||
|
property: r'url',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> urlLessThan(
|
||||||
|
String value, {
|
||||||
|
bool include = false,
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.lessThan(
|
||||||
|
include: include,
|
||||||
|
property: r'url',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> urlBetween(
|
||||||
|
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'url',
|
||||||
|
lower: lower,
|
||||||
|
includeLower: includeLower,
|
||||||
|
upper: upper,
|
||||||
|
includeUpper: includeUpper,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> urlStartsWith(
|
||||||
|
String value, {
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.startsWith(
|
||||||
|
property: r'url',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> urlEndsWith(
|
||||||
|
String value, {
|
||||||
|
bool caseSensitive = true,
|
||||||
|
}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.endsWith(
|
||||||
|
property: r'url',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition>
|
||||||
|
urlContains(String value, {bool caseSensitive = true}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.contains(
|
||||||
|
property: r'url',
|
||||||
|
value: value,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition>
|
||||||
|
urlMatches(String pattern, {bool caseSensitive = true}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.matches(
|
||||||
|
property: r'url',
|
||||||
|
wildcard: pattern,
|
||||||
|
caseSensitive: caseSensitive,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> urlIsEmpty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.equalTo(
|
||||||
|
property: r'url',
|
||||||
|
value: '',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer,
|
||||||
|
QAfterFilterCondition> urlIsNotEmpty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addFilterCondition(FilterCondition.greaterThan(
|
||||||
|
property: r'url',
|
||||||
|
value: '',
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerQueryObject on QueryBuilder<
|
||||||
|
TransactionBlockExplorer, TransactionBlockExplorer, QFilterCondition> {}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerQueryLinks on QueryBuilder<
|
||||||
|
TransactionBlockExplorer, TransactionBlockExplorer, QFilterCondition> {}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerQuerySortBy on QueryBuilder<
|
||||||
|
TransactionBlockExplorer, TransactionBlockExplorer, QSortBy> {
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
sortByTicker() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'ticker', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
sortByTickerDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'ticker', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
sortByUrl() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'url', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
sortByUrlDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'url', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerQuerySortThenBy on QueryBuilder<
|
||||||
|
TransactionBlockExplorer, TransactionBlockExplorer, QSortThenBy> {
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
thenById() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'id', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
thenByIdDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'id', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
thenByTicker() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'ticker', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
thenByTickerDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'ticker', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
thenByUrl() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'url', Sort.asc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QAfterSortBy>
|
||||||
|
thenByUrlDesc() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addSortBy(r'url', Sort.desc);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerQueryWhereDistinct on QueryBuilder<
|
||||||
|
TransactionBlockExplorer, TransactionBlockExplorer, QDistinct> {
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QDistinct>
|
||||||
|
distinctByTicker({bool caseSensitive = true}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addDistinctBy(r'ticker', caseSensitive: caseSensitive);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, TransactionBlockExplorer, QDistinct>
|
||||||
|
distinctByUrl({bool caseSensitive = true}) {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addDistinctBy(r'url', caseSensitive: caseSensitive);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension TransactionBlockExplorerQueryProperty on QueryBuilder<
|
||||||
|
TransactionBlockExplorer, TransactionBlockExplorer, QQueryProperty> {
|
||||||
|
QueryBuilder<TransactionBlockExplorer, int, QQueryOperations> idProperty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addPropertyName(r'id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, String, QQueryOperations>
|
||||||
|
tickerProperty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addPropertyName(r'ticker');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryBuilder<TransactionBlockExplorer, String, QQueryOperations>
|
||||||
|
urlProperty() {
|
||||||
|
return QueryBuilder.apply(this, (query) {
|
||||||
|
return query.addPropertyName(r'url');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,18 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/debug_view.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/debug_view.dart';
|
||||||
|
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart';
|
||||||
import 'package:stackwallet/pages/stack_privacy_calls.dart';
|
import 'package:stackwallet/pages/stack_privacy_calls.dart';
|
||||||
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
import 'package:stackwallet/providers/global/prefs_provider.dart';
|
||||||
import 'package:stackwallet/utilities/constants.dart';
|
import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
import 'package:stackwallet/widgets/background.dart';
|
import 'package:stackwallet/widgets/background.dart';
|
||||||
|
import 'package:stackwallet/widgets/choose_coin_view.dart';
|
||||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
|
||||||
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
import 'package:stackwallet/widgets/rounded_white_container.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
class AdvancedSettingsView extends StatelessWidget {
|
class AdvancedSettingsView extends StatelessWidget {
|
||||||
const AdvancedSettingsView({
|
const AdvancedSettingsView({
|
||||||
|
@ -221,6 +224,43 @@ class AdvancedSettingsView extends StatelessWidget {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
child: RawMaterialButton(
|
||||||
|
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pushNamed(ChooseCoinView.routeName,
|
||||||
|
arguments: const Tuple3<String, String, String>(
|
||||||
|
"Manage block explorers",
|
||||||
|
"block explorer",
|
||||||
|
ManageExplorerView.routeName));
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 20,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Change block explorer",
|
||||||
|
style: STextStyles.titleBold12(context),
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:stackwallet/utilities/block_explorers.dart';
|
||||||
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
|
import 'package:stackwallet/utilities/theme/stack_colors.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';
|
||||||
|
|
||||||
|
class ManageExplorerView extends ConsumerStatefulWidget {
|
||||||
|
const ManageExplorerView({
|
||||||
|
Key? key,
|
||||||
|
required this.coin,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
static const String routeName = "/manageExplorer";
|
||||||
|
|
||||||
|
final Coin coin;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<ManageExplorerView> createState() => _ManageExplorerViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ManageExplorerViewState extends ConsumerState<ManageExplorerView> {
|
||||||
|
late TextEditingController textEditingController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
textEditingController = TextEditingController(
|
||||||
|
text:
|
||||||
|
getBlockExplorerTransactionUrlFor(coin: widget.coin, txid: "[TXID]")
|
||||||
|
.toString()
|
||||||
|
.replaceAll("%5BTXID%5D", "[TXID]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Background(
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: AppBarBackButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
"${widget.coin.prettyName} block explorer",
|
||||||
|
style: STextStyles.navBarTitle(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
controller: textEditingController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
RoundedWhiteContainer(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
"Edit your block explorer above. Keep in mind that "
|
||||||
|
"every block explorer has a slightly different URL "
|
||||||
|
"scheme.\n\nPaste in your block explorer of choice,"
|
||||||
|
" then edit in [TXID] where the transaction ID "
|
||||||
|
"should go, and Stack Wallet will auto fill the "
|
||||||
|
"transaction ID in that place of URL.",
|
||||||
|
style: STextStyles.itemSubtitle(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
minWidth: 480,
|
||||||
|
minHeight: 70,
|
||||||
|
),
|
||||||
|
child: TextButton(
|
||||||
|
style: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.getPrimaryEnabledButtonStyle(context),
|
||||||
|
onPressed: () {
|
||||||
|
textEditingController.text =
|
||||||
|
textEditingController.text.trim();
|
||||||
|
setBlockExplorerForCoin(
|
||||||
|
coin: widget.coin,
|
||||||
|
url: Uri.parse(textEditingController.text))
|
||||||
|
.then((value) => Navigator.of(context).pop());
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
"Save",
|
||||||
|
style: STextStyles.button(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,6 +63,7 @@ import 'package:stackwallet/pages/send_view/token_send_view.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/about_view.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/about_view.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/debug_view.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/debug_view.dart';
|
||||||
|
import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/global_settings_view/currency_view.dart';
|
import 'package:stackwallet/pages/settings_views/global_settings_view/currency_view.dart';
|
||||||
|
@ -99,6 +100,7 @@ import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_set
|
||||||
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart';
|
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart';
|
||||||
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart';
|
import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart';
|
||||||
import 'package:stackwallet/pages/stack_privacy_calls.dart';
|
import 'package:stackwallet/pages/stack_privacy_calls.dart';
|
||||||
|
import 'package:stackwallet/widgets/choose_coin_view.dart';
|
||||||
import 'package:stackwallet/pages/token_view/my_tokens_view.dart';
|
import 'package:stackwallet/pages/token_view/my_tokens_view.dart';
|
||||||
import 'package:stackwallet/pages/token_view/token_contract_details_view.dart';
|
import 'package:stackwallet/pages/token_view/token_contract_details_view.dart';
|
||||||
import 'package:stackwallet/pages/token_view/token_view.dart';
|
import 'package:stackwallet/pages/token_view/token_view.dart';
|
||||||
|
@ -206,6 +208,36 @@ class RouteGenerator {
|
||||||
builder: (_) => const StackPrivacyCalls(isSettings: false),
|
builder: (_) => const StackPrivacyCalls(isSettings: false),
|
||||||
settings: RouteSettings(name: settings.name));
|
settings: RouteSettings(name: settings.name));
|
||||||
|
|
||||||
|
case ChooseCoinView.routeName:
|
||||||
|
if (args is Tuple3<String, String, String>) {
|
||||||
|
return getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => ChooseCoinView(
|
||||||
|
title: args.item1,
|
||||||
|
coinAdditional: args.item2,
|
||||||
|
nextRouteName: args.item3,
|
||||||
|
),
|
||||||
|
settings: RouteSettings(
|
||||||
|
name: settings.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
|
case ManageExplorerView.routeName:
|
||||||
|
if (args is Coin) {
|
||||||
|
return getRoute(
|
||||||
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
builder: (_) => ManageExplorerView(
|
||||||
|
coin: args,
|
||||||
|
),
|
||||||
|
settings: RouteSettings(
|
||||||
|
name: settings.name,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _routeError("${settings.name} invalid args: ${args.toString()}");
|
||||||
|
|
||||||
case WalletsView.routeName:
|
case WalletsView.routeName:
|
||||||
return getRoute(
|
return getRoute(
|
||||||
shouldUseMaterialRoute: useMaterialPageRoute,
|
shouldUseMaterialRoute: useMaterialPageRoute,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
import 'package:stackwallet/db/isar/main_db.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/block_explorer.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
|
|
||||||
Uri getBlockExplorerTransactionUrlFor({
|
Uri getDefaultBlockExplorerUrlFor({
|
||||||
required Coin coin,
|
required Coin coin,
|
||||||
required String txid,
|
required String txid,
|
||||||
}) {
|
}) {
|
||||||
|
@ -41,3 +43,29 @@ Uri getBlockExplorerTransactionUrlFor({
|
||||||
return Uri.parse("https://chainz.cryptoid.info/part/tx.dws?$txid.htm");
|
return Uri.parse("https://chainz.cryptoid.info/part/tx.dws?$txid.htm");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// returns internal Isar ID for the inserted object/record
|
||||||
|
Future<int> setBlockExplorerForCoin({
|
||||||
|
required Coin coin,
|
||||||
|
required Uri url,
|
||||||
|
}) async {
|
||||||
|
return await MainDB.instance.putTransactionBlockExplorer(
|
||||||
|
TransactionBlockExplorer(
|
||||||
|
ticker: coin.ticker,
|
||||||
|
url: url.toString(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri getBlockExplorerTransactionUrlFor({
|
||||||
|
required Coin coin,
|
||||||
|
required String txid,
|
||||||
|
}) {
|
||||||
|
String? url = MainDB.instance.getTransactionBlockExplorer(coin: coin)?.url;
|
||||||
|
if (url == null) {
|
||||||
|
return getDefaultBlockExplorerUrlFor(coin: coin, txid: txid);
|
||||||
|
} else {
|
||||||
|
url = url.replaceAll("%5BTXID%5D", txid);
|
||||||
|
return Uri.parse(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
138
lib/widgets/choose_coin_view.dart
Normal file
138
lib/widgets/choose_coin_view.dart
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:stackwallet/providers/providers.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/theme/stack_colors.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';
|
||||||
|
|
||||||
|
class ChooseCoinView extends ConsumerStatefulWidget {
|
||||||
|
const ChooseCoinView({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.coinAdditional,
|
||||||
|
required this.nextRouteName,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
static const String routeName = "/chooseCoin";
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
final String coinAdditional;
|
||||||
|
final String nextRouteName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ConsumerState<ChooseCoinView> createState() => _ChooseCoinViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChooseCoinViewState extends ConsumerState<ChooseCoinView> {
|
||||||
|
List<Coin> _coins = [...Coin.values];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_coins = _coins.toList();
|
||||||
|
_coins.remove(Coin.firoTestNet);
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
bool showTestNet = ref.watch(
|
||||||
|
prefsChangeNotifierProvider.select((value) => value.showTestNetCoins),
|
||||||
|
);
|
||||||
|
|
||||||
|
List<Coin> coins = showTestNet
|
||||||
|
? _coins
|
||||||
|
: _coins.sublist(0, _coins.length - kTestNetCoinCount);
|
||||||
|
|
||||||
|
return Background(
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: AppBarBackButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
widget.title,
|
||||||
|
style: STextStyles.navBarTitle(context),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
top: 12,
|
||||||
|
left: 12,
|
||||||
|
right: 12,
|
||||||
|
),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
...coins.map(
|
||||||
|
(coin) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: RoundedWhiteContainer(
|
||||||
|
padding: const EdgeInsets.all(0),
|
||||||
|
child: RawMaterialButton(
|
||||||
|
// splashColor: Theme.of(context).extension<StackColors>()!.highlight,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(
|
||||||
|
Constants.size.circularBorderRadius,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
materialTapTargetSize:
|
||||||
|
MaterialTapTargetSize.shrinkWrap,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
widget.nextRouteName,
|
||||||
|
arguments: coin,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
Assets.svg.iconFor(coin: coin),
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"${coin.prettyName} ${widget.coinAdditional}",
|
||||||
|
style: STextStyles.titleBold12(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -510,6 +510,19 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs {
|
||||||
returnValueForMissingStub: null,
|
returnValueForMissingStub: null,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
|
bool get randomizePIN => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#randomizePIN),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
@override
|
||||||
|
set randomizePIN(bool? randomizePIN) => super.noSuchMethod(
|
||||||
|
Invocation.setter(
|
||||||
|
#randomizePIN,
|
||||||
|
randomizePIN,
|
||||||
|
),
|
||||||
|
returnValueForMissingStub: null,
|
||||||
|
);
|
||||||
|
@override
|
||||||
bool get useBiometrics => (super.noSuchMethod(
|
bool get useBiometrics => (super.noSuchMethod(
|
||||||
Invocation.getter(#useBiometrics),
|
Invocation.getter(#useBiometrics),
|
||||||
returnValue: false,
|
returnValue: false,
|
||||||
|
|
|
@ -231,6 +231,19 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs {
|
||||||
returnValueForMissingStub: null,
|
returnValueForMissingStub: null,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
|
bool get randomizePIN => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#randomizePIN),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
@override
|
||||||
|
set randomizePIN(bool? randomizePIN) => super.noSuchMethod(
|
||||||
|
Invocation.setter(
|
||||||
|
#randomizePIN,
|
||||||
|
randomizePIN,
|
||||||
|
),
|
||||||
|
returnValueForMissingStub: null,
|
||||||
|
);
|
||||||
|
@override
|
||||||
bool get useBiometrics => (super.noSuchMethod(
|
bool get useBiometrics => (super.noSuchMethod(
|
||||||
Invocation.getter(#useBiometrics),
|
Invocation.getter(#useBiometrics),
|
||||||
returnValue: false,
|
returnValue: false,
|
||||||
|
|
|
@ -2350,6 +2350,19 @@ class MockPrefs extends _i1.Mock implements _i24.Prefs {
|
||||||
returnValueForMissingStub: null,
|
returnValueForMissingStub: null,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
|
bool get randomizePIN => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#randomizePIN),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
@override
|
||||||
|
set randomizePIN(bool? randomizePIN) => super.noSuchMethod(
|
||||||
|
Invocation.setter(
|
||||||
|
#randomizePIN,
|
||||||
|
randomizePIN,
|
||||||
|
),
|
||||||
|
returnValueForMissingStub: null,
|
||||||
|
);
|
||||||
|
@override
|
||||||
bool get useBiometrics => (super.noSuchMethod(
|
bool get useBiometrics => (super.noSuchMethod(
|
||||||
Invocation.getter(#useBiometrics),
|
Invocation.getter(#useBiometrics),
|
||||||
returnValue: false,
|
returnValue: false,
|
||||||
|
|
|
@ -181,6 +181,19 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs {
|
||||||
returnValueForMissingStub: null,
|
returnValueForMissingStub: null,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
|
bool get randomizePIN => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#randomizePIN),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
@override
|
||||||
|
set randomizePIN(bool? randomizePIN) => super.noSuchMethod(
|
||||||
|
Invocation.setter(
|
||||||
|
#randomizePIN,
|
||||||
|
randomizePIN,
|
||||||
|
),
|
||||||
|
returnValueForMissingStub: null,
|
||||||
|
);
|
||||||
|
@override
|
||||||
bool get useBiometrics => (super.noSuchMethod(
|
bool get useBiometrics => (super.noSuchMethod(
|
||||||
Invocation.getter(#useBiometrics),
|
Invocation.getter(#useBiometrics),
|
||||||
returnValue: false,
|
returnValue: false,
|
||||||
|
|
|
@ -419,6 +419,19 @@ class MockPrefs extends _i1.Mock implements _i12.Prefs {
|
||||||
returnValueForMissingStub: null,
|
returnValueForMissingStub: null,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
|
bool get randomizePIN => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#randomizePIN),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
@override
|
||||||
|
set randomizePIN(bool? randomizePIN) => super.noSuchMethod(
|
||||||
|
Invocation.setter(
|
||||||
|
#randomizePIN,
|
||||||
|
randomizePIN,
|
||||||
|
),
|
||||||
|
returnValueForMissingStub: null,
|
||||||
|
);
|
||||||
|
@override
|
||||||
bool get useBiometrics => (super.noSuchMethod(
|
bool get useBiometrics => (super.noSuchMethod(
|
||||||
Invocation.getter(#useBiometrics),
|
Invocation.getter(#useBiometrics),
|
||||||
returnValue: false,
|
returnValue: false,
|
||||||
|
|
|
@ -2282,6 +2282,19 @@ class MockPrefs extends _i1.Mock implements _i19.Prefs {
|
||||||
returnValueForMissingStub: null,
|
returnValueForMissingStub: null,
|
||||||
);
|
);
|
||||||
@override
|
@override
|
||||||
|
bool get randomizePIN => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#randomizePIN),
|
||||||
|
returnValue: false,
|
||||||
|
) as bool);
|
||||||
|
@override
|
||||||
|
set randomizePIN(bool? randomizePIN) => super.noSuchMethod(
|
||||||
|
Invocation.setter(
|
||||||
|
#randomizePIN,
|
||||||
|
randomizePIN,
|
||||||
|
),
|
||||||
|
returnValueForMissingStub: null,
|
||||||
|
);
|
||||||
|
@override
|
||||||
bool get useBiometrics => (super.noSuchMethod(
|
bool get useBiometrics => (super.noSuchMethod(
|
||||||
Invocation.getter(#useBiometrics),
|
Invocation.getter(#useBiometrics),
|
||||||
returnValue: false,
|
returnValue: false,
|
||||||
|
|
Loading…
Reference in a new issue