diff --git a/heromodels/examples/marketplace_example.rs b/heromodels/examples/marketplace_example.rs new file mode 100644 index 0000000..f60c087 --- /dev/null +++ b/heromodels/examples/marketplace_example.rs @@ -0,0 +1,328 @@ +use chrono::{Duration, Utc}; +use heromodels::db::{Collection, Db}; +use heromodels::models::finance::marketplace::{Bid, Listing, ListingType}; +use heromodels::models::finance::asset::AssetType; +use heromodels_core::Model; + +// Helper function to print listing details +fn print_listing_details(listing: &Listing) { + println!("\n--- Listing Details ---"); + println!("ID: {}", listing.get_id()); + println!("Title: {}", listing.title); + println!("Description: {}", listing.description); + println!("Asset ID: {}", listing.asset_id); + println!("Asset Type: {:?}", listing.asset_type); + println!("Seller ID: {}", listing.seller_id); + println!("Price: {} {}", listing.price, listing.currency); + println!("Listing Type: {:?}", listing.listing_type); + println!("Status: {:?}", listing.status); + + if let Some(expires_at) = listing.expires_at { + println!("Expires At: {}", expires_at); + } else { + println!("Expires At: Never"); + } + + if let Some(sold_at) = listing.sold_at { + println!("Sold At: {}", sold_at); + } + + if let Some(buyer_id) = &listing.buyer_id { + println!("Buyer ID: {}", buyer_id); + } + + if let Some(sale_price) = listing.sale_price { + println!("Sale Price: {} {}", sale_price, listing.currency); + } + + println!("Bids: {}", listing.bids.len()); + println!("Tags: {:?}", listing.tags); + + if let Some(image_url) = &listing.image_url { + println!("Image URL: {}", image_url); + } + + println!("Created At: {}", listing.base_data.created_at); + println!("Modified At: {}", listing.base_data.modified_at); +} + +// Helper function to print bid details +fn print_bid_details(bid: &Bid) { + println!("\n--- Bid Details ---"); + println!("Listing ID: {}", bid.listing_id); + println!("Bidder ID: {}", bid.bidder_id); + println!("Amount: {} {}", bid.amount, bid.currency); + println!("Status: {:?}", bid.status); + println!("Created At: {}", bid.created_at); +} + +fn main() { + // Create a new DB instance in /tmp/marketplace_db, and reset before every run + let db = heromodels::db::hero::OurDB::new("/tmp/marketplace_db", true).expect("Can create DB"); + + println!("Hero Models - Marketplace Example"); + println!("================================"); + + // Create listings with auto-generated IDs + + // Fixed price listing + let fixed_price_listing = Listing::new( + None, // Auto-generated ID + "Vintage Guitar", + "A beautiful vintage guitar in excellent condition", + "asset123", + AssetType::Erc721, // NFT representing a physical item + "seller456", + 1200.0, + "USD", + ListingType::FixedPrice, + Some(Utc::now() + Duration::days(30)), // Expires in 30 days + vec!["music".to_string(), "instrument".to_string(), "vintage".to_string()], + Some("https://example.com/images/vintage_guitar.jpg"), + ); + + // Auction listing + let auction_listing = Listing::new( + None, // Auto-generated ID + "Rare Painting", + "A rare painting from the 19th century", + "asset789", + AssetType::Erc721, // NFT representing a physical item + "seller456", + 5000.0, // Starting price + "USD", + ListingType::Auction, + Some(Utc::now() + Duration::days(7)), // Auction ends in 7 days + vec!["art".to_string(), "painting".to_string(), "antique".to_string()], + Some("https://example.com/images/rare_painting.jpg"), + ); + + // Exchange listing + let exchange_listing = Listing::new( + None, // Auto-generated ID + "Digital Artwork NFT", + "A unique digital artwork as an NFT", + "asset101", + AssetType::Erc1155, // Multi-token for digital art + "seller789", + 0.5, // Price in ETH + "ETH", + ListingType::Exchange, + Some(Utc::now() + Duration::days(14)), // Expires in 14 days + vec!["digital".to_string(), "nft".to_string(), "art".to_string()], + Some("https://example.com/images/digital_artwork.jpg"), + ); + + // Save all listings to database and get their assigned IDs and updated models + let (fixed_price_id, db_fixed_price) = db.collection().expect("can open listing collection").set(&fixed_price_listing).expect("can set listing"); + let (auction_id, db_auction) = db.collection().expect("can open listing collection").set(&auction_listing).expect("can set listing"); + let (exchange_id, db_exchange) = db.collection().expect("can open listing collection").set(&exchange_listing).expect("can set listing"); + + println!("Fixed Price Listing assigned ID: {}", fixed_price_id); + println!("Auction Listing assigned ID: {}", auction_id); + println!("Exchange Listing assigned ID: {}", exchange_id); + + // Print all listings retrieved from database + println!("\n--- Listings Retrieved from Database ---"); + println!("\n1. Fixed Price Listing:"); + print_listing_details(&db_fixed_price); + + println!("\n2. Auction Listing:"); + print_listing_details(&db_auction); + + println!("\n3. Exchange Listing:"); + print_listing_details(&db_exchange); + + // Demonstrate working with bids on an auction listing + println!("\n--- Working with Bids ---"); + + // Create bids for the auction listing + let bid1 = Bid::new( + auction_id, + 101, // Bidder ID + 5200.0, + "USD", + ); + + let bid2 = Bid::new( + auction_id, + 102, // Bidder ID + 5500.0, + "USD", + ); + + // Print the bids + println!("\n1. First Bid:"); + print_bid_details(&bid1); + + println!("\n2. Second Bid:"); + print_bid_details(&bid2); + + // Add bids to the auction listing + let updated_auction = db_auction + .add_bid(bid1.clone()) + .expect("can add first bid") + .add_bid(bid2.clone()) + .expect("can add second bid"); + + // Save the updated auction listing + let (_, db_updated_auction) = db.collection() + .expect("can open listing collection") + .set(&updated_auction) + .expect("can set updated auction"); + + println!("\n3. Auction Listing After Adding Bids:"); + print_listing_details(&db_updated_auction); + + // Demonstrate retrieving the highest bid + if let Some(highest_bid) = db_updated_auction.highest_bid() { + println!("\n4. Highest Bid:"); + print_bid_details(highest_bid); + } + + // Demonstrate completing a sale for the fixed price listing + println!("\n--- Completing a Sale ---"); + + // Complete the fixed price listing sale + let completed_fixed_price = db_fixed_price + .complete_sale("buyer123", 1200.0) + .expect("can complete sale"); + + // Save the updated listing + let (_, db_completed_fixed_price) = db.collection() + .expect("can open listing collection") + .set(&completed_fixed_price) + .expect("can set completed listing"); + + println!("\n1. Fixed Price Listing After Sale:"); + print_listing_details(&db_completed_fixed_price); + + // Demonstrate completing an auction + println!("\n--- Completing an Auction ---"); + + // Complete the auction with the highest bidder + // Store the bidder_id and amount before moving db_updated_auction + let bidder_id = db_updated_auction.highest_bid().unwrap().bidder_id; + let amount = db_updated_auction.highest_bid().unwrap().amount; + + // Now complete the sale + let completed_auction = db_updated_auction + .complete_sale(bidder_id.to_string(), amount) + .expect("can complete auction"); + + // Save the updated auction listing + let (_, db_completed_auction) = db.collection() + .expect("can open listing collection") + .set(&completed_auction) + .expect("can set completed auction"); + + println!("\n1. Auction Listing After Completion:"); + print_listing_details(&db_completed_auction); + + // Demonstrate cancelling a listing + println!("\n--- Cancelling a Listing ---"); + + // Cancel the exchange listing + let cancelled_exchange = db_exchange + .cancel() + .expect("can cancel listing"); + + // Save the updated listing + let (_, db_cancelled_exchange) = db.collection() + .expect("can open listing collection") + .set(&cancelled_exchange) + .expect("can set cancelled listing"); + + println!("\n1. Exchange Listing After Cancellation:"); + print_listing_details(&db_cancelled_exchange); + + // Demonstrate checking for expired listings + println!("\n--- Checking for Expired Listings ---"); + + // Create a listing that's already expired + let expired_listing = Listing::new( + None, // Auto-generated ID + "Already Expired Item", + "This item's listing has already expired", + "asset202", + AssetType::Erc721, // NFT representing a physical item + "seller456", + 50.0, + "USD", + ListingType::FixedPrice, + Some(Utc::now() - Duration::days(1)), // Expired 1 day ago + vec!["expired".to_string()], + None::, + ); + + // Save the expired listing + let (expired_id, db_expired) = db.collection() + .expect("can open listing collection") + .set(&expired_listing) + .expect("can set expired listing"); + + println!("Expired Listing assigned ID: {}", expired_id); + + // Check expiration + let checked_expired = db_expired.check_expiration(); + + // Save the checked listing + let (_, db_checked_expired) = db.collection() + .expect("can open listing collection") + .set(&checked_expired) + .expect("can set checked listing"); + + println!("\n1. Listing After Expiration Check:"); + print_listing_details(&db_checked_expired); + + // Demonstrate updating listing details + println!("\n--- Updating Listing Details ---"); + + // Create a new listing to update + let listing_to_update = Listing::new( + None, // Auto-generated ID + "Original Title", + "Original description", + "asset303", + AssetType::Erc20, // Token for a digital asset + "seller456", + 75.0, + "USD", + ListingType::FixedPrice, + Some(Utc::now() + Duration::days(30)), + vec!["original".to_string()], + None::, + ); + + // Save the listing + let (update_id, db_to_update) = db.collection() + .expect("can open listing collection") + .set(&listing_to_update) + .expect("can set listing to update"); + + println!("Listing to Update assigned ID: {}", update_id); + println!("\n1. Original Listing:"); + print_listing_details(&db_to_update); + + // Update the listing details + let updated_listing = db_to_update + .update_details( + Some("Updated Title"), + Some("Updated description with more details"), + Some(85.0), + Some("https://example.com/images/updated_image.jpg"), + ) + .add_tags(vec!["updated".to_string(), "premium".to_string()]); + + // Save the updated listing + let (_, db_updated_listing) = db.collection() + .expect("can open listing collection") + .set(&updated_listing) + .expect("can set updated listing"); + + println!("\n2. Listing After Update:"); + print_listing_details(&db_updated_listing); + + println!("\n--- Model Information ---"); + println!("Listing DB Prefix: {}", Listing::db_prefix()); +}