taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 2afbff04553de78fd181068908b5706f0d8f4090
parent 2c86c9a164dfc54ce2f2bfb5c17ef09869eb963e
Author: Florian Dold <dold@taler.net>
Date:   Wed, 22 Jul 2026 10:53:30 +0200

wallet: order the sqlite status queries like the IndexedDB indexes

The IndexedDB backend returns these records ordered by status and primary key.
getFreshCoinsByDenomAndAge is the case that matters most: combined with a LIMIT
and no order, the two backends could return different coins.

Diffstat:
Mpackages/taler-wallet-core/src/dbtx-sqlite.ts | 41++++++++++++++++++++++++++++-------------
1 file changed, 28 insertions(+), 13 deletions(-)

diff --git a/packages/taler-wallet-core/src/dbtx-sqlite.ts b/packages/taler-wallet-core/src/dbtx-sqlite.ts @@ -1278,6 +1278,7 @@ export class SqliteWalletTransaction implements WalletDbTransaction { "SELECT * FROM coins" + " WHERE exchange_base_url = $url AND denom_pub_hash = $dph" + " AND max_age = $age AND status = $status" + + " ORDER BY coin_pub" + " LIMIT $limit", { url: exchangeBaseUrl, @@ -2297,7 +2298,8 @@ export class SqliteWalletTransaction implements WalletDbTransaction { async getActiveWithdrawalGroups(): Promise<WalletWithdrawalGroup[]> { const rows = await this.all( - "SELECT * FROM withdrawal_groups WHERE status BETWEEN $lo AND $hi", + "SELECT * FROM withdrawal_groups WHERE status BETWEEN $lo AND $hi" + + " ORDER BY status, withdrawal_group_id", { lo: OPERATION_STATUS_NONFINAL_FIRST, hi: OPERATION_STATUS_NONFINAL_LAST, @@ -2698,7 +2700,8 @@ export class SqliteWalletTransaction implements WalletDbTransaction { async getActivePeerPushDebits(): Promise<WalletPeerPushDebit[]> { const rows = await this.all( - "SELECT * FROM peer_push_debit WHERE status BETWEEN $lo AND $hi", + "SELECT * FROM peer_push_debit WHERE status BETWEEN $lo AND $hi" + + " ORDER BY status, purse_pub", { lo: OPERATION_STATUS_NONFINAL_FIRST, hi: OPERATION_STATUS_NONFINAL_LAST, @@ -2835,7 +2838,8 @@ export class SqliteWalletTransaction implements WalletDbTransaction { async getActivePeerPushCredits(): Promise<WalletPeerPushCredit[]> { const rows = await this.all( - "SELECT * FROM peer_push_credit WHERE status BETWEEN $lo AND $hi", + "SELECT * FROM peer_push_credit WHERE status BETWEEN $lo AND $hi" + + " ORDER BY status, peer_push_credit_id", { lo: OPERATION_STATUS_NONFINAL_FIRST, hi: OPERATION_STATUS_NONFINAL_LAST, @@ -3279,7 +3283,8 @@ export class SqliteWalletTransaction implements WalletDbTransaction { async getActiveDepositGroups(): Promise<WalletDepositGroup[]> { const rows = await this.all( "SELECT * FROM deposit_groups" + - " WHERE operation_status BETWEEN $lo AND $hi", + " WHERE operation_status BETWEEN $lo AND $hi" + + " ORDER BY operation_status, deposit_group_id", { lo: OPERATION_STATUS_NONFINAL_FIRST, hi: OPERATION_STATUS_NONFINAL_LAST, @@ -3389,7 +3394,8 @@ export class SqliteWalletTransaction implements WalletDbTransaction { async getActiveRefreshGroups(): Promise<WalletRefreshGroup[]> { const rows = await this.all( "SELECT * FROM refresh_groups" + - " WHERE operation_status BETWEEN $lo AND $hi", + " WHERE operation_status BETWEEN $lo AND $hi" + + " ORDER BY operation_status, refresh_group_id", { lo: OPERATION_STATUS_NONFINAL_FIRST, hi: OPERATION_STATUS_NONFINAL_LAST, @@ -3768,16 +3774,21 @@ export class SqliteWalletTransaction implements WalletDbTransaction { status: PurchaseStatus, ): Promise<WalletPurchase[]> { return await this.hydratePurchases( - await this.all("SELECT * FROM purchases WHERE purchase_status = $s", { - s: status, - }), + await this.all( + "SELECT * FROM purchases WHERE purchase_status = $s" + + " ORDER BY purchase_status, proposal_id", + { + s: status, + }, + ), ); } async getActivePurchases(): Promise<WalletPurchase[]> { return await this.hydratePurchases( await this.all( - "SELECT * FROM purchases WHERE purchase_status BETWEEN $lo AND $hi", + "SELECT * FROM purchases WHERE purchase_status BETWEEN $lo AND $hi" + + " ORDER BY purchase_status, proposal_id", { lo: OPERATION_STATUS_NONFINAL_FIRST, hi: OPERATION_STATUS_NONFINAL_LAST, @@ -4050,7 +4061,8 @@ export class SqliteWalletTransaction implements WalletDbTransaction { status: DonationReceiptStatus, ): Promise<WalletDonationReceipt[]> { const rows = await this.all( - "SELECT * FROM donation_receipts WHERE status = $s", + "SELECT * FROM donation_receipts WHERE status = $s" + + " ORDER BY status, udi_nonce", { s: status }, ); return rows.map((r) => this.rowToDonationReceipt(r)); @@ -4857,7 +4869,8 @@ export class SqliteWalletTransaction implements WalletDbTransaction { async getActiveRecoupGroups(): Promise<WalletRecoupGroup[]> { const rows = await this.all( "SELECT * FROM recoup_groups" + - " WHERE operation_status BETWEEN $lo AND $hi", + " WHERE operation_status BETWEEN $lo AND $hi" + + " ORDER BY operation_status, recoup_group_id", { lo: OPERATION_STATUS_NONFINAL_FIRST, hi: OPERATION_STATUS_NONFINAL_LAST, @@ -4870,7 +4883,8 @@ export class SqliteWalletTransaction implements WalletDbTransaction { async getActivePeerPullCredits(): Promise<WalletPeerPullCredit[]> { const rows = await this.all( - "SELECT * FROM peer_pull_credit WHERE status BETWEEN $lo AND $hi", + "SELECT * FROM peer_pull_credit WHERE status BETWEEN $lo AND $hi" + + " ORDER BY status, purse_pub", { lo: OPERATION_STATUS_NONFINAL_FIRST, hi: OPERATION_STATUS_NONFINAL_LAST, @@ -4881,7 +4895,8 @@ export class SqliteWalletTransaction implements WalletDbTransaction { async getActivePeerPullDebits(): Promise<WalletPeerPullDebit[]> { const rows = await this.all( - "SELECT * FROM peer_pull_debit WHERE status BETWEEN $lo AND $hi", + "SELECT * FROM peer_pull_debit WHERE status BETWEEN $lo AND $hi" + + " ORDER BY status, peer_pull_debit_id", { lo: OPERATION_STATUS_NONFINAL_FIRST, hi: OPERATION_STATUS_NONFINAL_LAST,