1use block_chain::block::Block;
7use block_chain::blockchain::Blockchain;
8use block_chain::wallet::{Transaction, Wallet};
9use futures::stream::TryStreamExt;
10use futures::StreamExt;
11use mongodb::{
12 bson::{self, doc, Document},
13 Collection,
14};
15use std::collections::HashMap;
16use std::error::Error;
17
18pub async fn reset_sample_data(
22 blockchain_collection: Collection<Document>,
23 blocks_collection: Collection<Document>,
24 wallets_collection: Collection<Document>,
25) -> Result<(), Box<dyn Error>> {
26 println!("Resetting Sample Data...");
27
28 blockchain_collection.delete_many(doc! {}).await?;
30
31 blocks_collection.delete_many(doc! {}).await?;
33
34 wallets_collection.delete_many(doc! {}).await?;
36
37 let genesis_blockchain = doc! {
39 "id": 1,
40 "chain": [
41 {
42 "block_index": 0,
43 "timestamp": 0,
44 "previous_hash": "0",
45 "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
46 "data": "Genesis Block",
47 "miner_address": "genesis_miner_address",
48 "transactions": []
49 }
50 ],
51 "mempool": []
52 };
53
54 let genesis_block = doc! {
55 "block_index": 0,
56 "timestamp": 0,
57 "previous_hash": "0",
58 "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
59 "data": "Genesis Block",
60 "miner_address": "genesis_miner_address",
61 "transactions": []
62 };
63
64 let wallet1_data = doc! {
65 "address": "address1",
66 "private_key": "private_key1",
67 "public_key": "public_key1",
68 "balance": 50.0,
69 "transaction_history": [],
70 "pending_transactions": []
71 };
72
73 let wallet2_data = doc! {
74 "address": "address2",
75 "private_key": "private_key2",
76 "public_key": "public_key2",
77 "balance": 20.0,
78 "transaction_history": [],
79 "pending_transactions": []
80 };
81
82 blockchain_collection.insert_one(genesis_blockchain).await?;
84
85 blocks_collection.insert_one(genesis_block).await?;
87
88 wallets_collection.insert_one(wallet1_data).await?;
90 wallets_collection.insert_one(wallet2_data).await?;
91
92 println!("Sample data has been reset.\n");
93
94 Ok(())
95}
96
97pub async fn load_blockchain(
101 blocks_collection: Collection<Document>,
102 blockchain_collection: Collection<Document>,
103) -> Result<Blockchain, Box<dyn Error>> {
104 let mut blockchain = Blockchain::new();
105
106 println!("\nLoading blocks from MongoDB:");
108
109 let mut cursor = blocks_collection.find(doc! {}).await?;
110 while let Some(result) = cursor.try_next().await? {
111 let block: Block = bson::from_document(result)?;
112 blockchain.chain.push(block);
116 }
117
118 let blockchain_doc = blockchain_collection.find_one(doc! { "id": 1 }).await?;
120 if let Some(doc) = blockchain_doc {
121 let chain: Vec<Block> =
122 bson::from_bson(doc.get("chain").unwrap().clone()).unwrap_or_default();
123 for block in chain {
124 if !blockchain.chain.contains(&block) {
125 blockchain.chain.push(block);
126 }
127 }
128
129 let mempool: Vec<Transaction> =
131 bson::from_bson(doc.get("mempool").unwrap().clone()).unwrap_or_default();
132 blockchain.mempool = mempool;
133 }
134
135 Ok(blockchain)
136}
137
138pub async fn load_wallet(
142 wallets_collection: Collection<Document>,
143 address: &str,
144) -> Result<Wallet, Box<dyn Error>> {
145 let filter = doc! {"address": address};
146 let result = wallets_collection.find_one(filter).await?;
147
148 if let Some(doc) = result {
149 let wallet: Wallet = bson::from_document(doc)?;
150 Ok(wallet)
151 } else {
152 Err("Wallet not found".into())
153 }
154}
155
156pub async fn load_wallets(
160 wallets_collection: Collection<Document>,
161) -> Result<HashMap<String, Wallet>, Box<dyn Error>> {
162 let mut wallet_map: HashMap<String, Wallet> = HashMap::new();
164
165 let mut cursor = wallets_collection.find(doc! {}).await?;
167
168 while let Some(result) = cursor.next().await {
170 if let Ok(doc) = result {
171 let wallet: Wallet = bson::from_document(doc)?;
172 wallet_map.insert(wallet.address.clone(), wallet);
173 }
174 }
175
176 Ok(wallet_map)
177}
178
179pub async fn save_blockchain(
183 blockchain: &Blockchain,
184 blocks_collection: Collection<Document>,
185 blockchain_collection: Collection<Document>,
186) -> Result<(), Box<dyn Error>> {
187 blocks_collection.drop().await?;
189 for block in &blockchain.chain {
190 let doc = bson::to_document(block)?;
191 blocks_collection.insert_one(doc).await?;
192 }
193
194 let blockchain_doc = doc! {
196 "id": 1,
197 "chain": bson::to_bson(&blockchain.chain)?,
198 "mempool": bson::to_bson(&blockchain.mempool)?
199 };
200 blockchain_collection
201 .update_one(doc! { "id": 1 }, doc! { "$set": blockchain_doc })
202 .await?;
203
204 Ok(())
205}
206
207pub async fn save_wallet(
211 wallet: Wallet,
212 wallets_collection: Collection<Document>,
213) -> Result<(), Box<dyn Error>> {
214 let filter = doc! {"address": wallet.address.clone()};
215 let update = bson::to_document(&wallet)?;
216 wallets_collection.replace_one(filter, update).await?;
217 Ok(())
218}