1use std::str::FromStr;
2
3use serde::{Deserialize, Serialize};
4
5use crate::{Payment, PaymentStatus, SignedTransferPackage};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
8#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
9pub enum TokenAllowanceLimit {
10 Unlimited,
11 Amount { amount: u128 },
12}
13
14#[derive(Debug, Clone)]
15#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
16pub struct CreateTokenAllowanceRequest {
17 pub spender_address: String,
19 pub token_identifier: String,
20 pub max_per_payment: TokenAllowanceLimit,
22 pub max_total: TokenAllowanceLimit,
24 pub expiry_time: u64,
26 pub allowed_recipients: Vec<String>,
28}
29
30#[derive(Debug, Clone, Serialize)]
31#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
32pub struct CreateTokenAllowanceResponse {
33 pub allowance: TokenAllowance,
34}
35
36#[derive(Debug, Clone)]
37#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
38pub struct RevokeTokenAllowanceRequest {
39 pub allowance_id: String,
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
43#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
44pub enum TokenAllowanceRole {
45 Owner,
46 Spender,
47}
48
49impl FromStr for TokenAllowanceRole {
50 type Err = String;
51
52 fn from_str(s: &str) -> Result<Self, Self::Err> {
53 match s.to_lowercase().as_str() {
54 "owner" => Ok(Self::Owner),
55 "spender" => Ok(Self::Spender),
56 _ => Err(format!("Invalid token allowance role '{s}'")),
57 }
58 }
59}
60
61#[derive(Debug, Clone)]
62#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
63pub struct ListTokenAllowancesRequest {
64 pub role: TokenAllowanceRole,
65 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
66 pub counterparty_address: Option<String>,
67 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
68 pub token_identifier: Option<String>,
69 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
70 pub include_inactive: Option<bool>,
71 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
72 pub offset: Option<u32>,
73 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
74 pub limit: Option<u32>,
75}
76
77#[derive(Debug, Clone, Serialize)]
78#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
79pub struct ListTokenAllowancesResponse {
80 pub allowances: Vec<TokenAllowance>,
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
84#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
85pub enum TokenAllowanceStatus {
86 Active,
87 Exhausted,
88 Expired,
89 Revoked,
90}
91
92#[derive(Debug, Clone, Serialize)]
93#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
94pub struct TokenAllowance {
95 pub id: String,
96 pub owner_address: String,
97 pub spender_address: String,
98 pub token_identifier: String,
99 pub max_per_payment: TokenAllowanceLimit,
101 pub max_total: TokenAllowanceLimit,
103 pub spent_amount: u128,
106 pub allowed_recipients: Vec<String>,
108 pub expiry_time: u64,
110 pub created_at: u64,
111 pub revoked_at: Option<u64>,
112 pub status: TokenAllowanceStatus,
113}
114
115#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
116#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
117pub struct PullReceiver {
118 pub amount: u128,
119 #[cfg_attr(feature = "uniffi", uniffi(default = None))]
121 pub receiver_address: Option<String>,
122}
123
124#[derive(Debug, Clone)]
125#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
126pub struct PreparePullPaymentRequest {
127 pub payer_address: String,
129 pub token_identifier: String,
130 pub receivers: Vec<PullReceiver>,
131}
132
133#[derive(Debug, Clone, Serialize)]
134#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
135pub struct PreparePullPaymentResponse {
136 pub payer_address: String,
137 pub token_identifier: String,
138 pub receivers: Vec<PullReceiver>,
139 pub amount: u128,
140 pub allowance_id: String,
141 pub expiry_time: u64,
143 pub pull_context: Vec<u8>,
145}
146
147#[derive(Debug, Clone)]
148#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
149pub struct PullPaymentRequest {
150 pub prepare_response: PreparePullPaymentResponse,
151}
152
153#[derive(Debug, Clone, Serialize)]
154#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
155pub struct PullPaymentResponse {
156 pub tx_hash: String,
157 pub status: PaymentStatus,
160 pub payment: Option<Payment>,
163}
164
165#[derive(Debug, Clone)]
166#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
167pub struct BuildUnsignedPullPackageRequest {
168 pub prepare_response: PreparePullPaymentResponse,
169}
170
171#[derive(Debug, Clone)]
172#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
173pub struct PublishSignedPullPackageRequest {
174 pub signed_package: SignedTransferPackage,
175}
176
177impl From<TokenAllowanceLimit> for Option<u128> {
178 fn from(limit: TokenAllowanceLimit) -> Self {
179 match limit {
180 TokenAllowanceLimit::Unlimited => None,
181 TokenAllowanceLimit::Amount { amount } => Some(amount),
182 }
183 }
184}
185
186impl From<Option<u128>> for TokenAllowanceLimit {
187 fn from(limit: Option<u128>) -> Self {
188 match limit {
189 Some(amount) => Self::Amount { amount },
190 None => Self::Unlimited,
191 }
192 }
193}
194
195impl From<TokenAllowanceRole> for spark_wallet::TokenAllowanceRole {
196 fn from(role: TokenAllowanceRole) -> Self {
197 match role {
198 TokenAllowanceRole::Owner => Self::Owner,
199 TokenAllowanceRole::Spender => Self::Spender,
200 }
201 }
202}
203
204impl From<spark_wallet::TokenAllowanceStatus> for TokenAllowanceStatus {
205 fn from(status: spark_wallet::TokenAllowanceStatus) -> Self {
206 match status {
207 spark_wallet::TokenAllowanceStatus::Active => Self::Active,
208 spark_wallet::TokenAllowanceStatus::Exhausted => Self::Exhausted,
209 spark_wallet::TokenAllowanceStatus::Expired => Self::Expired,
210 spark_wallet::TokenAllowanceStatus::Revoked => Self::Revoked,
211 }
212 }
213}