WIP spark interface

This commit is contained in:
julian 2023-11-27 14:57:33 -06:00
parent c1be34e9cb
commit 3cc0ebce26
3 changed files with 147 additions and 2 deletions
lib
models/isar/models/blockchain_data
wallets/wallet
impl
wallet_mixin_interfaces

View file

@ -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,9 @@ enum AddressType {
nonWallet,
ethereum,
nano,
banano;
banano,
spark,
;
String get readableName {
switch (this) {
@ -183,6 +185,8 @@ enum AddressType {
return "Nano";
case AddressType.banano:
return "Banano";
case AddressType.spark:
return "Spark";
}
}
}

View file

@ -18,8 +18,13 @@ import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/lelantus_inte
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
import 'package:tuple/tuple.dart';
const sparkStartBlock = 819300; // (approx 18 Jan 2024)
class FiroWallet extends Bip39HDWallet
with ElectrumXInterface, LelantusInterface, SparkInterface {
// IMPORTANT: The order of the above mixins matters.
// SparkInterface MUST come after LelantusInterface.
FiroWallet(CryptoCurrencyNetwork network) : super(Firo(network));
@override

View file

@ -1,11 +1,147 @@
import 'dart:typed_data';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart';
mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
Future<Address?> getCurrentReceivingSparkAddress() async {
return await mainDB.isar.addresses
.where()
.walletIdEqualTo(walletId)
.filter()
.typeEqualTo(AddressType.spark)
.sortByDerivationIndexDesc()
.findFirst();
}
Future<Uint8List> _getSpendKey() async {
final mnemonic = await getMnemonic();
final mnemonicPassphrase = await getMnemonicPassphrase();
// TODO call ffi lib to generate spend key
throw UnimplementedError();
}
Future<Address> generateNextSparkAddress() async {
final highestStoredDiversifier =
(await getCurrentReceivingSparkAddress())?.derivationIndex;
// default to starting at 1 if none found
final int diversifier = (highestStoredDiversifier ?? 0) + 1;
// TODO: use real data
final String derivationPath = "";
final Uint8List publicKey = Uint8List(0); // incomingViewKey?
final String addressString = "";
return Address(
walletId: walletId,
value: addressString,
publicKey: publicKey,
derivationIndex: diversifier,
derivationPath: DerivationPath()..value = derivationPath,
type: AddressType.spark,
subType: AddressSubType.receiving,
);
}
Future<Amount> estimateFeeForSpark(Amount amount) async {
throw UnimplementedError();
}
Future<TxData> prepareSendSpark({
required TxData txData,
}) async {
throw UnimplementedError();
}
Future<TxData> confirmSendSpark({
required TxData txData,
}) async {
throw UnimplementedError();
}
// TODO lots of room for performance improvements here. Should be similar to
// recoverSparkWallet but only fetch and check anonymity set data that we
// have not yet parsed.
Future<void> refreshSparkData() async {
try {
final latestSparkCoinId = await electrumXClient.getSparkLatestCoinId();
// TODO improve performance by adding this call to the cached client
final anonymitySet = await electrumXClient.getSparkAnonymitySet(
coinGroupId: latestSparkCoinId.toString(),
);
// TODO loop over set and see which coins are ours using the FFI call `identifyCoin`
List myCoins = [];
// fetch metadata for myCoins
// create list of Spark Coin isar objects
// update wallet spark coins in isar
// refresh spark balance?
throw UnimplementedError();
} catch (e, s) {
// todo logging
rethrow;
}
}
/// Should only be called within the standard wallet [recover] function due to
/// mutex locking. Otherwise behaviour MAY be undefined.
Future<void> recoverSparkWallet(
// {
// required int latestSetId,
// required Map<dynamic, dynamic> setDataMap,
// required Set<String> usedSerialNumbers,
// }
) async {
try {
// do we need to generate any spark address(es) here?
final latestSparkCoinId = await electrumXClient.getSparkLatestCoinId();
// TODO improve performance by adding this call to the cached client
final anonymitySet = await electrumXClient.getSparkAnonymitySet(
coinGroupId: latestSparkCoinId.toString(),
);
// TODO loop over set and see which coins are ours using the FFI call `identifyCoin`
List myCoins = [];
// fetch metadata for myCoins
// create list of Spark Coin isar objects
// update wallet spark coins in isar
throw UnimplementedError();
} catch (e, s) {
// todo logging
rethrow;
}
}
@override
Future<void> updateBalance() async {
// call to super to update transparent balance (and lelantus balance if
// what ever class this mixin is used on uses LelantusInterface as well)
final normalBalanceFuture = super.updateBalance();
throw UnimplementedError();
// wait for normalBalanceFuture to complete before returning
await normalBalanceFuture;
}
}