mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-12 09:27:01 +00:00
Update frost and hide insecure addresses on receive page and in address list
This commit is contained in:
parent
94757f0f2e
commit
412e3fdf07
9 changed files with 297 additions and 17 deletions
|
@ -1 +1 @@
|
|||
Subproject commit d3fa8169524376579da08a5062ad88e45ee9b1eb
|
||||
Subproject commit 2451deab817b456ad93d5579c0d0687cb681392a
|
|
@ -11,6 +11,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
import '../../../../exceptions/address/address_exception.dart';
|
||||
import 'crypto_currency_address.dart';
|
||||
import 'transaction.dart';
|
||||
|
@ -27,6 +28,7 @@ class Address extends CryptoCurrencyAddress {
|
|||
required this.derivationPath,
|
||||
required this.type,
|
||||
required this.subType,
|
||||
this.zSafeFrost,
|
||||
this.otherData,
|
||||
});
|
||||
|
||||
|
@ -55,6 +57,8 @@ class Address extends CryptoCurrencyAddress {
|
|||
|
||||
final transactions = IsarLinks<Transaction>();
|
||||
|
||||
late final bool? zSafeFrost;
|
||||
|
||||
int derivationChain() {
|
||||
if (subType == AddressSubType.receiving) {
|
||||
return 0; // 0 for receiving (external)
|
||||
|
@ -80,6 +84,7 @@ class Address extends CryptoCurrencyAddress {
|
|||
AddressType? type,
|
||||
AddressSubType? subType,
|
||||
DerivationPath? derivationPath,
|
||||
bool? zSafeFrost,
|
||||
String? otherData,
|
||||
}) {
|
||||
return Address(
|
||||
|
@ -90,6 +95,7 @@ class Address extends CryptoCurrencyAddress {
|
|||
type: type ?? this.type,
|
||||
subType: subType ?? this.subType,
|
||||
derivationPath: derivationPath ?? this.derivationPath,
|
||||
zSafeFrost: zSafeFrost ?? this.zSafeFrost,
|
||||
otherData: otherData ?? this.otherData,
|
||||
);
|
||||
}
|
||||
|
@ -105,6 +111,7 @@ class Address extends CryptoCurrencyAddress {
|
|||
"subType: ${subType.name}, "
|
||||
"transactionsLength: ${transactions.length} "
|
||||
"derivationPath: $derivationPath, "
|
||||
"zSafeFrost: $zSafeFrost, "
|
||||
"otherData: $otherData, "
|
||||
"}";
|
||||
|
||||
|
@ -117,6 +124,7 @@ class Address extends CryptoCurrencyAddress {
|
|||
"type": type.name,
|
||||
"subType": subType.name,
|
||||
"derivationPath": derivationPath?.value,
|
||||
"zSafeFrost": zSafeFrost,
|
||||
"otherData": otherData,
|
||||
};
|
||||
return jsonEncode(result);
|
||||
|
@ -143,6 +151,7 @@ class Address extends CryptoCurrencyAddress {
|
|||
derivationPath: derivationPath,
|
||||
type: AddressType.values.byName(json["type"] as String),
|
||||
subType: AddressSubType.values.byName(json["subType"] as String),
|
||||
zSafeFrost: json["zSafeFrost"] as bool?,
|
||||
otherData: json["otherData"] as String?,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,11 @@ const AddressSchema = CollectionSchema(
|
|||
id: 7,
|
||||
name: r'walletId',
|
||||
type: IsarType.string,
|
||||
),
|
||||
r'zSafeFrost': PropertySchema(
|
||||
id: 8,
|
||||
name: r'zSafeFrost',
|
||||
type: IsarType.bool,
|
||||
)
|
||||
},
|
||||
estimateSize: _addressEstimateSize,
|
||||
|
@ -172,6 +177,7 @@ void _addressSerialize(
|
|||
writer.writeByte(offsets[5], object.type.index);
|
||||
writer.writeString(offsets[6], object.value);
|
||||
writer.writeString(offsets[7], object.walletId);
|
||||
writer.writeBool(offsets[8], object.zSafeFrost);
|
||||
}
|
||||
|
||||
Address _addressDeserialize(
|
||||
|
@ -195,6 +201,7 @@ Address _addressDeserialize(
|
|||
AddressType.p2pkh,
|
||||
value: reader.readString(offsets[6]),
|
||||
walletId: reader.readString(offsets[7]),
|
||||
zSafeFrost: reader.readBoolOrNull(offsets[8]),
|
||||
);
|
||||
object.id = id;
|
||||
return object;
|
||||
|
@ -229,6 +236,8 @@ P _addressDeserializeProp<P>(
|
|||
return (reader.readString(offset)) as P;
|
||||
case 7:
|
||||
return (reader.readString(offset)) as P;
|
||||
case 8:
|
||||
return (reader.readBoolOrNull(offset)) as P;
|
||||
default:
|
||||
throw IsarError('Unknown property with id $propertyId');
|
||||
}
|
||||
|
@ -1474,6 +1483,32 @@ extension AddressQueryFilter
|
|||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Address, Address, QAfterFilterCondition> zSafeFrostIsNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNull(
|
||||
property: r'zSafeFrost',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Address, Address, QAfterFilterCondition> zSafeFrostIsNotNull() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(const FilterCondition.isNotNull(
|
||||
property: r'zSafeFrost',
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Address, Address, QAfterFilterCondition> zSafeFrostEqualTo(
|
||||
bool? value) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addFilterCondition(FilterCondition.equalTo(
|
||||
property: r'zSafeFrost',
|
||||
value: value,
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension AddressQueryObject
|
||||
|
@ -1621,6 +1656,18 @@ extension AddressQuerySortBy on QueryBuilder<Address, Address, QSortBy> {
|
|||
return query.addSortBy(r'walletId', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Address, Address, QAfterSortBy> sortByZSafeFrost() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'zSafeFrost', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Address, Address, QAfterSortBy> sortByZSafeFrostDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'zSafeFrost', Sort.desc);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension AddressQuerySortThenBy
|
||||
|
@ -1708,6 +1755,18 @@ extension AddressQuerySortThenBy
|
|||
return query.addSortBy(r'walletId', Sort.desc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Address, Address, QAfterSortBy> thenByZSafeFrost() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'zSafeFrost', Sort.asc);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Address, Address, QAfterSortBy> thenByZSafeFrostDesc() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addSortBy(r'zSafeFrost', Sort.desc);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension AddressQueryWhereDistinct
|
||||
|
@ -1756,6 +1815,12 @@ extension AddressQueryWhereDistinct
|
|||
return query.addDistinctBy(r'walletId', caseSensitive: caseSensitive);
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Address, Address, QDistinct> distinctByZSafeFrost() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addDistinctBy(r'zSafeFrost');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension AddressQueryProperty
|
||||
|
@ -1814,6 +1879,12 @@ extension AddressQueryProperty
|
|||
return query.addPropertyName(r'walletId');
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<Address, bool?, QQueryOperations> zSafeFrostProperty() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addPropertyName(r'zSafeFrost');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// **************************************************************************
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
@ -372,6 +373,16 @@ class _AddressDetailsViewState extends ConsumerState<AddressDetailsView> {
|
|||
detail: address.subType.prettyName,
|
||||
button: Container(),
|
||||
),
|
||||
if (kDebugMode)
|
||||
const _Div(
|
||||
height: 12,
|
||||
),
|
||||
if (kDebugMode)
|
||||
DetailItem(
|
||||
title: "frost secure (kDebugMode)",
|
||||
detail: address.zSafeFrost.toString(),
|
||||
button: Container(),
|
||||
),
|
||||
if (ref.watch(pWallets).getWallet(widget.walletId)
|
||||
is Bip39HDWallet)
|
||||
const _Div(
|
||||
|
|
|
@ -67,6 +67,19 @@ class _WalletAddressesViewState extends ConsumerState<WalletAddressesView> {
|
|||
.and()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.nonWallet)
|
||||
.and()
|
||||
.group(
|
||||
(q) => q
|
||||
.group(
|
||||
(q2) => q2
|
||||
.typeEqualTo(AddressType.frostMS)
|
||||
.and()
|
||||
.zSafeFrostEqualTo(true),
|
||||
)
|
||||
.or()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.frostMS),
|
||||
)
|
||||
.sortByDerivationIndex()
|
||||
.idProperty()
|
||||
.findAll();
|
||||
|
@ -114,6 +127,19 @@ class _WalletAddressesViewState extends ConsumerState<WalletAddressesView> {
|
|||
.and()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.nonWallet)
|
||||
.and()
|
||||
.group(
|
||||
(q) => q
|
||||
.group(
|
||||
(q2) => q2
|
||||
.typeEqualTo(AddressType.frostMS)
|
||||
.and()
|
||||
.zSafeFrostEqualTo(true),
|
||||
)
|
||||
.or()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.frostMS),
|
||||
)
|
||||
.sortByDerivationIndex()
|
||||
.idProperty()
|
||||
.findAll();
|
||||
|
|
|
@ -67,6 +67,7 @@ class _FrostSendStep1bState extends ConsumerState<FrostSendStep1b> {
|
|||
final data = Frost.extractDataFromSignConfig(
|
||||
signConfig: config,
|
||||
coin: wallet.cryptoCurrency,
|
||||
serializedKeys: (await wallet.getSerializedKeys())!,
|
||||
);
|
||||
|
||||
final utxos = await ref
|
||||
|
|
|
@ -69,6 +69,19 @@ class _DesktopAddressListState extends ConsumerState<DesktopAddressList> {
|
|||
.and()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.nonWallet)
|
||||
.and()
|
||||
.group(
|
||||
(q) => q
|
||||
.group(
|
||||
(q2) => q2
|
||||
.typeEqualTo(AddressType.frostMS)
|
||||
.and()
|
||||
.zSafeFrostEqualTo(true),
|
||||
)
|
||||
.or()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.frostMS),
|
||||
)
|
||||
.sortByDerivationIndex()
|
||||
.idProperty()
|
||||
.findAllSync();
|
||||
|
@ -118,6 +131,19 @@ class _DesktopAddressListState extends ConsumerState<DesktopAddressList> {
|
|||
.and()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.nonWallet)
|
||||
.and()
|
||||
.group(
|
||||
(q) => q
|
||||
.group(
|
||||
(q2) => q2
|
||||
.typeEqualTo(AddressType.frostMS)
|
||||
.and()
|
||||
.zSafeFrostEqualTo(true),
|
||||
)
|
||||
.or()
|
||||
.not()
|
||||
.typeEqualTo(AddressType.frostMS),
|
||||
)
|
||||
.sortByDerivationIndex()
|
||||
.idProperty()
|
||||
.findAllSync();
|
||||
|
|
|
@ -80,6 +80,7 @@ abstract class Frost {
|
|||
int feePerWeight,
|
||||
List<Output> inputs,
|
||||
}) extractDataFromSignConfig({
|
||||
required String serializedKeys,
|
||||
required String signConfig,
|
||||
required CryptoCurrency coin,
|
||||
}) {
|
||||
|
@ -89,6 +90,7 @@ abstract class Frost {
|
|||
final signConfigPointer = decodedSignConfig(
|
||||
encodedConfig: signConfig,
|
||||
network: network,
|
||||
serializedKeys: serializedKeys,
|
||||
);
|
||||
|
||||
// get various data from config
|
||||
|
@ -126,6 +128,7 @@ abstract class Frost {
|
|||
final List<Output> outputs = [];
|
||||
for (int i = 0; i < count; i++) {
|
||||
final output = signInput(
|
||||
thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys),
|
||||
signConfig: signConfig,
|
||||
index: i,
|
||||
network: network,
|
||||
|
@ -283,6 +286,7 @@ abstract class Frost {
|
|||
//=================== transaction creation ===================================
|
||||
|
||||
static String createSignConfig({
|
||||
required String serializedKeys,
|
||||
required int network,
|
||||
required List<
|
||||
({
|
||||
|
@ -297,6 +301,7 @@ abstract class Frost {
|
|||
}) {
|
||||
try {
|
||||
final signConfig = newSignConfig(
|
||||
thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys),
|
||||
network: network,
|
||||
outputs: inputs
|
||||
.map(
|
||||
|
@ -402,12 +407,16 @@ abstract class Frost {
|
|||
}
|
||||
|
||||
static Pointer<SignConfig> decodedSignConfig({
|
||||
required String serializedKeys,
|
||||
required String encodedConfig,
|
||||
required int network,
|
||||
}) {
|
||||
try {
|
||||
final configPtr =
|
||||
decodeSignConfig(encodedSignConfig: encodedConfig, network: network);
|
||||
final configPtr = decodeSignConfig(
|
||||
thresholdKeysWrapperPointer: deserializeKeys(keys: serializedKeys),
|
||||
encodedSignConfig: encodedConfig,
|
||||
network: network,
|
||||
);
|
||||
return configPtr;
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
|
|
|
@ -32,6 +32,8 @@ import '../../models/tx_data.dart';
|
|||
import '../wallet.dart';
|
||||
import '../wallet_mixin_interfaces/multi_address_interface.dart';
|
||||
|
||||
const kFrostSecureStartingIndex = 1;
|
||||
|
||||
class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
||||
with MultiAddressInterface {
|
||||
BitcoinFrostWallet(CryptoCurrencyNetwork network)
|
||||
|
@ -85,8 +87,9 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
|
||||
final address = await _generateAddress(
|
||||
change: 0,
|
||||
index: 0,
|
||||
index: kFrostSecureStartingIndex,
|
||||
serializedKeys: serializedKeys,
|
||||
secure: true,
|
||||
);
|
||||
|
||||
await mainDB.putAddresses([address]);
|
||||
|
@ -198,6 +201,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
outputs: txData.recipients!,
|
||||
changeAddress: changeAddress!.value,
|
||||
feePerWeight: feePerWeight,
|
||||
serializedKeys: (await getSerializedKeys())!,
|
||||
);
|
||||
} on FrostdartException catch (e) {
|
||||
if (e.errorCode == NOT_ENOUGH_FUNDS_ERROR &&
|
||||
|
@ -375,6 +379,14 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
property: r"subType",
|
||||
value: AddressSubType.change,
|
||||
),
|
||||
const FilterCondition.equalTo(
|
||||
property: r"zSafeFrost",
|
||||
value: true,
|
||||
),
|
||||
const FilterCondition.greaterThan(
|
||||
property: r"derivationIndex",
|
||||
value: 0,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -389,6 +401,14 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
property: r"subType",
|
||||
value: AddressSubType.receiving,
|
||||
),
|
||||
const FilterCondition.equalTo(
|
||||
property: r"zSafeFrost",
|
||||
value: true,
|
||||
),
|
||||
const FilterCondition.greaterThan(
|
||||
property: r"derivationIndex",
|
||||
value: 0,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
|
@ -618,13 +638,30 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
if (address == null) {
|
||||
final serializedKeys = await getSerializedKeys();
|
||||
if (serializedKeys != null) {
|
||||
final address = await _generateAddress(
|
||||
change: 0,
|
||||
index: 0,
|
||||
serializedKeys: serializedKeys,
|
||||
);
|
||||
int index = kFrostSecureStartingIndex;
|
||||
const someSaneMaximum = 200;
|
||||
Address? address;
|
||||
while (index < someSaneMaximum) {
|
||||
try {
|
||||
address = await _generateAddress(
|
||||
change: 0,
|
||||
index: index,
|
||||
serializedKeys: serializedKeys,
|
||||
secure: true,
|
||||
);
|
||||
|
||||
await mainDB.updateOrPutAddresses([address]);
|
||||
await mainDB.updateOrPutAddresses([address]);
|
||||
} catch (_) {}
|
||||
if (address != null) {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index >= someSaneMaximum) {
|
||||
throw Exception(
|
||||
"index < kFrostSecureStartingIndex hit someSaneMaximum");
|
||||
}
|
||||
} else {
|
||||
Logging.instance.log(
|
||||
"$runtimeType.checkSaveInitialReceivingAddress() failed due"
|
||||
|
@ -818,6 +855,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
_checkGapsLinearly(
|
||||
serializedKeys,
|
||||
receiveChain,
|
||||
secure: true,
|
||||
),
|
||||
];
|
||||
final List<Future<({int index, List<Address> addresses})>>
|
||||
|
@ -825,6 +863,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
_checkGapsLinearly(
|
||||
serializedKeys,
|
||||
changeChain,
|
||||
secure: true,
|
||||
),
|
||||
];
|
||||
|
||||
|
@ -881,6 +920,8 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
);
|
||||
|
||||
await mainDB.updateOrPutAddresses(addressesToStore);
|
||||
|
||||
await _legacyInsecureScan(serializedKeys);
|
||||
});
|
||||
|
||||
GlobalEventBus.instance.fire(
|
||||
|
@ -908,6 +949,80 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
}
|
||||
}
|
||||
|
||||
// for legacy support secure is set to false to see
|
||||
// funds received on insecure addresses
|
||||
Future<void> _legacyInsecureScan(String serializedKeys) async {
|
||||
const receiveChain = 0;
|
||||
const changeChain = 1;
|
||||
|
||||
final List<Future<({int index, List<Address> addresses})>> receiveFutures =
|
||||
[
|
||||
_checkGapsLinearly(
|
||||
serializedKeys,
|
||||
receiveChain,
|
||||
secure: false,
|
||||
),
|
||||
];
|
||||
final List<Future<({int index, List<Address> addresses})>> changeFutures = [
|
||||
// for legacy support secure is set to false to see
|
||||
// funds received on insecure addresses
|
||||
_checkGapsLinearly(
|
||||
serializedKeys,
|
||||
changeChain,
|
||||
secure: false,
|
||||
),
|
||||
];
|
||||
|
||||
// io limitations may require running these linearly instead
|
||||
final futuresResult = await Future.wait([
|
||||
Future.wait(receiveFutures),
|
||||
Future.wait(changeFutures),
|
||||
]);
|
||||
|
||||
final receiveResults = futuresResult[0];
|
||||
final changeResults = futuresResult[1];
|
||||
|
||||
final List<Address> addressesToStore = [];
|
||||
|
||||
int highestReceivingIndexWithHistory = 0;
|
||||
for (final tuple in receiveResults) {
|
||||
if (tuple.addresses.isNotEmpty) {
|
||||
highestReceivingIndexWithHistory = max(
|
||||
tuple.index,
|
||||
highestReceivingIndexWithHistory,
|
||||
);
|
||||
addressesToStore.addAll(tuple.addresses);
|
||||
}
|
||||
}
|
||||
|
||||
int highestChangeIndexWithHistory = 0;
|
||||
for (final tuple in changeResults) {
|
||||
if (tuple.addresses.isNotEmpty) {
|
||||
highestChangeIndexWithHistory = max(
|
||||
tuple.index,
|
||||
highestChangeIndexWithHistory,
|
||||
);
|
||||
addressesToStore.addAll(tuple.addresses);
|
||||
}
|
||||
}
|
||||
|
||||
// remove extra addresses to help minimize risk of creating a large gap
|
||||
addressesToStore.removeWhere(
|
||||
(e) =>
|
||||
e.subType == AddressSubType.change &&
|
||||
e.derivationIndex > highestChangeIndexWithHistory,
|
||||
);
|
||||
addressesToStore.removeWhere(
|
||||
(e) =>
|
||||
e.subType == AddressSubType.receiving &&
|
||||
e.derivationIndex > highestReceivingIndexWithHistory,
|
||||
);
|
||||
|
||||
if (addressesToStore.isNotEmpty) {
|
||||
await mainDB.updateOrPutAddresses(addressesToStore);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateBalance() async {
|
||||
final utxos = await mainDB.getUTXOs(walletId).findAll();
|
||||
|
@ -1394,7 +1509,9 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
@override
|
||||
Future<void> generateNewChangeAddress() async {
|
||||
final current = await getCurrentChangeAddress();
|
||||
int index = current == null ? 0 : current.derivationIndex + 1;
|
||||
int index = current == null
|
||||
? kFrostSecureStartingIndex
|
||||
: current.derivationIndex + 1;
|
||||
const chain = 1; // change address
|
||||
|
||||
final serializedKeys = (await getSerializedKeys())!;
|
||||
|
@ -1406,6 +1523,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
change: chain,
|
||||
index: index,
|
||||
serializedKeys: serializedKeys,
|
||||
secure: true,
|
||||
);
|
||||
} on FrostdartException catch (e) {
|
||||
if (e.errorCode == 72) {
|
||||
|
@ -1424,7 +1542,9 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
@override
|
||||
Future<void> generateNewReceivingAddress() async {
|
||||
final current = await getCurrentReceivingAddress();
|
||||
int index = current == null ? 0 : current.derivationIndex + 1;
|
||||
int index = current == null
|
||||
? kFrostSecureStartingIndex
|
||||
: current.derivationIndex + 1;
|
||||
const chain = 0; // receiving address
|
||||
|
||||
final serializedKeys = (await getSerializedKeys())!;
|
||||
|
@ -1436,6 +1556,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
change: chain,
|
||||
index: index,
|
||||
serializedKeys: serializedKeys,
|
||||
secure: true,
|
||||
);
|
||||
} on FrostdartException catch (e) {
|
||||
if (e.errorCode == 72) {
|
||||
|
@ -1532,6 +1653,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
change: chain,
|
||||
index: startingIndex,
|
||||
serializedKeys: serializedKeys,
|
||||
secure: true,
|
||||
);
|
||||
} on FrostdartException catch (e) {
|
||||
if (e.errorCode == 72) {
|
||||
|
@ -1554,6 +1676,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
required int change,
|
||||
required int index,
|
||||
required String serializedKeys,
|
||||
required bool secure,
|
||||
}) async {
|
||||
final addressDerivationData = (
|
||||
account: account,
|
||||
|
@ -1569,6 +1692,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
: Network.Testnet,
|
||||
keys: keys,
|
||||
addressDerivationData: addressDerivationData,
|
||||
secure: secure,
|
||||
);
|
||||
|
||||
return Address(
|
||||
|
@ -1583,16 +1707,18 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
? AddressSubType.change
|
||||
: AddressSubType.unknown,
|
||||
type: AddressType.frostMS,
|
||||
zSafeFrost: secure && index >= kFrostSecureStartingIndex,
|
||||
);
|
||||
}
|
||||
|
||||
Future<({List<Address> addresses, int index})> _checkGapsLinearly(
|
||||
String serializedKeys,
|
||||
int chain,
|
||||
) async {
|
||||
int chain, {
|
||||
required bool secure,
|
||||
}) async {
|
||||
final List<Address> addressArray = [];
|
||||
int gapCounter = 0;
|
||||
int index = 0;
|
||||
int index = secure ? kFrostSecureStartingIndex : 0;
|
||||
for (; gapCounter < 20; index++) {
|
||||
Logging.instance.log(
|
||||
"Frost index: $index, \t GapCounter chain=$chain: $gapCounter",
|
||||
|
@ -1606,6 +1732,7 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
change: chain,
|
||||
index: index,
|
||||
serializedKeys: serializedKeys,
|
||||
secure: secure,
|
||||
);
|
||||
} on FrostdartException catch (e) {
|
||||
if (e.errorCode == 72) {
|
||||
|
@ -1620,13 +1747,13 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
|
||||
// get address tx count
|
||||
final count = await _fetchTxCount(
|
||||
address: address!,
|
||||
address: address,
|
||||
);
|
||||
|
||||
// check and add appropriate addresses
|
||||
if (count > 0) {
|
||||
// add address to array
|
||||
addressArray.add(address!);
|
||||
addressArray.add(address);
|
||||
// reset counter
|
||||
gapCounter = 0;
|
||||
// add info to derivations
|
||||
|
|
Loading…
Reference in a new issue