WIP database schema for spark coin data

This commit is contained in:
julian 2023-12-04 09:35:59 -06:00
parent 734e9d90b1
commit 9ad723a5b2
3 changed files with 3023 additions and 12 deletions

View file

@ -0,0 +1,126 @@
import 'package:isar/isar.dart';
part 'spark_coin.g.dart';
enum SparkCoinType {
mint(0),
spend(1);
const SparkCoinType(this.value);
final int value;
}
@Collection()
class SparkCoin {
Id id = Isar.autoIncrement;
@Index(
unique: true,
replace: true,
composite: [
CompositeIndex("lTagHash"),
],
)
final String walletId;
@enumerated
final SparkCoinType type;
final bool isUsed;
final List<int>? k; // TODO: proper name (not single char!!) is this nonce???
final String address;
final String txHash;
final String valueIntString;
final String? memo;
final List<int>? serialContext;
final String diversifierIntString;
final List<int>? encryptedDiversifier;
final List<int>? serial;
final List<int>? tag;
final String lTagHash;
@ignore
BigInt get value => BigInt.parse(valueIntString);
@ignore
BigInt get diversifier => BigInt.parse(diversifierIntString);
SparkCoin({
required this.walletId,
required this.type,
required this.isUsed,
this.k,
required this.address,
required this.txHash,
required this.valueIntString,
this.memo,
this.serialContext,
required this.diversifierIntString,
this.encryptedDiversifier,
this.serial,
this.tag,
required this.lTagHash,
});
SparkCoin copyWith({
SparkCoinType? type,
bool? isUsed,
List<int>? k,
String? address,
String? txHash,
BigInt? value,
String? memo,
List<int>? serialContext,
BigInt? diversifier,
List<int>? encryptedDiversifier,
List<int>? serial,
List<int>? tag,
String? lTagHash,
}) {
return SparkCoin(
walletId: walletId,
type: type ?? this.type,
isUsed: isUsed ?? this.isUsed,
k: k ?? this.k,
address: address ?? this.address,
txHash: txHash ?? this.txHash,
valueIntString: value?.toString() ?? this.value.toString(),
memo: memo ?? this.memo,
serialContext: serialContext ?? this.serialContext,
diversifierIntString:
diversifier?.toString() ?? this.diversifier.toString(),
encryptedDiversifier: encryptedDiversifier ?? this.encryptedDiversifier,
serial: serial ?? this.serial,
tag: tag ?? this.tag,
lTagHash: lTagHash ?? this.lTagHash,
);
}
@override
String toString() {
return 'SparkCoin('
', walletId: $walletId'
', type: $type'
', isUsed: $isUsed'
', k: $k'
', address: $address'
', txHash: $txHash'
', value: $value'
', memo: $memo'
', serialContext: $serialContext'
', diversifier: $diversifier'
', encryptedDiversifier: $encryptedDiversifier'
', serial: $serial'
', tag: $tag'
', lTagHash: $lTagHash'
')';
}
}

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,9 @@ import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart';
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/utilities/extensions/impl/uint8_list.dart';
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
import 'package:stackwallet/wallets/isar/models/spark_coin.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';
@ -151,26 +153,81 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
// have not yet parsed.
Future<void> refreshSparkData() async {
try {
final privateKeyHex = "TODO";
final index = 0;
final latestSparkCoinId = await electrumXClient.getSparkLatestCoinId();
// TODO improve performance by adding this call to the cached client
final anonymitySet = await electrumXClient.getSparkAnonymitySet(
// TODO improve performance by adding these calls to the cached client
final futureResults = await Future.wait([
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
// check against spent list (this call could possibly also be cached later on)
final spentCoinTags = await electrumXClient.getSparkUsedCoinsTags(
),
electrumXClient.getSparkUsedCoinsTags(
startNumber: 0,
),
]);
final anonymitySet = futureResults[0];
final spentCoinTags = List<String>.from(
futureResults[1]["tags"] as List,
).toSet();
// find our coins
final List<SparkCoin> myCoins = [];
for (final data
in List<List<String>>.from(anonymitySet["coin"] as List)) {
if (data.length != 2) {
throw Exception("Unexpected serialized coin info found");
}
final serializedCoin = data.first;
final txHash = data.last;
final coin = LibSpark.identifyAndRecoverCoin(
serializedCoin,
privateKeyHex: privateKeyHex,
index: index,
);
// create list of Spark Coin isar objects
// its ours
if (coin != null) {
final SparkCoinType coinType;
switch (coin.type.value) {
case 0:
coinType = SparkCoinType.mint;
case 1:
coinType = SparkCoinType.spend;
default:
throw Exception("Unknown spark coin type detected");
}
myCoins.add(
SparkCoin(
walletId: walletId,
type: coinType,
isUsed: spentCoinTags
.contains(coin.lTagHash!.toHex), // TODO: is hex right?
address: coin.address!,
txHash: txHash,
valueIntString: coin.value!.toString(),
lTagHash: coin.lTagHash!.toHex, // TODO: is hex right?
tag: coin.tag,
memo: coin.memo,
serial: coin.serial,
serialContext: coin.serialContext,
diversifierIntString: coin.diversifier!.toString(),
encryptedDiversifier: coin.encryptedDiversifier,
),
);
}
}
// update wallet spark coins in isar
if (myCoins.isNotEmpty) {
await mainDB.isar.writeTxn(() async {
await mainDB.isar.sparkCoins.putAll(myCoins);
});
}
// refresh spark balance?