[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-rust] branch master updated (33961b8 -> 3adb0e5)
From: |
Admin |
Subject: |
[taler-rust] branch master updated (33961b8 -> 3adb0e5) |
Date: |
Wed, 05 Feb 2025 17:30:05 +0100 |
This is an automated email from the git hooks/post-receive script.
antoine pushed a change to branch master
in repository taler-rust.
from 33961b8 magnet-bank: fix magnet API
new 347379a magnet-bank: db bounce logic
new 3adb0e5 magnet-bank: clean code
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
Cargo.lock | 18 ++---
taler-magnet-bank/db/schema.sql | 64 +++++++++++++++-
taler-magnet-bank/src/adapter.rs | 16 ++--
taler-magnet-bank/src/db.rs | 154 +++++++++++++++++++++++++++++++++------
taler-magnet-bank/src/magnet.rs | 10 +--
taler-magnet-bank/src/worker.rs | 8 +-
6 files changed, 219 insertions(+), 51 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index d507f2b..0f375a9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1861,7 +1861,7 @@ checksum =
"3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.0",
- "zerocopy 0.8.15",
+ "zerocopy 0.8.16",
]
[[package]]
@@ -1900,7 +1900,7 @@ source =
"registry+https://github.com/rust-lang/crates.io-index"
checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
dependencies = [
"getrandom 0.3.1",
- "zerocopy 0.8.15",
+ "zerocopy 0.8.16",
]
[[package]]
@@ -2933,9 +2933,9 @@ checksum =
"06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
-version = "1.12.1"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b"
+checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0"
[[package]]
name = "valuable"
@@ -3367,11 +3367,11 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.8.15"
+version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1e101d4bc320b6f9abb68846837b70e25e380ca2f467ab494bf29fcc435fcc3"
+checksum = "7b8c07a70861ce02bad1607b5753ecb2501f67847b9f9ada7c160fff0ec6300c"
dependencies = [
- "zerocopy-derive 0.8.15",
+ "zerocopy-derive 0.8.16",
]
[[package]]
@@ -3387,9 +3387,9 @@ dependencies = [
[[package]]
name = "zerocopy-derive"
-version = "0.8.15"
+version = "0.8.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03a73df1008145cd135b3c780d275c57c3e6ba8324a41bd5e0008fe167c3bc7c"
+checksum = "5226bc9a9a9836e7428936cde76bb6b22feea1a8bfdbc0d241136e4d13417e25"
dependencies = [
"proc-macro2",
"quote",
diff --git a/taler-magnet-bank/db/schema.sql b/taler-magnet-bank/db/schema.sql
index 8654d6b..a029bb5 100644
--- a/taler-magnet-bank/db/schema.sql
+++ b/taler-magnet-bank/db/schema.sql
@@ -98,6 +98,13 @@ CREATE TABLE transfer(
);
COMMENT ON TABLE transfer IS 'Wire Gateway transfers';
+CREATE TABLE bounced(
+ tx_in_id INT8 NOT NULL UNIQUE REFERENCES tx_in(tx_in_id) ON DELETE CASCADE,
+ initiated_id INT8 NOT NULL UNIQUE REFERENCES initiated(initiated_id) ON
DELETE CASCADE,
+ reason TEXT NOT NULL
+);
+COMMENT ON TABLE tx_in IS 'Bounced transactions';
+
CREATE FUNCTION register_tx_in(
IN in_code INT8,
IN in_amount taler_amount,
@@ -326,4 +333,59 @@ BEGIN
WHERE initiated_id = in_initiated_id;
END IF;
END IF;
-END $$;
\ No newline at end of file
+END $$;
+
+CREATE FUNCTION bounce(
+ IN in_tx_in_id INT8,
+ IN in_amount taler_amount,
+ IN in_reason TEXT,
+ IN in_timestamp INT8,
+ OUT out_tx_row_id INT8,
+ OUT out_timestamp INT8
+)
+LANGUAGE plpgsql AS $$
+DECLARE
+local_debit_account TEXT;
+local_debit_name TEXT;
+local_magnet_code INT8;
+BEGIN
+-- Check if already bounce
+SELECT initiated_id, created
+ INTO out_tx_row_id, out_timestamp
+ FROM bounced JOIN initiated USING (initiated_id)
+ WHERE tx_in_id = in_tx_in_id;
+
+-- Else initiate the bounce transaction
+IF NOT FOUND THEN
+ -- Get incoming transaction bank ID and creditor
+ SELECT debit_account, debit_name, magnet_code
+ INTO local_debit_account, local_debit_name, local_magnet_code
+ FROM tx_in
+ WHERE tx_in_id = in_tx_in_id;
+ -- Initiate the bounce transaction
+ INSERT INTO initiated (
+ amount,
+ subject,
+ credit_account,
+ credit_name,
+ created
+ ) VALUES (
+ in_amount,
+ 'bounce: ' || local_magnet_code,
+ local_debit_account,
+ local_debit_name,
+ in_timestamp
+ )
+ RETURNING initiated_id, created INTO out_tx_row_id, out_timestamp;
+ -- Register the bounce
+ INSERT INTO bounced (
+ tx_in_id,
+ initiated_id,
+ reason
+ ) VALUES (
+ in_tx_in_id,
+ out_tx_row_id,
+ in_reason
+ );
+END IF;
+END$$;
\ No newline at end of file
diff --git a/taler-magnet-bank/src/adapter.rs b/taler-magnet-bank/src/adapter.rs
index 5931034..a6f1643 100644
--- a/taler-magnet-bank/src/adapter.rs
+++ b/taler-magnet-bank/src/adapter.rs
@@ -152,9 +152,11 @@ impl WireGateway for MagnetApi {
)
.await?;
match res {
- AddIncomingResult::Success(res) => Ok(AddIncomingResponse {
- row_id: safe_u64(res.row_id),
- timestamp: res.timestamp,
+ AddIncomingResult::Success {
+ row_id, timestamp, ..
+ } => Ok(AddIncomingResponse {
+ row_id: safe_u64(row_id),
+ timestamp,
}),
AddIncomingResult::ReservePubReuse => Err(failure(
ErrorCode::BANK_DUPLICATE_RESERVE_PUB_SUBJECT,
@@ -177,9 +179,11 @@ impl WireGateway for MagnetApi {
)
.await?;
match res {
- AddIncomingResult::Success(res) => Ok(AddKycauthResponse {
- row_id: safe_u64(res.row_id),
- timestamp: res.timestamp,
+ AddIncomingResult::Success {
+ row_id, timestamp, ..
+ } => Ok(AddKycauthResponse {
+ row_id: safe_u64(row_id),
+ timestamp,
}),
AddIncomingResult::ReservePubReuse => Err(failure(
ErrorCode::BANK_DUPLICATE_RESERVE_PUB_SUBJECT,
diff --git a/taler-magnet-bank/src/db.rs b/taler-magnet-bank/src/db.rs
index 009761d..51e64b7 100644
--- a/taler-magnet-bank/src/db.rs
+++ b/taler-magnet-bank/src/db.rs
@@ -111,7 +111,7 @@ pub struct TxInAdmin {
}
#[derive(Debug, PartialEq, Eq)]
-pub struct RegisteredTx {
+pub struct AddOutgoingResult {
pub new: bool,
pub row_id: u64,
pub timestamp: Timestamp,
@@ -119,7 +119,11 @@ pub struct RegisteredTx {
#[derive(Debug, PartialEq, Eq)]
pub enum AddIncomingResult {
- Success(RegisteredTx),
+ Success {
+ new: bool,
+ row_id: u64,
+ timestamp: Timestamp,
+ },
ReservePubReuse,
}
@@ -174,11 +178,11 @@ pub async fn register_tx_in_admin(db: &PgPool, tx:
&TxInAdmin) -> sqlx::Result<A
Ok(if r.try_get(0)? {
AddIncomingResult::ReservePubReuse
} else {
- AddIncomingResult::Success(RegisteredTx {
+ AddIncomingResult::Success {
new: r.try_get(1)?,
row_id: r.try_get_u64(2)?,
timestamp: r.try_get_timestamp(3)?,
- })
+ }
})
})
.fetch_one(db)
@@ -208,11 +212,11 @@ pub async fn register_tx_in(
Ok(if r.try_get(0)? {
AddIncomingResult::ReservePubReuse
} else {
- AddIncomingResult::Success(RegisteredTx {
+ AddIncomingResult::Success {
new: r.try_get(1)?,
row_id: r.try_get_u64(2)?,
timestamp: r.try_get_timestamp(3)?,
- })
+ }
})
})
.fetch_one(db)
@@ -223,7 +227,7 @@ pub async fn register_tx_out(
db: &mut PgConnection,
tx: &TxOut,
subject: &Option<OutgoingSubject>,
-) -> sqlx::Result<RegisteredTx> {
+) -> sqlx::Result<AddOutgoingResult> {
sqlx::query(
"
SELECT out_new, out_tx_row_id, out_timestamp
@@ -239,7 +243,7 @@ pub async fn register_tx_out(
.bind(subject.as_ref().map(|it| it.0.as_ref()))
.bind(subject.as_ref().map(|it| it.1.as_str()))
.try_map(|r: PgRow| {
- Ok(RegisteredTx {
+ Ok(AddOutgoingResult {
new: r.try_get(0)?,
row_id: r.try_get_u64(1)?,
timestamp: r.try_get_timestamp(2)?,
@@ -293,6 +297,39 @@ pub async fn make_transfer<'a>(
.await
}
+#[derive(Debug, PartialEq, Eq)]
+pub struct BounceResult {
+ id: u64,
+ timestamp: Timestamp,
+}
+
+pub async fn bounce<'a>(
+ db: impl PgExecutor<'a>,
+ tx_in: u64,
+ amount: &Amount,
+ reason: &str,
+ timestamp: &Timestamp,
+) -> sqlx::Result<BounceResult> {
+ sqlx::query(
+ "
+ SELECT out_tx_row_id, out_timestamp
+ FROM bounce($1, ($2, $3)::taler_amount, $4, $5)
+ ",
+ )
+ .bind(tx_in as i64)
+ .bind_amount(amount)
+ .bind(reason)
+ .bind_timestamp(timestamp)
+ .try_map(|r: PgRow| {
+ Ok(BounceResult {
+ id: r.try_get_u64(0)?,
+ timestamp: r.try_get_timestamp(1)?,
+ })
+ })
+ .fetch_one(db)
+ .await
+}
+
pub async fn transfer_page<'a>(
db: impl PgExecutor<'a>,
status: &Option<TransferState>,
@@ -595,7 +632,8 @@ mod test {
constant::CURRENCY,
db::{
self, make_transfer, register_tx_in, register_tx_in_admin,
register_tx_out,
- AddIncomingResult, RegisteredTx, TransferResult, TxIn, TxOut,
+ AddIncomingResult, AddOutgoingResult, BounceResult, Initiated,
TransferResult, TxIn,
+ TxOut,
},
magnet_payto,
};
@@ -642,11 +680,11 @@ mod test {
register_tx_in(db, &tx, &first)
.await
.expect("register tx in"),
- AddIncomingResult::Success(RegisteredTx {
+ AddIncomingResult::Success {
new: true,
row_id: id,
timestamp: tx.timestamp
- })
+ }
);
// Idempotent
assert_eq!(
@@ -660,11 +698,11 @@ mod test {
)
.await
.expect("register tx in"),
- AddIncomingResult::Success(RegisteredTx {
+ AddIncomingResult::Success {
new: false,
row_id: id,
timestamp: tx.timestamp
- })
+ }
);
// Many
assert_eq!(
@@ -678,11 +716,11 @@ mod test {
)
.await
.expect("register tx in"),
- AddIncomingResult::Success(RegisteredTx {
+ AddIncomingResult::Success {
new: true,
row_id: id + 1,
timestamp: tx.timestamp
- })
+ }
);
}
@@ -760,11 +798,11 @@ mod test {
register_tx_in_admin(&pool, &tx)
.await
.expect("register tx in"),
- AddIncomingResult::Success(RegisteredTx {
+ AddIncomingResult::Success {
new: true,
row_id: 1,
timestamp: tx.timestamp
- })
+ }
);
// Idempotent
assert_eq!(
@@ -777,11 +815,11 @@ mod test {
)
.await
.expect("register tx in"),
- AddIncomingResult::Success(RegisteredTx {
+ AddIncomingResult::Success {
new: false,
row_id: 1,
timestamp: tx.timestamp
- })
+ }
);
// Many
assert_eq!(
@@ -795,11 +833,11 @@ mod test {
)
.await
.expect("register tx in"),
- AddIncomingResult::Success(RegisteredTx {
+ AddIncomingResult::Success {
new: true,
row_id: 2,
timestamp: tx.timestamp
- })
+ }
);
// History
@@ -841,7 +879,7 @@ mod test {
register_tx_out(db, &tx, &first)
.await
.expect("register tx out"),
- RegisteredTx {
+ AddOutgoingResult {
new: true,
row_id: id,
timestamp: tx.timestamp
@@ -859,7 +897,7 @@ mod test {
)
.await
.expect("register tx out"),
- RegisteredTx {
+ AddOutgoingResult {
new: false,
row_id: id,
timestamp: tx.timestamp
@@ -877,7 +915,7 @@ mod test {
)
.await
.expect("register tx out"),
- RegisteredTx {
+ AddOutgoingResult {
new: true,
row_id: id + 1,
timestamp: tx.timestamp
@@ -1025,6 +1063,74 @@ mod test {
);
}
+ #[tokio::test]
+ async fn bounce() {
+ let (mut db, _) = setup().await;
+
+ let amount = amount("HUF:10");
+ let payto =
magnet_payto("payto://iban/HU30162000031000163100000000?receiver-name=name");
+ let timestamp = Timestamp::now_stable();
+
+ // Empty db
+ assert!(db::pending_batch(&mut db, ×tamp)
+ .await
+ .unwrap()
+ .is_empty());
+
+ // Insert
+ assert_eq!(
+ register_tx_in(
+ &mut db,
+ &TxIn {
+ code: 12,
+ amount: amount.clone(),
+ subject: "subject".to_owned(),
+ debtor: payto.clone(),
+ timestamp
+ },
+ &None
+ )
+ .await
+ .expect("register tx in"),
+ AddIncomingResult::Success {
+ new: true,
+ row_id: 1,
+ timestamp
+ }
+ );
+ // Bounce
+ assert_eq!(
+ db::bounce(&mut db, 1, &amount, "good reason", ×tamp)
+ .await
+ .expect("bounce"),
+ BounceResult {
+ id: 1,
+ timestamp: timestamp
+ }
+ );
+ // Idempotent
+ assert_eq!(
+ db::bounce(&mut db, 1, &amount, "good reason", ×tamp)
+ .await
+ .expect("bounce"),
+ BounceResult {
+ id: 1,
+ timestamp: timestamp
+ }
+ );
+
+ // Batch
+ assert_eq!(
+ db::pending_batch(&mut db, ×tamp).await.unwrap(),
+ &[Initiated {
+ id: 1,
+ amount,
+ subject: "bounce: 12".to_owned(),
+ creditor: payto
+ }]
+ );
+ }
+
#[tokio::test]
async fn status() {
let (mut db, _) = setup().await;
diff --git a/taler-magnet-bank/src/magnet.rs b/taler-magnet-bank/src/magnet.rs
index 664d8a9..5c9b5c6 100644
--- a/taler-magnet-bank/src/magnet.rs
+++ b/taler-magnet-bank/src/magnet.rs
@@ -442,17 +442,13 @@ impl ApiClient<'_> {
if let Some(next) = next {
req = req
.query(&[("nextId", next.next_id)])
- .query(&[("nextTipus", &next.next_type)])
- .query(&[("tranzakciofrissite", true)]);
+ .query(&[("nextTipus", &next.next_type)]);
}
if let Some(status) = status {
req = req.query(&[("statusz", status)]);
}
- if direction != Direction::Both {
- req = req.query(&[("terheles", direction)])
- }
-
- req.query(&[("tranzakciofrissites", "true")])
+ req.query(&[("terheles", direction)])
+ .query(&[("tranzakciofrissites", true)])
.oauth(self.consumer, Some(self.access), None)
.await
.magnet_call()
diff --git a/taler-magnet-bank/src/worker.rs b/taler-magnet-bank/src/worker.rs
index 8eda144..9b9f31c 100644
--- a/taler-magnet-bank/src/worker.rs
+++ b/taler-magnet-bank/src/worker.rs
@@ -73,8 +73,8 @@ impl Worker<'_> {
// TODO bounce in db
let res = db::register_tx_in(db, tx_in,
&None).await?;
match res {
- AddIncomingResult::Success(registered_tx) => {
- if registered_tx.new {
+ AddIncomingResult::Success { new, .. } => {
+ if new {
info!("incoming {tx_in} bounced in
TODO");
} else {
debug!("incoming {tx_in} already seen
and bounced in TODO");
@@ -93,8 +93,8 @@ impl Worker<'_> {
let res =
db::register_tx_in(self.db, &tx_in,
&Some(subject)).await?;
match res {
- AddIncomingResult::Success(registered_tx)
=> {
- if registered_tx.new {
+ AddIncomingResult::Success { new, .. } => {
+ if new {
info!("incoming {tx_in}");
} else {
debug!("incoming {tx_in}");
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-rust] branch master updated (33961b8 -> 3adb0e5),
Admin <=