1use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct Bid {
12 pub provider: String,
13 pub price_uakt: u64,
14 pub resources: Resources,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct BidId {
20 pub owner: String,
21 pub dseq: u64,
22 pub gseq: u32,
23 pub oseq: u32,
24 pub provider: String,
25 pub bseq: u32,
26}
27
28impl BidId {
29 pub fn from_bid(owner: &str, dseq: u64, gseq: u32, oseq: u32, bid: &Bid) -> Self {
30 Self {
31 owner: owner.to_string(),
32 dseq,
33 gseq,
34 oseq,
35 provider: bid.provider.clone(),
36 bseq: 0, }
38 }
39}
40
41#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct LeaseId {
44 pub owner: String,
45 pub dseq: u64,
46 pub gseq: u32,
47 pub oseq: u32,
48 pub provider: String,
49}
50
51impl From<BidId> for LeaseId {
52 fn from(bid: BidId) -> Self {
53 Self {
54 owner: bid.owner,
55 dseq: bid.dseq,
56 gseq: bid.gseq,
57 oseq: bid.oseq,
58 provider: bid.provider,
59 }
60 }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
65pub enum LeaseState {
66 Active,
67 InsufficientFunds,
68 Closed,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct LeaseInfo {
74 pub state: LeaseState,
75 pub price_uakt: u64,
76}
77
78#[derive(Debug, Clone, Serialize, Deserialize)]
80pub struct CertificateInfo {
81 pub owner: String,
82 pub cert_pem: Vec<u8>,
83 pub serial: String,
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct ProviderInfo {
89 pub address: String,
90 pub host_uri: String,
91 pub email: String,
92 pub website: String,
93 pub attributes: Vec<(String, String)>,
94 pub cached_at: u64,
95}
96
97#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct EscrowInfo {
100 pub balance_uakt: u64,
101 pub deposited_uakt: u64,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct TxResult {
107 pub hash: String,
108 pub code: u32,
109 pub raw_log: String,
110 pub height: u64,
111}
112
113impl TxResult {
114 pub fn is_success(&self) -> bool {
115 self.code == 0
116 }
117}
118
119#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct ServiceEndpoint {
122 pub service: String,
123 pub uri: String,
124 pub port: u16,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct ProviderLeaseStatus {
130 pub ready: bool,
131 pub endpoints: Vec<ServiceEndpoint>,
132}
133
134#[derive(Debug, Clone, Default, Serialize, Deserialize)]
136pub struct Resources {
137 pub cpu_millicores: u32,
138 pub memory_bytes: u64,
139 pub storage_bytes: u64,
140 pub gpu_count: u32,
141}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_bid_id_from_bid() {
149 let bid = Bid {
150 provider: "akash1provider".to_string(),
151 price_uakt: 1000,
152 resources: Resources::default(),
153 };
154
155 let bid_id = BidId::from_bid("akash1owner", 123, 1, 1, &bid);
156 assert_eq!(bid_id.owner, "akash1owner");
157 assert_eq!(bid_id.dseq, 123);
158 assert_eq!(bid_id.gseq, 1);
159 assert_eq!(bid_id.oseq, 1);
160 assert_eq!(bid_id.provider, "akash1provider");
161 }
162
163 #[test]
164 fn test_lease_id_from_bid_id() {
165 let bid_id = BidId {
166 owner: "akash1owner".to_string(),
167 dseq: 456,
168 gseq: 2,
169 oseq: 3,
170 provider: "akash1provider".to_string(),
171 bseq: 1,
172 };
173
174 let lease_id: LeaseId = bid_id.into();
175 assert_eq!(lease_id.owner, "akash1owner");
176 assert_eq!(lease_id.dseq, 456);
177 assert_eq!(lease_id.gseq, 2);
178 assert_eq!(lease_id.oseq, 3);
179 assert_eq!(lease_id.provider, "akash1provider");
180 }
181
182 #[test]
183 fn test_tx_result_is_success() {
184 let success_tx = TxResult {
185 hash: "ABC123".to_string(),
186 code: 0,
187 raw_log: "success".to_string(),
188 height: 1000,
189 };
190 assert!(success_tx.is_success());
191
192 let failed_tx = TxResult {
193 hash: "DEF456".to_string(),
194 code: 5,
195 raw_log: "insufficient funds".to_string(),
196 height: 1001,
197 };
198 assert!(!failed_tx.is_success());
199 }
200
201 #[test]
202 fn test_serialization_golden() {
203 let bid = Bid {
204 provider: "akash1test".to_string(),
205 price_uakt: 5000,
206 resources: Resources {
207 cpu_millicores: 1000,
208 memory_bytes: 1073741824, storage_bytes: 10737418240, gpu_count: 1,
211 },
212 };
213
214 let json = serde_json::to_string(&bid).unwrap();
215
216 let expected = r#"{"provider":"akash1test","price_uakt":5000,"resources":{"cpu_millicores":1000,"memory_bytes":1073741824,"storage_bytes":10737418240,"gpu_count":1}}"#;
218 assert_eq!(
219 json, expected,
220 "JSON structure changed - wire format compatibility broken"
221 );
222
223 let deserialized: Bid = serde_json::from_str(&json).unwrap();
225 assert_eq!(deserialized.provider, bid.provider);
226 assert_eq!(deserialized.price_uakt, bid.price_uakt);
227 }
228
229 #[test]
230 fn test_boundary_conditions() {
231 let bid = Bid {
233 provider: "akash1provider".to_string(),
234 price_uakt: u64::MAX,
235 resources: Resources {
236 cpu_millicores: u32::MAX,
237 memory_bytes: u64::MAX,
238 storage_bytes: u64::MAX,
239 gpu_count: u32::MAX,
240 },
241 };
242
243 let json = serde_json::to_string(&bid).unwrap();
244 let deserialized: Bid = serde_json::from_str(&json).unwrap();
245 assert_eq!(deserialized.price_uakt, u64::MAX);
246 assert_eq!(deserialized.resources.cpu_millicores, u32::MAX);
247
248 let min_resources = Resources {
250 cpu_millicores: 0,
251 memory_bytes: 0,
252 storage_bytes: 0,
253 gpu_count: 0,
254 };
255 let json = serde_json::to_string(&min_resources).unwrap();
256 let deserialized: Resources = serde_json::from_str(&json).unwrap();
257 assert_eq!(deserialized.cpu_millicores, 0);
258 }
259}