refactor: use Option<String> for SendResult.transaction_id
This commit is contained in:
@@ -987,15 +987,21 @@ class WalletProvider extends ChangeNotifier {
|
||||
|
||||
// Save token metadata using the deterministic transaction ID returned by CDK
|
||||
// (SHA-256 of sorted proof Y values — no racy listTransactions needed)
|
||||
if (result.transactionId.isNotEmpty) {
|
||||
await _txMetaStorage.save(
|
||||
result.transactionId,
|
||||
TransactionMeta(
|
||||
type: TransactionType.cashu,
|
||||
token: result.token.encoded,
|
||||
),
|
||||
);
|
||||
debugPrint('Token guardado para tx ${result.transactionId}');
|
||||
// Best-effort: don't fail the send if metadata persistence fails
|
||||
final txId = result.transactionId;
|
||||
if (txId != null && txId.isNotEmpty) {
|
||||
try {
|
||||
await _txMetaStorage.save(
|
||||
txId,
|
||||
TransactionMeta(
|
||||
type: TransactionType.cashu,
|
||||
token: result.token.encoded,
|
||||
),
|
||||
);
|
||||
debugPrint('Token guardado para tx $txId');
|
||||
} catch (e) {
|
||||
debugPrint('Error guardando send metadata: $e');
|
||||
}
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
@@ -1124,7 +1130,7 @@ class WalletProvider extends ChangeNotifier {
|
||||
amount: amount,
|
||||
description: description,
|
||||
).listen(
|
||||
(quote) {
|
||||
(quote) async {
|
||||
// Guardar invoice temprano en SharedPreferences
|
||||
if (quote.state == MintQuoteState.unpaid) {
|
||||
invoiceBolt11 = quote.request;
|
||||
@@ -1133,8 +1139,10 @@ class WalletProvider extends ChangeNotifier {
|
||||
|
||||
// Cuando se completa, guardar metadata, confetti, limpiar pending
|
||||
if (quote.state == MintQuoteState.issued && invoiceBolt11 != null) {
|
||||
_saveMintMetadata(wallet, invoiceBolt11!, quote.transactionId);
|
||||
_removePendingMintInvoice(quote.id);
|
||||
final saved = await _saveMintMetadata(wallet, invoiceBolt11!, quote.transactionId);
|
||||
// Only remove pending invoice if metadata was saved;
|
||||
// otherwise _matchPendingMintInvoices can recover it on next startup
|
||||
if (saved) _removePendingMintInvoice(quote.id);
|
||||
}
|
||||
|
||||
// Reenviar a la UI (si sigue escuchando)
|
||||
@@ -1368,8 +1376,8 @@ class WalletProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
/// Guarda metadata para una transacción de mint (Lightning deposit).
|
||||
/// Uses the deterministic transaction ID from CDK when available.
|
||||
Future<void> _saveMintMetadata(Wallet wallet, String invoice, String? transactionId) async {
|
||||
/// Returns true if metadata was actually saved.
|
||||
Future<bool> _saveMintMetadata(Wallet wallet, String invoice, String? transactionId) async {
|
||||
try {
|
||||
if (transactionId != null && transactionId.isNotEmpty) {
|
||||
await _txMetaStorage.save(
|
||||
@@ -1380,13 +1388,18 @@ class WalletProvider extends ChangeNotifier {
|
||||
),
|
||||
);
|
||||
debugPrint('Mint metadata guardada para tx $transactionId');
|
||||
confettiController.fire();
|
||||
notifyListeners();
|
||||
return true;
|
||||
} else {
|
||||
debugPrint('Mint metadata: no transaction ID available');
|
||||
confettiController.fire();
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
confettiController.fire();
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
debugPrint('Error guardando mint metadata: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -271,9 +271,11 @@ class SendOptions {
|
||||
/// listTransactions lookup.
|
||||
class SendResult {
|
||||
final Token token;
|
||||
final String transactionId;
|
||||
|
||||
const SendResult({required this.token, required this.transactionId});
|
||||
/// Deterministic transaction ID (None if computation failed)
|
||||
final String? transactionId;
|
||||
|
||||
const SendResult({required this.token, this.transactionId});
|
||||
|
||||
@override
|
||||
int get hashCode => token.hashCode ^ transactionId.hashCode;
|
||||
|
||||
@@ -3298,7 +3298,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
throw Exception('unexpected arr length: expect 2 but see ${arr.length}');
|
||||
return SendResult(
|
||||
token: dco_decode_token(arr[0]),
|
||||
transactionId: dco_decode_String(arr[1]),
|
||||
transactionId: dco_decode_opt_String(arr[1]),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4398,7 +4398,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
SendResult sse_decode_send_result(SseDeserializer deserializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
var var_token = sse_decode_token(deserializer);
|
||||
var var_transactionId = sse_decode_String(deserializer);
|
||||
var var_transactionId = sse_decode_opt_String(deserializer);
|
||||
return SendResult(token: var_token, transactionId: var_transactionId);
|
||||
}
|
||||
|
||||
@@ -5493,7 +5493,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
|
||||
void sse_encode_send_result(SendResult self, SseSerializer serializer) {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
sse_encode_token(self.token, serializer);
|
||||
sse_encode_String(self.transactionId, serializer);
|
||||
sse_encode_opt_String(self.transactionId, serializer);
|
||||
}
|
||||
|
||||
@protected
|
||||
|
||||
@@ -158,7 +158,7 @@ impl Wallet {
|
||||
let proofs = cdk_token.proofs(&keysets)?;
|
||||
let tx_id = TransactionId::try_from(proofs)
|
||||
.map(|id| id.to_string())
|
||||
.unwrap_or_default();
|
||||
.ok();
|
||||
|
||||
let token_str = cdk_token.to_string();
|
||||
self.update_balance_streams().await;
|
||||
@@ -500,7 +500,8 @@ impl Wallet {
|
||||
/// listTransactions lookup.
|
||||
pub struct SendResult {
|
||||
pub token: Token,
|
||||
pub transaction_id: String,
|
||||
/// Deterministic transaction ID (None if computation failed)
|
||||
pub transaction_id: Option<String>,
|
||||
}
|
||||
|
||||
pub struct MintQuote {
|
||||
|
||||
@@ -3954,7 +3954,7 @@ impl SseDecode for crate::api::wallet::SendResult {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
|
||||
let mut var_token = <crate::api::token::Token>::sse_decode(deserializer);
|
||||
let mut var_transactionId = <String>::sse_decode(deserializer);
|
||||
let mut var_transactionId = <Option<String>>::sse_decode(deserializer);
|
||||
return crate::api::wallet::SendResult {
|
||||
token: var_token,
|
||||
transaction_id: var_transactionId,
|
||||
@@ -5609,7 +5609,7 @@ impl SseEncode for crate::api::wallet::SendResult {
|
||||
// Codec=Sse (Serialization based), see doc to use other codecs
|
||||
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
|
||||
<crate::api::token::Token>::sse_encode(self.token, serializer);
|
||||
<String>::sse_encode(self.transaction_id, serializer);
|
||||
<Option<String>>::sse_encode(self.transaction_id, serializer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user