Skip to main content

allsource_core/application/dto/
transaction_dto.rs

1use crate::domain::entities::{Blockchain, Transaction, TransactionStatus};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6/// DTO for initiating a payment transaction
7#[derive(Debug, Deserialize)]
8pub struct InitiatePaymentRequest {
9    pub tenant_id: String,
10    pub article_id: String,
11    pub reader_wallet: String,
12    pub tx_signature: String,
13    pub blockchain: Option<BlockchainDto>,
14}
15
16/// DTO for payment initiation response
17#[derive(Debug, Serialize)]
18pub struct InitiatePaymentResponse {
19    pub transaction: TransactionDto,
20}
21
22/// DTO for confirming a transaction
23#[derive(Debug, Deserialize)]
24pub struct ConfirmTransactionRequest {
25    pub transaction_id: String,
26}
27
28/// DTO for transaction confirmation response
29#[derive(Debug, Serialize)]
30pub struct ConfirmTransactionResponse {
31    pub transaction: TransactionDto,
32    pub access_token: Option<String>,
33}
34
35/// DTO for refunding a transaction
36#[derive(Debug, Deserialize)]
37pub struct RefundTransactionRequest {
38    pub transaction_id: String,
39    pub refund_tx_signature: String,
40    pub reason: Option<String>,
41}
42
43/// DTO for refund response
44#[derive(Debug, Serialize)]
45pub struct RefundTransactionResponse {
46    pub transaction: TransactionDto,
47}
48
49/// DTO for listing transactions response
50#[derive(Debug, Serialize)]
51pub struct ListTransactionsResponse {
52    pub transactions: Vec<TransactionDto>,
53    pub count: usize,
54}
55
56/// DTO for blockchain type
57#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
58#[serde(rename_all = "snake_case")]
59pub enum BlockchainDto {
60    Solana,
61    Base,
62    Polygon,
63}
64
65impl Default for BlockchainDto {
66    fn default() -> Self {
67        Self::Solana
68    }
69}
70
71impl From<Blockchain> for BlockchainDto {
72    fn from(blockchain: Blockchain) -> Self {
73        match blockchain {
74            Blockchain::Solana => BlockchainDto::Solana,
75            Blockchain::Base => BlockchainDto::Base,
76            Blockchain::Polygon => BlockchainDto::Polygon,
77        }
78    }
79}
80
81impl From<BlockchainDto> for Blockchain {
82    fn from(dto: BlockchainDto) -> Self {
83        match dto {
84            BlockchainDto::Solana => Blockchain::Solana,
85            BlockchainDto::Base => Blockchain::Base,
86            BlockchainDto::Polygon => Blockchain::Polygon,
87        }
88    }
89}
90
91/// DTO for transaction status
92#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
93#[serde(rename_all = "snake_case")]
94pub enum TransactionStatusDto {
95    Pending,
96    Confirmed,
97    Failed,
98    Refunded,
99    Disputed,
100}
101
102impl From<TransactionStatus> for TransactionStatusDto {
103    fn from(status: TransactionStatus) -> Self {
104        match status {
105            TransactionStatus::Pending => TransactionStatusDto::Pending,
106            TransactionStatus::Confirmed => TransactionStatusDto::Confirmed,
107            TransactionStatus::Failed => TransactionStatusDto::Failed,
108            TransactionStatus::Refunded => TransactionStatusDto::Refunded,
109            TransactionStatus::Disputed => TransactionStatusDto::Disputed,
110        }
111    }
112}
113
114/// DTO for a transaction in responses
115#[derive(Debug, Clone, Serialize)]
116pub struct TransactionDto {
117    pub id: Uuid,
118    pub tenant_id: String,
119    pub article_id: String,
120    pub creator_id: String,
121    pub reader_wallet: String,
122    pub amount_cents: u64,
123    pub platform_fee_cents: u64,
124    pub creator_amount_cents: u64,
125    pub blockchain: BlockchainDto,
126    pub tx_signature: String,
127    pub status: TransactionStatusDto,
128    pub explorer_url: String,
129    pub created_at: DateTime<Utc>,
130    pub confirmed_at: Option<DateTime<Utc>>,
131    pub refunded_at: Option<DateTime<Utc>>,
132}
133
134impl From<&Transaction> for TransactionDto {
135    fn from(tx: &Transaction) -> Self {
136        Self {
137            id: tx.id().as_uuid(),
138            tenant_id: tx.tenant_id().to_string(),
139            article_id: tx.article_id().to_string(),
140            creator_id: tx.creator_id().as_uuid().to_string(),
141            reader_wallet: tx.reader_wallet().to_string(),
142            amount_cents: tx.amount_cents(),
143            platform_fee_cents: tx.platform_fee_cents(),
144            creator_amount_cents: tx.creator_amount_cents(),
145            blockchain: tx.blockchain().into(),
146            tx_signature: tx.tx_signature().to_string(),
147            status: tx.status().into(),
148            explorer_url: tx.explorer_url(),
149            created_at: tx.created_at(),
150            confirmed_at: tx.confirmed_at(),
151            refunded_at: tx.refunded_at(),
152        }
153    }
154}
155
156impl From<Transaction> for TransactionDto {
157    fn from(tx: Transaction) -> Self {
158        TransactionDto::from(&tx)
159    }
160}
161
162/// DTO for revenue summary
163#[derive(Debug, Serialize)]
164pub struct RevenueSummaryDto {
165    pub total_revenue_cents: u64,
166    pub total_transactions: u64,
167    pub total_platform_fees_cents: u64,
168    pub total_creator_earnings_cents: u64,
169}