refactor: recover mint quotes by quote_id (closes #118)

This commit is contained in:
Forte11Cuba
2026-04-19 06:03:21 -06:00
parent 09565aa3ed
commit dd9450c0cc
8 changed files with 615 additions and 239 deletions
+50 -138
View File
@@ -87,8 +87,8 @@ class WalletProvider extends ChangeNotifier {
static const _mintsKey = 'wallet_mints';
static const _activeMintKey = 'wallet_active_mint';
static const _activeUnitKey = 'wallet_active_unit';
static const _pendingMintInvoicesKey = 'pending_mint_invoices';
static const _pendingNostrRequestKey = 'pending_nostr_request';
static const _legacyPendingMintInvoicesKey = 'pending_mint_invoices';
/// Mint de Cuba Bitcoin - siempre aparece primero en la lista
static const cubaBitcoinMint = 'https://mint.cubabitcoin.org';
@@ -1330,8 +1330,6 @@ class WalletProvider extends ChangeNotifier {
throw Exception('No hay wallet activo');
}
final mintUrl = _activeMintUrl!;
final unit = _activeUnit;
String? invoiceBolt11;
// Cerrar controller anterior si existe (evitar leak)
@@ -1355,10 +1353,8 @@ class WalletProvider extends ChangeNotifier {
description: description,
).listen(
(quote) {
// Guardar invoice temprano en SharedPreferences
if (quote.state == MintQuoteState.unpaid) {
invoiceBolt11 = quote.request;
_savePendingMintInvoice(quote.id, quote.request, mintUrl, unit, amount);
}
// Reenviar a la UI ANTES de cualquier await: Rust cierra el stream
@@ -1372,13 +1368,7 @@ class WalletProvider extends ChangeNotifier {
// Metadata async fire-and-forget (no bloquea el forward)
if (quote.state == MintQuoteState.issued && invoiceBolt11 != null) {
final invoice = invoiceBolt11!;
unawaited(
_saveMintMetadata(wallet, invoice, quote.transactionId).then((saved) {
// Only remove pending invoice if metadata was saved;
// otherwise _matchPendingMintInvoices can recover it on next startup
if (saved) _removePendingMintInvoice(quote.id);
}),
);
unawaited(_saveMintMetadata(wallet, invoice, quote.transactionId));
}
},
onError: (error) {
@@ -1397,91 +1387,63 @@ class WalletProvider extends ChangeNotifier {
return controller.stream;
}
/// Guarda un invoice de mint pendiente para recuperarlo después.
Future<void> _savePendingMintInvoice(
String quoteId, String invoice, String mintUrl, String unit, BigInt amount,
) async {
/// Exact recovery of paid-but-unissued mint quotes using `quote_id`.
///
/// Replaces the old heuristic that matched by (mintUrl, unit, amount) and
/// could pair a freshly created invoice to an unrelated orphan transaction
/// of the same amount. For every unissued quote the CDK knows about, we
/// ask the mint for the current state and — if Paid — issue the proofs,
/// linking the resulting tx_id to its bolt11 in TransactionMeta.
Future<void> _recoverPendingMintQuotes() async {
// One-time cleanup of the legacy SharedPreferences state (no-op after
// the first run). Only writes when the key is actually present.
try {
final prefs = await SharedPreferences.getInstance();
final jsonStr = prefs.getString(_pendingMintInvoicesKey) ?? '{}';
final map = Map<String, dynamic>.from(jsonDecode(jsonStr));
map[quoteId] = {
'invoice': invoice,
'mintUrl': mintUrl,
'unit': unit,
'amount': amount.toString(),
'createdAt': DateTime.now().toIso8601String(),
};
await prefs.setString(_pendingMintInvoicesKey, jsonEncode(map));
debugPrint('Pending mint invoice guardado: $quoteId');
if (prefs.getString(_legacyPendingMintInvoicesKey) != null) {
await prefs.remove(_legacyPendingMintInvoicesKey);
debugPrint('Removed legacy $_legacyPendingMintInvoicesKey from prefs');
}
} catch (e) {
debugPrint('Error guardando pending mint invoice: $e');
debugPrint('Legacy pending-invoices cleanup failed: $e');
}
}
/// Elimina un invoice de mint pendiente (ya fue procesado).
Future<void> _removePendingMintInvoice(String quoteId) async {
try {
final prefs = await SharedPreferences.getInstance();
final jsonStr = prefs.getString(_pendingMintInvoicesKey) ?? '{}';
final map = Map<String, dynamic>.from(jsonDecode(jsonStr));
map.remove(quoteId);
await prefs.setString(_pendingMintInvoicesKey, jsonEncode(map));
debugPrint('Pending mint invoice eliminado: $quoteId');
} catch (e) {
debugPrint('Error eliminando pending mint invoice: $e');
}
}
for (final entry in _mintUnits.entries) {
for (final unit in entry.value) {
try {
final wallet = await getWallet(entry.key, unit);
final pending = await wallet.getUnissuedMintQuotes();
for (final quote in pending) {
try {
final updated = await wallet.checkMintQuoteStatus(quoteId: quote.id);
if (updated.state != MintQuoteState.paid) continue;
/// TTL para invoices de mint pendientes (24 horas).
static const _pendingMintInvoiceTtl = Duration(hours: 24);
/// Obtiene todos los invoices de mint pendientes, limpiando expirados.
Future<Map<String, dynamic>> _getPendingMintInvoices() async {
try {
final prefs = await SharedPreferences.getInstance();
final jsonStr = prefs.getString(_pendingMintInvoicesKey) ?? '{}';
final map = Map<String, dynamic>.from(jsonDecode(jsonStr));
// Filtrar expirados
final now = DateTime.now();
final expired = <String>[];
for (final entry in map.entries) {
final data = Map<String, dynamic>.from(entry.value);
final createdAt = DateTime.tryParse(data['createdAt'] ?? '');
if (createdAt == null || now.difference(createdAt) > _pendingMintInvoiceTtl) {
expired.add(entry.key);
final minted = await wallet.mintByQuoteId(quoteId: quote.id);
final txId = minted.transactionId;
if (txId != null && txId.isNotEmpty) {
await _txMetaStorage.save(
txId,
TransactionMeta(
type: TransactionType.lightning,
invoice: updated.request,
),
);
debugPrint('Recovered mint quote ${quote.id} → tx $txId');
} else {
debugPrint('Recovered mint quote ${quote.id} but no tx_id');
}
confettiController.fire();
notifyListeners();
} catch (e) {
debugPrint('Recover quote ${quote.id} failed: $e');
}
}
} catch (e) {
debugPrint('Recover quotes for ${entry.key}/$unit failed: $e');
}
}
// Limpiar expirados si hay
if (expired.isNotEmpty) {
for (final key in expired) {
map.remove(key);
}
await prefs.setString(_pendingMintInvoicesKey, jsonEncode(map));
debugPrint('Pending mint invoices expirados eliminados: ${expired.length}');
}
return map;
} catch (e) {
return {};
}
}
/// Busca un invoice pendiente que coincida con un mintUrl y unit.
/// Retorna el invoice string o null.
Future<String?> findPendingMintInvoice(String mintUrl, String unit) async {
final pending = await _getPendingMintInvoices();
for (final entry in pending.values) {
final data = Map<String, dynamic>.from(entry);
if (data['mintUrl'] == mintUrl && data['unit'] == unit) {
return data['invoice'] as String?;
}
}
return null;
}
// ============================================================
// PENDING NOSTR PAYMENT REQUESTS
// ============================================================
@@ -1916,63 +1878,13 @@ class WalletProvider extends ChangeNotifier {
}
}
// Vincular transacciones incoming sin metadata con pending invoices
await _matchPendingMintInvoices();
// Recover paid-but-unissued quotes by quote_id (exact, no heuristics)
await _recoverPendingMintQuotes();
// Resume pending Nostr payment request if app was killed mid-wait
await resumePendingNostrRequest();
}
/// Busca transacciones incoming sin metadata y las vincula con
/// invoices de mint pendientes guardados en SharedPreferences.
Future<void> _matchPendingMintInvoices() async {
try {
final pending = await _getPendingMintInvoices();
if (pending.isEmpty) return;
// Obtener todas las transacciones incoming
final allTxs = await getAllTransactions(
direction: TransactionDirection.incoming,
);
for (final tx in allTxs) {
// Solo procesar transacciones sin metadata
if (_txMetaStorage.has(tx.id)) continue;
// Buscar un pending invoice que coincida con mintUrl, unit y amount
String? matchedQuoteId;
String? matchedInvoice;
for (final entry in pending.entries) {
final data = Map<String, dynamic>.from(entry.value);
if (data['mintUrl'] == tx.mintUrl && data['unit'] == tx.unit && data['amount'] == tx.amount.toString()) {
matchedQuoteId = entry.key;
matchedInvoice = data['invoice'] as String?;
break;
}
}
if (matchedQuoteId != null && matchedInvoice != null) {
await _txMetaStorage.save(
tx.id,
TransactionMeta(
type: TransactionType.lightning,
invoice: matchedInvoice,
),
);
// Limpiar el pending invoice ya vinculado
await _removePendingMintInvoice(matchedQuoteId);
pending.remove(matchedQuoteId);
debugPrint('Matched pending mint invoice → tx ${tx.id}');
confettiController.fire();
notifyListeners();
}
}
} catch (e) {
debugPrint('Error matching pending mint invoices: $e');
}
}
/// Verifica si un token específico fue gastado.
Future<bool> isTokenSpent(String encodedToken) async {
final wallet = activeWallet;
+1 -27
View File
@@ -782,7 +782,6 @@ class _TransactionDetailScreenState extends State<_TransactionDetailScreen> {
late final bool _isLightning;
String? _tokenOrInvoice;
late final bool _shouldShowQR;
bool _isLoadingPendingInvoice = false;
bool _isReclaiming = false;
@override
@@ -795,11 +794,6 @@ class _TransactionDetailScreenState extends State<_TransactionDetailScreen> {
final meta = widget.walletProvider.getTransactionMeta(widget.transaction.id);
_tokenOrInvoice = meta?.token ?? meta?.invoice;
// Si es Lightning incoming sin invoice, buscar en pending mint invoices
if (_tokenOrInvoice == null && _isLightning && _isIncoming) {
_loadPendingMintInvoice();
}
// Mostrar QR para todo EXCEPTO Lightning saliente
_shouldShowQR = !_isLightning || _isIncoming;
@@ -809,26 +803,6 @@ class _TransactionDetailScreenState extends State<_TransactionDetailScreen> {
}
}
/// Busca el invoice en pending mint invoices si no hay metadata.
Future<void> _loadPendingMintInvoice() async {
setState(() => _isLoadingPendingInvoice = true);
String? invoice;
try {
invoice = await widget.walletProvider.findPendingMintInvoice(
widget.transaction.mintUrl,
widget.transaction.unit,
);
} catch (e, st) {
debugPrint('findPendingMintInvoice failed: $e\n$st');
}
if (mounted) {
setState(() {
_isLoadingPendingInvoice = false;
if (invoice != null) _tokenOrInvoice = invoice;
});
}
}
@override
void dispose() {
_animationTimer?.cancel();
@@ -968,7 +942,7 @@ class _TransactionDetailScreenState extends State<_TransactionDetailScreen> {
],
// Mensaje si no hay token/invoice (ocultar mientras carga)
if (_tokenOrInvoice == null && !_isLoadingPendingInvoice) ...[
if (_tokenOrInvoice == null) ...[
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
+15
View File
@@ -70,6 +70,11 @@ abstract class Wallet implements RustOpaqueInterface {
Future<void> checkAllMintQuotes();
/// Ask the mint for the current state of a single quote by id and
/// return the refreshed MintQuote. Local store is updated as a side
/// effect inside CDK.
Future<MintQuote> checkMintQuoteStatus({required String quoteId});
Future<void> checkPendingTransactions();
/// Observe-only counterpart of `reclaim_proofs_by_ys`. Queries the mint
@@ -105,6 +110,10 @@ abstract class Wallet implements RustOpaqueInterface {
Future<MintInfo?> getMint();
/// Return pending (unissued) mint quotes known to the local store,
/// filtered to this wallet's mint/unit.
Future<List<MintQuote>> getUnissuedMintQuotes();
Future<bool> isTokenSpent({required Token token});
Future<List<Transaction>> listTransactions({TransactionDirection? direction});
@@ -113,6 +122,12 @@ abstract class Wallet implements RustOpaqueInterface {
Stream<MintQuote> mint({required BigInt amount, String? description});
/// Mint proofs for a paid quote and return an Issued MintQuote with
/// `transaction_id` and `token` populated — same shape the `mint()`
/// stream emits on Issued. Use this to recover metadata for quotes
/// that were paid while the app was killed.
Future<MintQuote> mintByQuoteId({required String quoteId});
factory Wallet({
required String mintUrl,
required String unit,
+215 -37
View File
@@ -69,7 +69,7 @@ class RustLib extends BaseEntrypoint<RustLibApi, RustLibApiImpl, RustLibWire> {
String get codegenVersion => '2.11.1';
@override
int get rustContentHash => 1593022460;
int get rustContentHash => 884570592;
static const kDefaultExternalLibraryLoaderConfig =
ExternalLibraryLoaderConfig(
@@ -246,6 +246,11 @@ abstract class RustLibApi extends BaseApi {
Future<void> crateApiWalletWalletCheckAllMintQuotes({required Wallet that});
Future<MintQuote> crateApiWalletWalletCheckMintQuoteStatus({
required Wallet that,
required String quoteId,
});
Future<void> crateApiWalletWalletCheckPendingTransactions({
required Wallet that,
});
@@ -269,6 +274,10 @@ abstract class RustLibApi extends BaseApi {
Future<MintInfo?> crateApiWalletWalletGetMint({required Wallet that});
Future<List<MintQuote>> crateApiWalletWalletGetUnissuedMintQuotes({
required Wallet that,
});
Future<bool> crateApiWalletWalletIsTokenSpent({
required Wallet that,
required Token token,
@@ -290,6 +299,11 @@ abstract class RustLibApi extends BaseApi {
String? description,
});
Future<MintQuote> crateApiWalletWalletMintByQuoteId({
required Wallet that,
required String quoteId,
});
Wallet crateApiWalletWalletNew({
required String mintUrl,
required String unit,
@@ -1772,6 +1786,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
argNames: ["that"],
);
@override
Future<MintQuote> crateApiWalletWalletCheckMintQuoteStatus({
required Wallet that,
required String quoteId,
}) {
return handler.executeNormal(
NormalTask(
callFfi: (port_) {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerWallet(
that,
serializer,
);
sse_encode_String(quoteId, serializer);
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 41,
port: port_,
);
},
codec: SseCodec(
decodeSuccessData: sse_decode_mint_quote,
decodeErrorData: sse_decode_error,
),
constMeta: kCrateApiWalletWalletCheckMintQuoteStatusConstMeta,
argValues: [that, quoteId],
apiImpl: this,
),
);
}
TaskConstMeta get kCrateApiWalletWalletCheckMintQuoteStatusConstMeta =>
const TaskConstMeta(
debugName: "Wallet_check_mint_quote_status",
argNames: ["that", "quoteId"],
);
@override
Future<void> crateApiWalletWalletCheckPendingTransactions({
required Wallet that,
@@ -1787,7 +1839,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 41,
funcId: 42,
port: port_,
);
},
@@ -1825,7 +1877,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 42,
funcId: 43,
port: port_,
);
},
@@ -1866,7 +1918,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 43,
funcId: 44,
port: port_,
);
},
@@ -1904,7 +1956,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 44,
funcId: 45,
port: port_,
);
},
@@ -1941,7 +1993,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 45,
funcId: 46,
port: port_,
);
},
@@ -1975,7 +2027,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 46,
funcId: 47,
port: port_,
);
},
@@ -1993,6 +2045,42 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
TaskConstMeta get kCrateApiWalletWalletGetMintConstMeta =>
const TaskConstMeta(debugName: "Wallet_get_mint", argNames: ["that"]);
@override
Future<List<MintQuote>> crateApiWalletWalletGetUnissuedMintQuotes({
required Wallet that,
}) {
return handler.executeNormal(
NormalTask(
callFfi: (port_) {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerWallet(
that,
serializer,
);
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 48,
port: port_,
);
},
codec: SseCodec(
decodeSuccessData: sse_decode_list_mint_quote,
decodeErrorData: sse_decode_error,
),
constMeta: kCrateApiWalletWalletGetUnissuedMintQuotesConstMeta,
argValues: [that],
apiImpl: this,
),
);
}
TaskConstMeta get kCrateApiWalletWalletGetUnissuedMintQuotesConstMeta =>
const TaskConstMeta(
debugName: "Wallet_get_unissued_mint_quotes",
argNames: ["that"],
);
@override
Future<bool> crateApiWalletWalletIsTokenSpent({
required Wallet that,
@@ -2010,7 +2098,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 47,
funcId: 49,
port: port_,
);
},
@@ -2051,7 +2139,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 48,
funcId: 50,
port: port_,
);
},
@@ -2089,7 +2177,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 49,
funcId: 51,
port: port_,
);
},
@@ -2132,7 +2220,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 50,
funcId: 52,
port: port_,
);
},
@@ -2154,6 +2242,44 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
argNames: ["that", "amount", "description", "sink"],
);
@override
Future<MintQuote> crateApiWalletWalletMintByQuoteId({
required Wallet that,
required String quoteId,
}) {
return handler.executeNormal(
NormalTask(
callFfi: (port_) {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_Auto_Ref_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerWallet(
that,
serializer,
);
sse_encode_String(quoteId, serializer);
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 53,
port: port_,
);
},
codec: SseCodec(
decodeSuccessData: sse_decode_mint_quote,
decodeErrorData: sse_decode_error,
),
constMeta: kCrateApiWalletWalletMintByQuoteIdConstMeta,
argValues: [that, quoteId],
apiImpl: this,
),
);
}
TaskConstMeta get kCrateApiWalletWalletMintByQuoteIdConstMeta =>
const TaskConstMeta(
debugName: "Wallet_mint_by_quote_id",
argNames: ["that", "quoteId"],
);
@override
Wallet crateApiWalletWalletNew({
required String mintUrl,
@@ -2174,7 +2300,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
db,
serializer,
);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 51)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 54)!;
},
codec: SseCodec(
decodeSuccessData:
@@ -2212,7 +2338,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 52,
funcId: 55,
port: port_,
);
},
@@ -2250,7 +2376,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 53,
funcId: 56,
port: port_,
);
},
@@ -2291,7 +2417,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 54,
funcId: 57,
port: port_,
);
},
@@ -2332,7 +2458,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 55,
funcId: 58,
port: port_,
);
},
@@ -2368,7 +2494,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 56,
funcId: 59,
port: port_,
);
},
@@ -2406,7 +2532,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 57,
funcId: 60,
port: port_,
);
},
@@ -2442,7 +2568,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 58,
funcId: 61,
port: port_,
);
},
@@ -2476,7 +2602,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 59,
funcId: 62,
port: port_,
);
},
@@ -2510,7 +2636,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 60,
funcId: 63,
port: port_,
);
},
@@ -2552,7 +2678,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 61,
funcId: 64,
port: port_,
);
},
@@ -2588,7 +2714,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 62,
funcId: 65,
port: port_,
);
},
@@ -2634,7 +2760,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 63,
funcId: 66,
port: port_,
);
},
@@ -2672,7 +2798,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
sse_encode_String(proofsJson, serializer);
sse_encode_opt_String(memo, serializer);
sse_encode_opt_String(unit, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 64)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 67)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_token,
@@ -2702,7 +2828,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_box_autoadd_token(token, serializer);
sse_encode_opt_box_autoadd_usize(maxFragmentLength, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 65)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 68)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_list_String,
@@ -2732,7 +2858,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 66,
funcId: 69,
port: port_,
);
},
@@ -2756,7 +2882,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
SyncTask(
callFfi: () {
final serializer = SseSerializer(generalizedFrbRustBinding);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 67)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 70)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_String,
@@ -2782,7 +2908,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 68,
funcId: 71,
port: port_,
);
},
@@ -2807,7 +2933,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
callFfi: () {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_String(secret, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 69)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 72)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_String,
@@ -2830,7 +2956,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
callFfi: () {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_String(mnemonic, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 70)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 73)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_list_prim_u_8_strict,
@@ -2857,7 +2983,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
callFfi: () {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_String(encoded, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 71)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 74)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_payment_request_info,
@@ -2886,7 +3012,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 72,
funcId: 75,
port: port_,
);
},
@@ -2913,7 +3039,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 73,
funcId: 76,
port: port_,
);
},
@@ -2940,7 +3066,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
pdeCallFfi(
generalizedFrbRustBinding,
serializer,
funcId: 74,
funcId: 77,
port: port_,
);
},
@@ -2965,7 +3091,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
callFfi: () {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_list_prim_u_8_loose(raw, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 75)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 78)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_token,
@@ -2988,7 +3114,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
callFfi: () {
final serializer = SseSerializer(generalizedFrbRustBinding);
sse_encode_String(encoded, serializer);
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 76)!;
return pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 79)!;
},
codec: SseCodec(
decodeSuccessData: sse_decode_token,
@@ -3513,6 +3639,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return (raw as List<dynamic>).map(dco_decode_mint_method_settings).toList();
}
@protected
List<MintQuote> dco_decode_list_mint_quote(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
return (raw as List<dynamic>).map(dco_decode_mint_quote).toList();
}
@protected
List<int> dco_decode_list_prim_u_8_loose(dynamic raw) {
// Codec=Dco (DartCObject based), see doc to use other codecs
@@ -4553,6 +4685,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
return ans_;
}
@protected
List<MintQuote> sse_decode_list_mint_quote(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
var len_ = sse_decode_i_32(deserializer);
var ans_ = <MintQuote>[];
for (var idx_ = 0; idx_ < len_; ++idx_) {
ans_.add(sse_decode_mint_quote(deserializer));
}
return ans_;
}
@protected
List<int> sse_decode_list_prim_u_8_loose(SseDeserializer deserializer) {
// Codec=Sse (Serialization based), see doc to use other codecs
@@ -5778,6 +5922,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi {
}
}
@protected
void sse_encode_list_mint_quote(
List<MintQuote> self,
SseSerializer serializer,
) {
// Codec=Sse (Serialization based), see doc to use other codecs
sse_encode_i_32(self.length, serializer);
for (final item in self) {
sse_encode_mint_quote(item, serializer);
}
}
@protected
void sse_encode_list_prim_u_8_loose(
List<int> self,
@@ -6592,6 +6748,14 @@ class WalletImpl extends RustOpaque implements Wallet {
Future<void> checkAllMintQuotes() =>
RustLib.instance.api.crateApiWalletWalletCheckAllMintQuotes(that: this);
/// Ask the mint for the current state of a single quote by id and
/// return the refreshed MintQuote. Local store is updated as a side
/// effect inside CDK.
Future<MintQuote> checkMintQuoteStatus({required String quoteId}) => RustLib
.instance
.api
.crateApiWalletWalletCheckMintQuoteStatus(that: this, quoteId: quoteId);
Future<void> checkPendingTransactions() => RustLib.instance.api
.crateApiWalletWalletCheckPendingTransactions(that: this);
@@ -6639,6 +6803,11 @@ class WalletImpl extends RustOpaque implements Wallet {
Future<MintInfo?> getMint() =>
RustLib.instance.api.crateApiWalletWalletGetMint(that: this);
/// Return pending (unissued) mint quotes known to the local store,
/// filtered to this wallet's mint/unit.
Future<List<MintQuote>> getUnissuedMintQuotes() => RustLib.instance.api
.crateApiWalletWalletGetUnissuedMintQuotes(that: this);
Future<bool> isTokenSpent({required Token token}) => RustLib.instance.api
.crateApiWalletWalletIsTokenSpent(that: this, token: token);
@@ -6659,6 +6828,15 @@ class WalletImpl extends RustOpaque implements Wallet {
description: description,
);
/// Mint proofs for a paid quote and return an Issued MintQuote with
/// `transaction_id` and `token` populated — same shape the `mint()`
/// stream emits on Issued. Use this to recover metadata for quotes
/// that were paid while the app was killed.
Future<MintQuote> mintByQuoteId({required String quoteId}) => RustLib
.instance
.api
.crateApiWalletWalletMintByQuoteId(that: this, quoteId: quoteId);
/// Pay a NUT-18 payment request.
/// Uses CDK's pay_request() which handles:
/// - NUT-10 spending conditions
+12
View File
@@ -299,6 +299,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
List<MintMethodSettings> dco_decode_list_mint_method_settings(dynamic raw);
@protected
List<MintQuote> dco_decode_list_mint_quote(dynamic raw);
@protected
List<int> dco_decode_list_prim_u_8_loose(dynamic raw);
@@ -706,6 +709,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
SseDeserializer deserializer,
);
@protected
List<MintQuote> sse_decode_list_mint_quote(SseDeserializer deserializer);
@protected
List<int> sse_decode_list_prim_u_8_loose(SseDeserializer deserializer);
@@ -1200,6 +1206,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
SseSerializer serializer,
);
@protected
void sse_encode_list_mint_quote(
List<MintQuote> self,
SseSerializer serializer,
);
@protected
void sse_encode_list_prim_u_8_loose(List<int> self, SseSerializer serializer);
+12
View File
@@ -301,6 +301,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
@protected
List<MintMethodSettings> dco_decode_list_mint_method_settings(dynamic raw);
@protected
List<MintQuote> dco_decode_list_mint_quote(dynamic raw);
@protected
List<int> dco_decode_list_prim_u_8_loose(dynamic raw);
@@ -708,6 +711,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
SseDeserializer deserializer,
);
@protected
List<MintQuote> sse_decode_list_mint_quote(SseDeserializer deserializer);
@protected
List<int> sse_decode_list_prim_u_8_loose(SseDeserializer deserializer);
@@ -1202,6 +1208,12 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl<RustLibWire> {
SseSerializer serializer,
);
@protected
void sse_encode_list_mint_quote(
List<MintQuote> self,
SseSerializer serializer,
);
@protected
void sse_encode_list_prim_u_8_loose(List<int> self, SseSerializer serializer);
+56
View File
@@ -411,6 +411,62 @@ impl Wallet {
Ok(())
}
/// Return pending (unissued) mint quotes known to the local store,
/// filtered to this wallet's mint/unit.
pub async fn get_unissued_mint_quotes(&self) -> Result<Vec<MintQuote>, Error> {
let quotes = self.inner.get_unissued_mint_quotes().await?;
Ok(quotes.into_iter().map(MintQuote::from).collect())
}
/// Ask the mint for the current state of a single quote by id and
/// return the refreshed MintQuote. Local store is updated as a side
/// effect inside CDK.
pub async fn check_mint_quote_status(&self, quote_id: String) -> Result<MintQuote, Error> {
let quote = self.inner.check_mint_quote_status(&quote_id).await?;
Ok(MintQuote::from(quote))
}
/// Mint proofs for a paid quote and return an Issued MintQuote with
/// `transaction_id` and `token` populated — same shape the `mint()`
/// stream emits on Issued. Use this to recover metadata for quotes
/// that were paid while the app was killed.
pub async fn mint_by_quote_id(&self, quote_id: String) -> Result<MintQuote, Error> {
let mint_url = self.mint_url()?;
let unit = self.unit();
let cdk_quote = self.inner.check_mint_quote_status(&quote_id).await?;
let expiry = cdk_quote.expiry;
let request = cdk_quote.request.clone();
let mint_proofs = self
.inner
.mint(&quote_id, SplitTarget::None, None)
.await?;
let tx_id = match TransactionId::try_from(mint_proofs.clone()) {
Ok(id) => Some(id.to_string()),
Err(e) => {
info!("Failed to compute mint tx ID: {e}");
None
}
};
let mint_amount = mint_proofs.total_amount().unwrap_or_default();
let token = Token::try_from(CdkToken::new(mint_url, mint_proofs, None, unit)).ok();
self.update_balance_streams().await;
Ok(MintQuote {
id: quote_id,
request,
amount: Some(mint_amount.into()),
expiry: Some(expiry),
state: CdkMintQuoteState::Issued.into(),
token,
error: None,
transaction_id: tx_id,
})
}
// === Lightning Withdrawal (NUT-05) ===
pub async fn melt_quote(&self, request: String) -> Result<MeltQuote, Error> {
+254 -37
View File
@@ -40,7 +40,7 @@ flutter_rust_bridge::frb_generated_boilerplate!(
default_rust_auto_opaque = RustAutoOpaqueMoi,
);
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_VERSION: &str = "2.11.1";
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 1593022460;
pub(crate) const FLUTTER_RUST_BRIDGE_CODEGEN_CONTENT_HASH: i32 = 884570592;
// Section: executor
@@ -1985,6 +1985,66 @@ fn wire__crate__api__wallet__Wallet_check_all_mint_quotes_impl(
},
)
}
fn wire__crate__api__wallet__Wallet_check_mint_quote_status_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "Wallet_check_mint_quote_status",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_that = <RustOpaqueMoi<
flutter_rust_bridge::for_generated::RustAutoOpaqueInner<Wallet>,
>>::sse_decode(&mut deserializer);
let api_quote_id = <String>::sse_decode(&mut deserializer);
deserializer.end();
move |context| async move {
transform_result_sse::<_, crate::api::error::Error>(
(move || async move {
let mut api_that_guard = None;
let decode_indices_ =
flutter_rust_bridge::for_generated::lockable_compute_decode_order(
vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new(
&api_that, 0, false,
)],
);
for i in decode_indices_ {
match i {
0 => {
api_that_guard =
Some(api_that.lockable_decode_async_ref().await)
}
_ => unreachable!(),
}
}
let api_that_guard = api_that_guard.unwrap();
let output_ok = crate::api::wallet::Wallet::check_mint_quote_status(
&*api_that_guard,
api_quote_id,
)
.await?;
Ok(output_ok)
})()
.await,
)
}
},
)
}
fn wire__crate__api__wallet__Wallet_check_pending_transactions_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
@@ -2335,6 +2395,63 @@ fn wire__crate__api__wallet__Wallet_get_mint_impl(
},
)
}
fn wire__crate__api__wallet__Wallet_get_unissued_mint_quotes_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "Wallet_get_unissued_mint_quotes",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_that = <RustOpaqueMoi<
flutter_rust_bridge::for_generated::RustAutoOpaqueInner<Wallet>,
>>::sse_decode(&mut deserializer);
deserializer.end();
move |context| async move {
transform_result_sse::<_, crate::api::error::Error>(
(move || async move {
let mut api_that_guard = None;
let decode_indices_ =
flutter_rust_bridge::for_generated::lockable_compute_decode_order(
vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new(
&api_that, 0, false,
)],
);
for i in decode_indices_ {
match i {
0 => {
api_that_guard =
Some(api_that.lockable_decode_async_ref().await)
}
_ => unreachable!(),
}
}
let api_that_guard = api_that_guard.unwrap();
let output_ok =
crate::api::wallet::Wallet::get_unissued_mint_quotes(&*api_that_guard)
.await?;
Ok(output_ok)
})()
.await,
)
}
},
)
}
fn wire__crate__api__wallet__Wallet_is_token_spent_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
@@ -2579,6 +2696,66 @@ fn wire__crate__api__wallet__Wallet_mint_impl(
},
)
}
fn wire__crate__api__wallet__Wallet_mint_by_quote_id_impl(
port_: flutter_rust_bridge::for_generated::MessagePort,
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
data_len_: i32,
) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap_async::<flutter_rust_bridge::for_generated::SseCodec, _, _, _>(
flutter_rust_bridge::for_generated::TaskInfo {
debug_name: "Wallet_mint_by_quote_id",
port: Some(port_),
mode: flutter_rust_bridge::for_generated::FfiCallMode::Normal,
},
move || {
let message = unsafe {
flutter_rust_bridge::for_generated::Dart2RustMessageSse::from_wire(
ptr_,
rust_vec_len_,
data_len_,
)
};
let mut deserializer =
flutter_rust_bridge::for_generated::SseDeserializer::new(message);
let api_that = <RustOpaqueMoi<
flutter_rust_bridge::for_generated::RustAutoOpaqueInner<Wallet>,
>>::sse_decode(&mut deserializer);
let api_quote_id = <String>::sse_decode(&mut deserializer);
deserializer.end();
move |context| async move {
transform_result_sse::<_, crate::api::error::Error>(
(move || async move {
let mut api_that_guard = None;
let decode_indices_ =
flutter_rust_bridge::for_generated::lockable_compute_decode_order(
vec![flutter_rust_bridge::for_generated::LockableOrderInfo::new(
&api_that, 0, false,
)],
);
for i in decode_indices_ {
match i {
0 => {
api_that_guard =
Some(api_that.lockable_decode_async_ref().await)
}
_ => unreachable!(),
}
}
let api_that_guard = api_that_guard.unwrap();
let output_ok = crate::api::wallet::Wallet::mint_by_quote_id(
&*api_that_guard,
api_quote_id,
)
.await?;
Ok(output_ok)
})()
.await,
)
}
},
)
}
fn wire__crate__api__wallet__Wallet_new_impl(
ptr_: flutter_rust_bridge::for_generated::PlatformGeneralizedUint8ListPtr,
rust_vec_len_: i32,
@@ -4158,6 +4335,18 @@ impl SseDecode for Vec<crate::api::mint_info::MintMethodSettings> {
}
}
impl SseDecode for Vec<crate::api::wallet::MintQuote> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
let mut len_ = <i32>::sse_decode(deserializer);
let mut ans_ = vec![];
for idx_ in 0..len_ {
ans_.push(<crate::api::wallet::MintQuote>::sse_decode(deserializer));
}
return ans_;
}
}
impl SseDecode for Vec<u8> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self {
@@ -4833,94 +5022,112 @@ fn pde_ffi_dispatcher_primary_impl(
rust_vec_len,
data_len,
),
41 => wire__crate__api__wallet__Wallet_check_pending_transactions_impl(
41 => wire__crate__api__wallet__Wallet_check_mint_quote_status_impl(
port,
ptr,
rust_vec_len,
data_len,
),
42 => wire__crate__api__wallet__Wallet_check_proofs_by_ys_impl(
42 => wire__crate__api__wallet__Wallet_check_pending_transactions_impl(
port,
ptr,
rust_vec_len,
data_len,
),
43 => wire__crate__api__wallet__Wallet_confirm_melt_impl(port, ptr, rust_vec_len, data_len),
44 => wire__crate__api__wallet__Wallet_create_payment_request_impl(
43 => wire__crate__api__wallet__Wallet_check_proofs_by_ys_impl(
port,
ptr,
rust_vec_len,
data_len,
),
45 => wire__crate__api__wallet__Wallet_finalize_pending_melts_impl(
44 => wire__crate__api__wallet__Wallet_confirm_melt_impl(port, ptr, rust_vec_len, data_len),
45 => wire__crate__api__wallet__Wallet_create_payment_request_impl(
port,
ptr,
rust_vec_len,
data_len,
),
46 => wire__crate__api__wallet__Wallet_get_mint_impl(port, ptr, rust_vec_len, data_len),
47 => {
46 => wire__crate__api__wallet__Wallet_finalize_pending_melts_impl(
port,
ptr,
rust_vec_len,
data_len,
),
47 => wire__crate__api__wallet__Wallet_get_mint_impl(port, ptr, rust_vec_len, data_len),
48 => wire__crate__api__wallet__Wallet_get_unissued_mint_quotes_impl(
port,
ptr,
rust_vec_len,
data_len,
),
49 => {
wire__crate__api__wallet__Wallet_is_token_spent_impl(port, ptr, rust_vec_len, data_len)
}
48 => wire__crate__api__wallet__Wallet_list_transactions_impl(
50 => wire__crate__api__wallet__Wallet_list_transactions_impl(
port,
ptr,
rust_vec_len,
data_len,
),
49 => wire__crate__api__wallet__Wallet_melt_quote_impl(port, ptr, rust_vec_len, data_len),
50 => wire__crate__api__wallet__Wallet_mint_impl(port, ptr, rust_vec_len, data_len),
52 => wire__crate__api__wallet__Wallet_pay_payment_request_impl(
51 => wire__crate__api__wallet__Wallet_melt_quote_impl(port, ptr, rust_vec_len, data_len),
52 => wire__crate__api__wallet__Wallet_mint_impl(port, ptr, rust_vec_len, data_len),
53 => wire__crate__api__wallet__Wallet_mint_by_quote_id_impl(
port,
ptr,
rust_vec_len,
data_len,
),
53 => wire__crate__api__wallet__Wallet_prepare_melt_impl(port, ptr, rust_vec_len, data_len),
54 => wire__crate__api__wallet__Wallet_prepare_send_impl(port, ptr, rust_vec_len, data_len),
55 => wire__crate__api__wallet__Wallet_receive_impl(port, ptr, rust_vec_len, data_len),
56 => wire__crate__api__wallet__Wallet_reclaim_pending_proofs_impl(
55 => wire__crate__api__wallet__Wallet_pay_payment_request_impl(
port,
ptr,
rust_vec_len,
data_len,
),
57 => wire__crate__api__wallet__Wallet_reclaim_proofs_by_ys_impl(
56 => wire__crate__api__wallet__Wallet_prepare_melt_impl(port, ptr, rust_vec_len, data_len),
57 => wire__crate__api__wallet__Wallet_prepare_send_impl(port, ptr, rust_vec_len, data_len),
58 => wire__crate__api__wallet__Wallet_receive_impl(port, ptr, rust_vec_len, data_len),
59 => wire__crate__api__wallet__Wallet_reclaim_pending_proofs_impl(
port,
ptr,
rust_vec_len,
data_len,
),
58 => wire__crate__api__wallet__Wallet_recover_incomplete_sagas_impl(
60 => wire__crate__api__wallet__Wallet_reclaim_proofs_by_ys_impl(
port,
ptr,
rust_vec_len,
data_len,
),
59 => {
61 => wire__crate__api__wallet__Wallet_recover_incomplete_sagas_impl(
port,
ptr,
rust_vec_len,
data_len,
),
62 => {
wire__crate__api__wallet__Wallet_refresh_balance_impl(port, ptr, rust_vec_len, data_len)
}
60 => wire__crate__api__wallet__Wallet_restore_impl(port, ptr, rust_vec_len, data_len),
61 => wire__crate__api__wallet__Wallet_send_impl(port, ptr, rust_vec_len, data_len),
62 => {
63 => wire__crate__api__wallet__Wallet_restore_impl(port, ptr, rust_vec_len, data_len),
64 => wire__crate__api__wallet__Wallet_send_impl(port, ptr, rust_vec_len, data_len),
65 => {
wire__crate__api__wallet__Wallet_stream_balance_impl(port, ptr, rust_vec_len, data_len)
}
63 => wire__crate__api__wallet__Wallet_wait_for_nostr_payment_impl(
66 => wire__crate__api__wallet__Wallet_wait_for_nostr_payment_impl(
port,
ptr,
rust_vec_len,
data_len,
),
66 => wire__crate__api__mint_info__fetch_keysets_impl(port, ptr, rust_vec_len, data_len),
68 => wire__crate__api__mint_info__get_mint_info_impl(port, ptr, rust_vec_len, data_len),
72 => wire__crate__api__mint_info__ping_mint_impl(port, ptr, rust_vec_len, data_len),
73 => wire__crate__api__wallet__receive_options_default_impl(
69 => wire__crate__api__mint_info__fetch_keysets_impl(port, ptr, rust_vec_len, data_len),
71 => wire__crate__api__mint_info__get_mint_info_impl(port, ptr, rust_vec_len, data_len),
75 => wire__crate__api__mint_info__ping_mint_impl(port, ptr, rust_vec_len, data_len),
76 => wire__crate__api__wallet__receive_options_default_impl(
port,
ptr,
rust_vec_len,
data_len,
),
74 => {
77 => {
wire__crate__api__wallet__send_options_default_impl(port, ptr, rust_vec_len, data_len)
}
_ => unreachable!(),
@@ -4969,15 +5176,15 @@ fn pde_ffi_dispatcher_sync_impl(
34 => wire__crate__api__wallet__Wallet_auto_accessor_get_unit_impl(ptr, rust_vec_len, data_len),
35 => wire__crate__api__wallet__Wallet_auto_accessor_set_mint_url_impl(ptr, rust_vec_len, data_len),
36 => wire__crate__api__wallet__Wallet_auto_accessor_set_unit_impl(ptr, rust_vec_len, data_len),
51 => wire__crate__api__wallet__Wallet_new_impl(ptr, rust_vec_len, data_len),
64 => wire__crate__api__token__create_offline_token_impl(ptr, rust_vec_len, data_len),
65 => wire__crate__api__token__encode_qr_token_impl(ptr, rust_vec_len, data_len),
67 => wire__crate__api__keys__generate_mnemonic_impl(ptr, rust_vec_len, data_len),
69 => wire__crate__api__keys__get_pub_key_impl(ptr, rust_vec_len, data_len),
70 => wire__crate__api__keys__mnemonic_to_seed_impl(ptr, rust_vec_len, data_len),
71 => wire__crate__api__payment_request__payment_request_info_parse_impl(ptr, rust_vec_len, data_len),
75 => wire__crate__api__token__token_from_raw_bytes_impl(ptr, rust_vec_len, data_len),
76 => wire__crate__api__token__token_parse_impl(ptr, rust_vec_len, data_len),
54 => wire__crate__api__wallet__Wallet_new_impl(ptr, rust_vec_len, data_len),
67 => wire__crate__api__token__create_offline_token_impl(ptr, rust_vec_len, data_len),
68 => wire__crate__api__token__encode_qr_token_impl(ptr, rust_vec_len, data_len),
70 => wire__crate__api__keys__generate_mnemonic_impl(ptr, rust_vec_len, data_len),
72 => wire__crate__api__keys__get_pub_key_impl(ptr, rust_vec_len, data_len),
73 => wire__crate__api__keys__mnemonic_to_seed_impl(ptr, rust_vec_len, data_len),
74 => wire__crate__api__payment_request__payment_request_info_parse_impl(ptr, rust_vec_len, data_len),
78 => wire__crate__api__token__token_from_raw_bytes_impl(ptr, rust_vec_len, data_len),
79 => wire__crate__api__token__token_parse_impl(ptr, rust_vec_len, data_len),
_ => unreachable!(),
}
}
@@ -6039,6 +6246,16 @@ impl SseEncode for Vec<crate::api::mint_info::MintMethodSettings> {
}
}
impl SseEncode for Vec<crate::api::wallet::MintQuote> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {
<i32>::sse_encode(self.len() as _, serializer);
for item in self {
<crate::api::wallet::MintQuote>::sse_encode(item, serializer);
}
}
}
impl SseEncode for Vec<u8> {
// Codec=Sse (Serialization based), see doc to use other codecs
fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {