2023-10-30 20:02:33 +00:00
|
|
|
import 'package:coinlib_flutter/coinlib_flutter.dart' as coinlib;
|
2023-09-18 21:28:31 +00:00
|
|
|
import 'package:crypto/crypto.dart';
|
|
|
|
import 'package:flutter/foundation.dart';
|
2023-10-22 00:35:15 +00:00
|
|
|
|
2024-05-23 00:37:06 +00:00
|
|
|
import '../../../models/isar/models/blockchain_data/address.dart';
|
|
|
|
import '../../../utilities/amount/amount.dart';
|
|
|
|
import '../../../utilities/enums/derive_path_type_enum.dart';
|
2024-11-13 00:45:17 +00:00
|
|
|
import '../interfaces/view_only_option_currency_interface.dart';
|
2024-05-23 00:37:06 +00:00
|
|
|
import 'bip39_currency.dart';
|
2023-09-18 21:28:31 +00:00
|
|
|
|
2024-11-13 00:45:17 +00:00
|
|
|
abstract class Bip39HDCurrency extends Bip39Currency
|
|
|
|
implements ViewOnlyOptionCurrencyInterface {
|
2023-09-18 21:28:31 +00:00
|
|
|
Bip39HDCurrency(super.network);
|
|
|
|
|
2024-03-22 21:19:48 +00:00
|
|
|
coinlib.Network get networkParams;
|
2023-09-18 21:28:31 +00:00
|
|
|
|
|
|
|
Amount get dustLimit;
|
|
|
|
|
2023-11-07 18:19:42 +00:00
|
|
|
List<DerivePathType> get supportedDerivationPathTypes;
|
|
|
|
|
|
|
|
int get maxUnusedAddressGap => 50;
|
|
|
|
|
2023-09-18 21:28:31 +00:00
|
|
|
String constructDerivePath({
|
|
|
|
required DerivePathType derivePathType,
|
|
|
|
int account = 0,
|
|
|
|
required int chain,
|
|
|
|
required int index,
|
|
|
|
});
|
|
|
|
|
|
|
|
({coinlib.Address address, AddressType addressType}) getAddressForPublicKey({
|
|
|
|
required coinlib.ECPublicKey publicKey,
|
|
|
|
required DerivePathType derivePathType,
|
|
|
|
});
|
|
|
|
|
|
|
|
String addressToScriptHash({required String address}) {
|
|
|
|
try {
|
|
|
|
final addr = coinlib.Address.fromString(address, networkParams);
|
|
|
|
return convertBytesToScriptHash(addr.program.script.compiled);
|
|
|
|
} catch (e) {
|
|
|
|
rethrow;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-13 00:45:17 +00:00
|
|
|
List<String> get supportedHardenedDerivationPaths {
|
|
|
|
final paths = supportedDerivationPathTypes.map(
|
|
|
|
(e) => (
|
|
|
|
path: e,
|
|
|
|
addressType: e.getAddressType(),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
return paths.map((e) {
|
|
|
|
final path = constructDerivePath(
|
|
|
|
derivePathType: e.path,
|
|
|
|
chain: 0,
|
|
|
|
index: 0,
|
|
|
|
);
|
|
|
|
// trim unhardened
|
|
|
|
return path.substring(0, path.lastIndexOf("'") + 1);
|
|
|
|
}).toList();
|
|
|
|
}
|
|
|
|
|
2023-09-18 21:28:31 +00:00
|
|
|
static String convertBytesToScriptHash(Uint8List bytes) {
|
|
|
|
final hash = sha256.convert(bytes.toList(growable: false)).toString();
|
|
|
|
|
|
|
|
final chars = hash.split("");
|
|
|
|
final List<String> reversedPairs = [];
|
|
|
|
// TODO find a better/faster way to do this?
|
|
|
|
int i = chars.length - 1;
|
|
|
|
while (i > 0) {
|
|
|
|
reversedPairs.add(chars[i - 1]);
|
|
|
|
reversedPairs.add(chars[i]);
|
|
|
|
i -= 2;
|
|
|
|
}
|
|
|
|
return reversedPairs.join("");
|
|
|
|
}
|
2023-10-30 22:58:15 +00:00
|
|
|
|
|
|
|
DerivePathType addressType({required String address}) {
|
2024-04-12 20:57:41 +00:00
|
|
|
final address2 = coinlib.Address.fromString(address, networkParams);
|
2024-03-26 21:05:16 +00:00
|
|
|
|
2024-04-12 20:57:41 +00:00
|
|
|
if (address2 is coinlib.P2PKHAddress) {
|
|
|
|
return DerivePathType.bip44;
|
|
|
|
} else if (address2 is coinlib.P2SHAddress) {
|
|
|
|
return DerivePathType.bip49;
|
|
|
|
} else if (address2 is coinlib.P2WPKHAddress) {
|
2023-10-30 22:58:15 +00:00
|
|
|
return DerivePathType.bip84;
|
2024-04-12 20:57:41 +00:00
|
|
|
} else if (address2 is coinlib.P2TRAddress) {
|
|
|
|
return DerivePathType.bip86;
|
|
|
|
} else {
|
|
|
|
// TODO: [prio=med] better error handling
|
|
|
|
throw ArgumentError('Invalid address');
|
2023-10-30 22:58:15 +00:00
|
|
|
}
|
|
|
|
}
|
2023-09-18 21:28:31 +00:00
|
|
|
}
|