depolymerization

wire gateway for Bitcoin/Ethereum
Log | Files | Refs | Submodules | README | LICENSE

commit 78de19c38700070ab3fa965f573f180997c749ff
parent 9361da39e566a5054398bbd853da762f20bfc473
Author: Antoine A <>
Date:   Tue, 21 Jul 2026 18:26:43 +0200

bitcoin: test and fix prepared transfers

Diffstat:
Mdepolymerizer-bitcoin/db/depolymerizer-bitcoin-procedures.sql | 8++++----
Mdepolymerizer-bitcoin/src/api.rs | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/depolymerizer-bitcoin/db/depolymerizer-bitcoin-procedures.sql b/depolymerizer-bitcoin/db/depolymerizer-bitcoin-procedures.sql @@ -175,7 +175,7 @@ IF out_pending THEN ELSIF in_type IS NOT NULL THEN UPDATE prepared_in SET tx_in_id = out_tx_row_id - WHERE (tx_in_id IS NULL AND account_pub = in_metadata) OR authorization_pub = local_authorization_pub; + WHERE (tx_in_id IS NULL AND account_pub = in_metadata AND type='reserve') OR authorization_pub = local_authorization_pub; -- Insert new incoming talerable tranreceived_atsaction INSERT INTO taler_in ( tx_in_id, @@ -389,11 +389,11 @@ IF in_recurrent THEN WITH moved_tx AS ( DELETE FROM pending_recurrent_in WHERE tx_in_id = ( - SELECT txid - FROM tx_in + SELECT tx_in_id + FROM pending_recurrent_in JOIN tx_in USING (tx_in_id) WHERE authorization_pub = in_authorization_pub - ORDER BY created_at ASC + ORDER BY received_at ASC LIMIT 1 ) RETURNING tx_in_id diff --git a/depolymerizer-bitcoin/src/api.rs b/depolymerizer-bitcoin/src/api.rs @@ -362,15 +362,21 @@ pub mod test { use axum::Router; use jiff::Timestamp; - use sqlx::PgPool; - use taler_api::{api::TalerRouter as _, auth::AuthMethod, subject::OutgoingSubject}; + use sqlx::{PgPool, Row, postgres::PgRow}; + use taler_api::{ + api::TalerRouter as _, auth::AuthMethod, db::TypeHelper, subject::OutgoingSubject, + }; use taler_common::{ api::wire::{TransferState, WireConfig}, + db::IncomingType, types::amount::{Currency, amount}, }; use taler_test_utils::{ db::db_test_setup, - routine::{admin_add_incoming_routine, out_history_routine, transfer_routine}, + routine::{ + Status, admin_add_incoming_routine, out_history_routine, registration_routine, + revenue_routine, transfer_routine, + }, server::TestServer, tasks, }; @@ -396,6 +402,13 @@ pub mod test { .unwrap() }); + pub static UNKNOWN: LazyLock<FullBtcPayto> = LazyLock::new(|| { + FullBtcPayto::from_str( + "payto://bitcoin/1Q2TWHE3GMdB6BZKafqwxXtWAWgFt5Jvm3?receiver-name=Unknown", + ) + .unwrap() + }); + async fn setup() -> (Router, PgPool) { let (_, pool) = db_test_setup(CONFIG_SOURCE).await; let api = ServerState::start( @@ -475,4 +488,63 @@ pub mod test { ) .await; } + + #[tokio::test] + async fn revenue() { + let (server, _) = &setup().await; + revenue_routine( + &server.prefix("/taler-wire-gateway"), + &server.prefix("/taler-revenue"), + &EXCHANGE.as_uri(), + tasks!(), + tasks!(), + ) + .await; + } + + async fn check_in(pool: &PgPool) -> Vec<Status> { + sqlx::query( + " + SELECT pending_recurrent_in.authorization_pub IS NOT NULL, bounced.reason IS NOT NULL, type, metadata + FROM tx_in + LEFT JOIN taler_in USING (tx_in_id) + LEFT JOIN pending_recurrent_in USING (tx_in_id) + LEFT JOIN bounced USING (tx_in_id) + ORDER BY tx_in.tx_in_id + ", + ) + .try_map(|r: PgRow| { + Ok( + if r.try_get_flag(0)? { + Status::Pending + } else if r.try_get_flag(1)? { + Status::Bounced + } else { + match r.try_get(2)? { + None => Status::Simple, + Some(IncomingType::reserve) => Status::Reserve(r.try_get(3)?), + Some(IncomingType::kyc) => Status::Kyc(r.try_get(3)?), + Some(e) => unreachable!("{e:?}") + } + } + ) + }) + .fetch_all(pool) + .await + .unwrap() + } + + #[tokio::test] + async fn registration() { + let (server, pool) = setup().await; + registration_routine( + &server.prefix("/taler-wire-gateway"), + &server.prefix("/taler-prepared-transfer"), + &CLIENT.as_uri(), + &EXCHANGE.as_uri(), + &UNKNOWN.as_uri(), + || check_in(&pool), + ) + .await; + } }