commit 8d324855c5196858bfab1d1109be96df88f372d7
parent 7d17036797515db23661d670b40acd0ea792216f
Author: Antoine A <>
Date: Fri, 28 Nov 2025 21:51:07 +0100
common: stop using taler weird timestamp everywhere
Diffstat:
13 files changed, 96 insertions(+), 141 deletions(-)
diff --git a/common/taler-api/src/db.rs b/common/taler-api/src/db.rs
@@ -17,6 +17,7 @@
use std::{str::FromStr, time::Duration};
use jiff::{
+ Timestamp,
civil::{Date, Time},
tz::TimeZone,
};
@@ -33,7 +34,6 @@ use taler_common::{
base32::Base32,
iban::IBAN,
payto::PaytoURI,
- timestamp::Timestamp,
utils::date_to_utc_timestamp,
},
};
@@ -140,7 +140,7 @@ impl<'q> BindHelper for Query<'q, Postgres, <Postgres as sqlx::Database>::Argume
}
fn bind_timestamp(self, timestamp: &Timestamp) -> Self {
- self.bind(timestamp.as_sql_micros())
+ self.bind(timestamp.as_microsecond())
}
fn bind_date(self, date: &Date) -> Self {
@@ -168,11 +168,14 @@ pub trait TypeHelper {
index: I,
) -> sqlx::Result<T>;
fn try_get_timestamp<I: sqlx::ColumnIndex<Self>>(&self, index: I) -> sqlx::Result<Timestamp> {
- self.try_get_map(index, Timestamp::from_sql_micros)
+ self.try_get_map(index, |micros| {
+ jiff::Timestamp::from_microsecond(micros)
+ .map_err(|e| format!("expected timestamp micros got overflowing {micros}: {e}"))
+ })
}
fn try_get_date<I: sqlx::ColumnIndex<Self>>(&self, index: I) -> sqlx::Result<Date> {
let timestamp = self.try_get_timestamp(index)?;
- let zoned = timestamp.0.to_zoned(TimeZone::UTC);
+ let zoned = timestamp.to_zoned(TimeZone::UTC);
assert_eq!(zoned.time(), Time::midnight());
Ok(zoned.date())
}
diff --git a/common/taler-api/tests/common/db.rs b/common/taler-api/tests/common/db.rs
@@ -14,6 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+use jiff::Timestamp;
use sqlx::{PgPool, QueryBuilder, Row, postgres::PgRow};
use taler_api::db::{BindHelper, IncomingType, TypeHelper, history, page};
use taler_common::{
@@ -27,7 +28,6 @@ use taler_common::{
types::{
amount::{Amount, Currency},
payto::PaytoURI,
- timestamp::Timestamp,
},
};
use tokio::sync::watch::{Receiver, Sender};
@@ -75,7 +75,7 @@ pub async fn transfer(db: &PgPool, transfer: TransferRequest) -> sqlx::Result<Tr
} else {
TransferResult::Success(TransferResponse {
row_id: r.try_get_safeu64("out_transfer_row_id")?,
- timestamp: r.try_get_timestamp("out_created_at")?,
+ timestamp: r.try_get_timestamp("out_created_at")?.into(),
})
})
})
@@ -117,7 +117,7 @@ pub async fn transfer_page(
status: r.try_get("status")?,
amount: r.try_get_amount("amount", currency)?,
credit_account: r.try_get_payto("credit_payto")?,
- timestamp: r.try_get_timestamp("created_at")?,
+ timestamp: r.try_get_timestamp("created_at")?.into(),
})
},
)
@@ -152,7 +152,7 @@ pub async fn transfer_by_id(
origin_exchange_url: r.try_get("exchange_base_url")?,
wtid: r.try_get_base32("wtid")?,
credit_account: r.try_get_payto("credit_payto")?,
- timestamp: r.try_get_timestamp("created_at")?,
+ timestamp: r.try_get_timestamp("created_at")?.into(),
})
})
.fetch_optional(db)
@@ -191,7 +191,7 @@ pub async fn outgoing_revenue(
wtid: r.try_get_base32("wtid")?,
credit_account: r.try_get_payto("credit_payto")?,
row_id: r.try_get_safeu64("transfer_id")?,
- date: r.try_get_timestamp("created_at")?,
+ date: r.try_get_timestamp("created_at")?.into(),
exchange_base_url: r.try_get_url("exchange_base_url")?,
})
},
@@ -271,21 +271,21 @@ pub async fn incoming_history(
Ok(match kind {
IncomingType::reserve => IncomingBankTransaction::Reserve {
row_id: r.try_get_safeu64("tx_in_id")?,
- date: r.try_get_timestamp("created_at")?,
+ date: r.try_get_timestamp("created_at")?.into(),
amount: r.try_get_amount("amount", currency)?,
debit_account: r.try_get_payto("debit_payto")?,
reserve_pub: r.try_get_base32("metadata")?,
},
IncomingType::kyc => IncomingBankTransaction::Kyc {
row_id: r.try_get_safeu64("tx_in_id")?,
- date: r.try_get_timestamp("created_at")?,
+ date: r.try_get_timestamp("created_at")?.into(),
amount: r.try_get_amount("amount", currency)?,
debit_account: r.try_get_payto("debit_payto")?,
account_pub: r.try_get_base32("metadata")?,
},
IncomingType::wad => IncomingBankTransaction::Wad {
row_id: r.try_get_safeu64("tx_in_id")?,
- date: r.try_get_timestamp("created_at")?,
+ date: r.try_get_timestamp("created_at")?.into(),
amount: r.try_get_amount("amount", currency)?,
debit_account: r.try_get_payto("debit_payto")?,
origin_exchange_url: r.try_get_url("origin_exchange_url")?,
@@ -325,7 +325,7 @@ pub async fn revenue_history(
|r: PgRow| {
Ok(RevenueIncomingBankTransaction {
row_id: r.try_get_safeu64("tx_in_id")?,
- date: r.try_get_timestamp("created_at")?,
+ date: r.try_get_timestamp("created_at")?.into(),
amount: r.try_get_amount("amount", currency)?,
credit_fee: None,
debit_account: r.try_get_payto("debit_payto")?,
diff --git a/common/taler-api/tests/common/mod.rs b/common/taler-api/tests/common/mod.rs
@@ -17,6 +17,7 @@
use std::sync::Arc;
use db::notification_listener;
+use jiff::Timestamp;
use sqlx::PgPool;
use taler_api::{
api::{Router, TalerApi, TalerRouter as _, revenue::Revenue, wire::WireGateway},
@@ -33,7 +34,7 @@ use taler_common::{
TransferState, TransferStatus,
},
error_code::ErrorCode,
- types::{amount::Currency, payto::payto, timestamp::Timestamp},
+ types::{amount::Currency, payto::payto},
};
use taler_test_utils::db_test_setup_manual;
use tokio::sync::watch::Sender;
@@ -127,7 +128,7 @@ impl WireGateway for TestApi {
.await?;
match res {
db::AddIncomingResult::Success { id, created_at } => Ok(AddIncomingResponse {
- timestamp: created_at,
+ timestamp: created_at.into(),
row_id: id,
}),
db::AddIncomingResult::ReservePubReuse => Err(failure(
@@ -150,7 +151,7 @@ impl WireGateway for TestApi {
.await?;
match res {
db::AddIncomingResult::Success { id, created_at } => Ok(AddKycauthResponse {
- timestamp: created_at,
+ timestamp: created_at.into(),
row_id: id,
}),
db::AddIncomingResult::ReservePubReuse => Err(failure(
diff --git a/common/taler-build/build.rs b/common/taler-build/build.rs
@@ -42,7 +42,7 @@ fn main() -> Result<(), String> {
// Get the short commit hash
let commit_hash = run_command("git", &["rev-parse", "--short", "HEAD"])?;
-
+
// Set the environment variable VERSION
println!("cargo:rustc-env=GIT_HASH={}", commit_hash);
diff --git a/common/taler-common/src/api_revenue.rs b/common/taler-common/src/api_revenue.rs
@@ -16,7 +16,7 @@
//! Type for the Taler Wire Gateway HTTP API <https://docs.taler.net/core/api-bank-wire.html#taler-wire-gateway-http-api>
-use crate::types::{amount::Amount, payto::PaytoURI, timestamp::Timestamp};
+use crate::types::{amount::Amount, payto::PaytoURI, timestamp::TalerTimestamp};
use super::api_common::SafeU64;
use serde::{Deserialize, Serialize};
@@ -41,7 +41,7 @@ pub struct RevenueIncomingHistory {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct RevenueIncomingBankTransaction {
pub row_id: SafeU64,
- pub date: Timestamp,
+ pub date: TalerTimestamp,
pub amount: Amount,
pub credit_fee: Option<Amount>,
pub debit_account: PaytoURI,
diff --git a/common/taler-common/src/api_wire.rs b/common/taler-common/src/api_wire.rs
@@ -18,7 +18,7 @@
use url::Url;
-use crate::types::{amount::Amount, payto::PaytoURI, timestamp::Timestamp};
+use crate::types::{amount::Amount, payto::PaytoURI, timestamp::TalerTimestamp};
use super::api_common::{EddsaPublicKey, HashCode, SafeU64, ShortHashCode, WadId};
use serde::{Deserialize, Serialize};
@@ -36,7 +36,7 @@ pub struct WireConfig<'a> {
/// <https://docs.taler.net/core/api-bank-wire.html#tsref-type-TransferResponse>
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TransferResponse {
- pub timestamp: Timestamp,
+ pub timestamp: TalerTimestamp,
pub row_id: SafeU64,
}
@@ -64,7 +64,7 @@ pub struct TransferListStatus {
pub status: TransferState,
pub amount: Amount,
pub credit_account: PaytoURI,
- pub timestamp: Timestamp,
+ pub timestamp: TalerTimestamp,
}
/// <https://docs.taler.net/core/api-bank-wire.html#tsref-type-TransfertSatus>
@@ -76,7 +76,7 @@ pub struct TransferStatus {
pub origin_exchange_url: String,
pub wtid: ShortHashCode,
pub credit_account: PaytoURI,
- pub timestamp: Timestamp,
+ pub timestamp: TalerTimestamp,
}
/// <https://docs.taler.net/core/api-bank-wire.html#tsref-type-OutgoingHistory>
@@ -90,7 +90,7 @@ pub struct OutgoingHistory {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct OutgoingBankTransaction {
pub row_id: SafeU64,
- pub date: Timestamp,
+ pub date: TalerTimestamp,
pub amount: Amount,
pub credit_account: PaytoURI,
pub wtid: ShortHashCode,
@@ -111,7 +111,7 @@ pub enum IncomingBankTransaction {
#[serde(rename = "RESERVE")]
Reserve {
row_id: SafeU64,
- date: Timestamp,
+ date: TalerTimestamp,
amount: Amount,
debit_account: PaytoURI,
reserve_pub: EddsaPublicKey,
@@ -119,7 +119,7 @@ pub enum IncomingBankTransaction {
#[serde(rename = "WAD")]
Wad {
row_id: SafeU64,
- date: Timestamp,
+ date: TalerTimestamp,
amount: Amount,
debit_account: PaytoURI,
origin_exchange_url: Url,
@@ -128,7 +128,7 @@ pub enum IncomingBankTransaction {
#[serde(rename = "KYCAUTH")]
Kyc {
row_id: SafeU64,
- date: Timestamp,
+ date: TalerTimestamp,
amount: Amount,
debit_account: PaytoURI,
account_pub: EddsaPublicKey,
@@ -147,7 +147,7 @@ pub struct AddIncomingRequest {
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddIncomingResponse {
pub row_id: SafeU64,
- pub timestamp: Timestamp,
+ pub timestamp: TalerTimestamp,
}
/// <https://docs.taler.net/core/api-bank-wire.html#tsref-type-AddKycauthRequest>
diff --git a/common/taler-common/src/types/timestamp.rs b/common/taler-common/src/types/timestamp.rs
@@ -16,63 +16,23 @@
use std::{fmt::Display, ops::Add};
-use jiff::{civil::Time, tz::TimeZone};
+use jiff::{Timestamp, civil::Time, tz::TimeZone};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error, ser::SerializeStruct}; // codespell:ignore
use serde_json::Value;
/// <https://docs.taler.net/core/api-common.html#tsref-type-Timestamp>
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Timestamp(pub jiff::Timestamp);
+pub enum TalerTimestamp {
+ Never,
+ Timestamp(Timestamp),
+}
#[derive(Serialize, Deserialize)]
struct TimestampImpl {
t_s: Value,
}
-impl Timestamp {
- /** Timestamp corresponding to "now" */
- pub fn now() -> Self {
- Self(jiff::Timestamp::now())
- }
-
- /** Timestamp corresponding to now as it would be stored in db */
- pub fn now_stable() -> Self {
- Self::from_sql_micros(Self::now().as_sql_micros())
- .expect("timestamp sql roundtrip must always succeed")
- }
-
- /** Timestamp corresponding to "never" */
- pub const fn never() -> Self {
- Self(jiff::Timestamp::MAX)
- }
-
- /** Whether timestamp correspond to "never" */
- pub fn is_never(&self) -> bool {
- self.0 == jiff::Timestamp::MAX
- }
-
- /** I64 equivalent of this timestamp for db storage */
- pub fn as_sql_micros(&self) -> i64 {
- if self.is_never() {
- i64::MAX
- } else {
- self.0.as_microsecond()
- }
- }
-
- /** Timestamp equivalent of as i64 as stored in db */
- pub fn from_sql_micros(micros: i64) -> Result<Self, String> {
- if micros == i64::MAX {
- Ok(Self::never())
- } else {
- let timestamp = jiff::Timestamp::from_microsecond(micros)
- .map_err(|e| format!("expected timestamp micros got overflowing {micros}: {e}"))?;
- Ok(Self(timestamp))
- }
- }
-}
-
-impl<'de> Deserialize<'de> for Timestamp {
+impl<'de> Deserialize<'de> for TalerTimestamp {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
@@ -82,51 +42,50 @@ impl<'de> Deserialize<'de> for Timestamp {
Value::Number(s) => {
if let Some(since_epoch_s) = s.as_i64() {
jiff::Timestamp::from_second(since_epoch_s)
- .map(Self)
+ .map(Self::Timestamp)
.map_err(Error::custom)
} else {
Err(Error::custom("Expected epoch time"))
}
}
- Value::String(str) if str == "never" => Ok(Self::never()),
+ Value::String(str) if str == "never" => Ok(Self::Never),
_ => Err(Error::custom("Expected epoch time or 'never'")),
}
}
}
-impl Serialize for Timestamp {
+impl Serialize for TalerTimestamp {
fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut se_struct = se.serialize_struct("Timestamp", 1)?;
- if self.is_never() {
- se_struct.serialize_field("t_s", "never")?
- } else {
- se_struct.serialize_field("t_s", &self.0.as_second())?
+ match self {
+ TalerTimestamp::Never => se_struct.serialize_field("t_s", "never")?,
+ TalerTimestamp::Timestamp(timestamp) => {
+ se_struct.serialize_field("t_s", ×tamp.as_second())?
+ }
}
-
se_struct.end()
}
}
-impl Display for Timestamp {
+impl Display for TalerTimestamp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- if self.is_never() {
- f.write_str("never")
- } else {
- self.0.fmt(f)
+ match self {
+ TalerTimestamp::Never => f.write_str("never"),
+ TalerTimestamp::Timestamp(timestamp) => timestamp.fmt(f),
}
}
}
-impl From<jiff::Timestamp> for Timestamp {
+impl From<jiff::Timestamp> for TalerTimestamp {
fn from(time: jiff::Timestamp) -> Self {
- Self(time)
+ Self::Timestamp(time)
}
}
-impl From<jiff::civil::Date> for Timestamp {
+impl From<jiff::civil::Date> for TalerTimestamp {
fn from(date: jiff::civil::Date) -> Self {
date.to_datetime(Time::midnight())
.to_zoned(TimeZone::UTC)
@@ -136,22 +95,13 @@ impl From<jiff::civil::Date> for Timestamp {
}
}
-impl Add<jiff::Span> for Timestamp {
+impl Add<jiff::Span> for TalerTimestamp {
type Output = Self;
fn add(self, rhs: jiff::Span) -> Self::Output {
- Self(self.0 + rhs)
- }
-}
-
-impl PartialEq<jiff::Timestamp> for Timestamp {
- fn eq(&self, other: &jiff::Timestamp) -> bool {
- self.0.eq(other)
- }
-}
-
-impl PartialOrd<jiff::Timestamp> for Timestamp {
- fn partial_cmp(&self, other: &jiff::Timestamp) -> Option<std::cmp::Ordering> {
- self.0.partial_cmp(other)
+ match self {
+ TalerTimestamp::Never => TalerTimestamp::Never,
+ TalerTimestamp::Timestamp(timestamp) => TalerTimestamp::Timestamp(timestamp + rhs),
+ }
}
}
diff --git a/common/taler-common/src/types/utils.rs b/common/taler-common/src/types/utils.rs
@@ -16,9 +16,7 @@
use std::{fmt::Debug, ops::Deref};
-use jiff::{civil::Date, tz::TimeZone};
-
-use crate::types::timestamp::Timestamp;
+use jiff::{Timestamp, civil::Date, tz::TimeZone};
#[derive(Clone, PartialEq, Eq)]
pub struct InlineStr<const LEN: usize> {
@@ -95,6 +93,10 @@ impl<const LEN: usize> Deref for InlineStr<LEN> {
/** Convert a date to a UTC timestamp */
pub fn date_to_utc_timestamp(date: &Date) -> Timestamp {
- let zoned = date.to_zoned(TimeZone::UTC).unwrap();
- Timestamp(zoned.timestamp())
+ date.to_zoned(TimeZone::UTC).unwrap().timestamp()
+}
+
+/** Get current timestamp truncated to micros precision */
+pub fn now_sql_stable_timestamp() -> Timestamp {
+ Timestamp::from_microsecond(Timestamp::now().as_microsecond()).unwrap()
}
diff --git a/taler-magnet-bank/src/api.rs b/taler-magnet-bank/src/api.rs
@@ -14,6 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+use jiff::Timestamp;
use taler_api::{
api::{TalerApi, revenue::Revenue, wire::WireGateway},
error::{ApiResult, failure},
@@ -29,7 +30,7 @@ use taler_common::{
TransferState, TransferStatus,
},
error_code::ErrorCode,
- types::{payto::PaytoURI, timestamp::Timestamp, utils::date_to_utc_timestamp},
+ types::{payto::PaytoURI, utils::date_to_utc_timestamp},
};
use tokio::sync::watch::Sender;
@@ -89,7 +90,7 @@ impl WireGateway for MagnetApi {
let result = db::make_transfer(&self.pool, &req, &creditor, &Timestamp::now()).await?;
match result {
db::TransferResult::Success { id, initiated_at } => Ok(TransferResponse {
- timestamp: initiated_at,
+ timestamp: initiated_at.into(),
row_id: SafeU64::try_from(id).unwrap(),
}),
db::TransferResult::RequestUidReuse => Err(failure(
@@ -159,7 +160,7 @@ impl WireGateway for MagnetApi {
row_id, valued_at, ..
} => Ok(AddIncomingResponse {
row_id: safe_u64(row_id),
- timestamp: date_to_utc_timestamp(&valued_at),
+ timestamp: date_to_utc_timestamp(&valued_at).into(),
}),
AddIncomingResult::ReservePubReuse => Err(failure(
ErrorCode::BANK_DUPLICATE_RESERVE_PUB_SUBJECT,
@@ -186,7 +187,7 @@ impl WireGateway for MagnetApi {
row_id, valued_at, ..
} => Ok(AddKycauthResponse {
row_id: safe_u64(row_id),
- timestamp: date_to_utc_timestamp(&valued_at),
+ timestamp: date_to_utc_timestamp(&valued_at).into(),
}),
AddIncomingResult::ReservePubReuse => Err(failure(
ErrorCode::BANK_DUPLICATE_RESERVE_PUB_SUBJECT,
diff --git a/taler-magnet-bank/src/bin/magnet-bank-harness.rs b/taler-magnet-bank/src/bin/magnet-bank-harness.rs
@@ -30,7 +30,7 @@ use taler_common::{
config::Config,
db::{dbinit, pool},
taler_main,
- types::{self, amount::amount, url},
+ types::{amount::amount, url},
};
use taler_magnet_bank::{
FullHuPayto, HuIban,
@@ -147,7 +147,7 @@ impl<'a> Harness<'a> {
credit_account: creditor.as_payto(),
},
creditor,
- &types::timestamp::Timestamp::now(),
+ &Timestamp::now(),
)
.await
.unwrap();
diff --git a/taler-magnet-bank/src/db.rs b/taler-magnet-bank/src/db.rs
@@ -16,7 +16,7 @@
use std::fmt::Display;
-use jiff::{civil::Date, tz::TimeZone};
+use jiff::{Timestamp, civil::Date, tz::TimeZone};
use serde::{Serialize, de::DeserializeOwned};
use sqlx::{PgConnection, PgExecutor, PgPool, QueryBuilder, Row, postgres::PgRow};
use taler_api::{
@@ -30,7 +30,7 @@ use taler_common::{
IncomingBankTransaction, OutgoingBankTransaction, TransferListStatus, TransferRequest,
TransferState, TransferStatus,
},
- types::{amount::Amount, payto::PaytoImpl as _, timestamp::Timestamp},
+ types::{amount::Amount, payto::PaytoImpl as _},
};
use tokio::sync::watch::{Receiver, Sender};
@@ -175,7 +175,7 @@ pub async fn register_tx_in_admin(
.bind(&tx.subject)
.bind(tx.debtor.iban())
.bind(&tx.debtor.name)
- .bind_date(&now.0.to_zoned(TimeZone::UTC).date())
+ .bind_date(&now.to_zoned(TimeZone::UTC).date())
.bind(tx.metadata.ty())
.bind(tx.metadata.key())
.try_map(|r: PgRow| {
@@ -451,7 +451,7 @@ pub async fn transfer_page<'a>(
status: r.try_get(1)?,
amount: r.try_get_amount_i(2, &CURRENCY)?,
credit_account: r.try_get_iban(4)?.as_full_payto(r.try_get(5)?),
- timestamp: r.try_get_timestamp(6)?,
+ timestamp: r.try_get_timestamp(6)?.into(),
})
},
)
@@ -491,7 +491,7 @@ pub async fn outgoing_history(
row_id: r.try_get_safeu64(0)?,
amount: r.try_get_amount_i(1, &CURRENCY)?,
credit_account: r.try_get_iban(3)?.as_full_payto(r.try_get(4)?),
- date: r.try_get_timestamp(5)?,
+ date: r.try_get_timestamp(5)?.into(),
exchange_base_url: r.try_get_url(6)?,
wtid: r.try_get_base32(7)?,
})
@@ -534,14 +534,14 @@ pub async fn incoming_history(
row_id: r.try_get_safeu64(1)?,
amount: r.try_get_amount_i(2, &CURRENCY)?,
debit_account: r.try_get_iban(4)?.as_full_payto(r.try_get(5)?),
- date: r.try_get_timestamp(6)?,
+ date: r.try_get_timestamp(6)?.into(),
reserve_pub: r.try_get_base32(7)?,
},
IncomingType::kyc => IncomingBankTransaction::Kyc {
row_id: r.try_get_safeu64(1)?,
amount: r.try_get_amount_i(2, &CURRENCY)?,
debit_account: r.try_get_iban(4)?.as_full_payto(r.try_get(5)?),
- date: r.try_get_timestamp(6)?,
+ date: r.try_get_timestamp(6)?.into(),
account_pub: r.try_get_base32(7)?,
},
IncomingType::wad => {
@@ -582,7 +582,7 @@ pub async fn revenue_history(
|r: PgRow| {
Ok(RevenueIncomingBankTransaction {
row_id: r.try_get_safeu64(0)?,
- date: r.try_get_timestamp(1)?,
+ date: r.try_get_timestamp(1)?.into(),
amount: r.try_get_amount_i(2, &CURRENCY)?,
credit_fee: None,
debit_account: r.try_get_iban(4)?.as_full_payto(r.try_get(5)?),
@@ -623,7 +623,7 @@ pub async fn transfer_by_id<'a>(
origin_exchange_url: r.try_get(4)?,
wtid: r.try_get_base32(5)?,
credit_account: r.try_get_iban(6)?.as_full_payto(r.try_get(7)?),
- timestamp: r.try_get_timestamp(8)?,
+ timestamp: r.try_get_timestamp(8)?.into(),
})
})
.fetch_optional(db)
@@ -765,7 +765,7 @@ pub async fn kv_set<'a, T: Serialize>(
#[cfg(test)]
mod test {
- use jiff::{Span, Zoned};
+ use jiff::{Span, Timestamp, Zoned};
use serde_json::json;
use sqlx::{PgConnection, PgPool, postgres::PgRow};
use taler_api::{
@@ -776,7 +776,7 @@ mod test {
api_common::{EddsaPublicKey, HashCode, ShortHashCode},
api_params::{History, Page},
api_wire::TransferRequest,
- types::{amount::amount, payto::payto, timestamp::Timestamp, url},
+ types::{amount::amount, payto::payto, url, utils::now_sql_stable_timestamp},
};
use tokio::sync::watch::Receiver;
@@ -839,7 +839,7 @@ mod test {
.fetch_one(&mut *db)
.await
.unwrap();
- let now = Timestamp::now_stable();
+ let now = now_sql_stable_timestamp();
let date = Zoned::now().date();
let later = date.tomorrow().unwrap();
let tx = TxIn {
@@ -966,7 +966,7 @@ mod test {
Vec::new()
);
- let now = Timestamp::now_stable();
+ let now = now_sql_stable_timestamp();
let later = now + Span::new().hours(2);
let date = Zoned::now().date();
let tx = TxInAdmin {
@@ -1038,7 +1038,7 @@ mod test {
.fetch_one(&mut *db)
.await
.unwrap();
- let now = Timestamp::now_stable();
+ let now = now_sql_stable_timestamp();
let date = Zoned::now().date();
let later = date.tomorrow().unwrap();
let tx = TxOut {
@@ -1165,7 +1165,7 @@ mod test {
async fn tx_out_failure() {
let (mut db, _) = setup().await;
- let now = Timestamp::now_stable();
+ let now = now_sql_stable_timestamp();
// Unknown
assert_eq!(
@@ -1286,7 +1286,7 @@ mod test {
credit_account: payto("payto://iban/HU02162000031000164800000000?receiver-name=name"),
};
let payto = magnet_payto("payto://iban/HU30162000031000163100000000?receiver-name=name");
- let now = Timestamp::now_stable();
+ let now = now_sql_stable_timestamp();
let later = now + Span::new().hours(2);
// Insert
assert_eq!(
@@ -1295,7 +1295,7 @@ mod test {
.expect("transfer"),
TransferResult::Success {
id: 1,
- initiated_at: now
+ initiated_at: now.into()
}
);
// Idempotent
@@ -1305,7 +1305,7 @@ mod test {
.expect("transfer"),
TransferResult::Success {
id: 1,
- initiated_at: now
+ initiated_at: now.into()
}
);
// Request UID reuse
@@ -1354,7 +1354,7 @@ mod test {
.expect("transfer"),
TransferResult::Success {
id: 2,
- initiated_at: later
+ initiated_at: later.into()
}
);
@@ -1377,7 +1377,7 @@ mod test {
let amount = amount("HUF:10");
let payto = magnet_payto("payto://iban/HU30162000031000163100000000?receiver-name=name");
- let now = Timestamp::now_stable();
+ let now = now_sql_stable_timestamp();
let date = Zoned::now().date();
// Empty db
@@ -1569,7 +1569,7 @@ mod test {
),
},
&magnet_payto,
- &&Timestamp::now(),
+ &Timestamp::now(),
)
.await
.expect("transfer");
diff --git a/taler-magnet-bank/src/worker.rs b/taler-magnet-bank/src/worker.rs
@@ -16,14 +16,13 @@
use std::num::ParseIntError;
-use jiff::{Zoned, civil::Date};
+use jiff::{Timestamp, Zoned, civil::Date};
use p256::ecdsa::SigningKey;
use sqlx::PgConnection;
use taler_api::subject::{self, parse_incoming_unstructured};
use taler_common::types::{
amount::{self},
iban::IBAN,
- timestamp::Timestamp,
};
use tracing::{debug, error, info, trace, warn};
diff --git a/taler-magnet-bank/tests/api.rs b/taler-magnet-bank/tests/api.rs
@@ -16,14 +16,14 @@
use std::sync::Arc;
-use jiff::Zoned;
+use jiff::{Timestamp, Zoned};
use sqlx::PgPool;
use taler_api::{api::TalerRouter as _, auth::AuthMethod, subject::OutgoingSubject};
use taler_common::{
api_common::ShortHashCode,
api_revenue::RevenueConfig,
api_wire::{OutgoingHistory, TransferState, WireConfig},
- types::{amount::amount, payto::payto, timestamp::Timestamp, url},
+ types::{amount::amount, payto::payto, url},
};
use taler_magnet_bank::{
api::MagnetApi,
@@ -93,7 +93,6 @@ async fn outgoing_history() {
},
|_, i| {
let acquire = pool.acquire();
- Timestamp::now().to_string();
async move {
let mut conn = acquire.await.unwrap();
let now = Zoned::now().date();