implement more models and rhai examples
This commit is contained in:
		
							
								
								
									
										109
									
								
								heromodels/examples/finance_rhai/example.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								heromodels/examples/finance_rhai/example.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
			
		||||
use rhai::{Engine, Scope, EvalAltResult};
 | 
			
		||||
use std::sync::{Arc, Mutex};
 | 
			
		||||
use std::collections::HashMap;
 | 
			
		||||
use std::fs;
 | 
			
		||||
 | 
			
		||||
// Import the models and the registration function
 | 
			
		||||
use heromodels::models::finance::account::Account;
 | 
			
		||||
use heromodels::models::finance::asset::{Asset};
 | 
			
		||||
use heromodels::models::finance::marketplace::{Listing}; 
 | 
			
		||||
use heromodels::models::finance::rhai::register_rhai_engine_functions;
 | 
			
		||||
 | 
			
		||||
// Define a simple in-memory mock database for the example
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct MockDb {
 | 
			
		||||
    pub accounts: Arc<Mutex<HashMap<u32, Account>>>,
 | 
			
		||||
    pub assets: Arc<Mutex<HashMap<u32, Asset>>>,
 | 
			
		||||
    pub listings: Arc<Mutex<HashMap<u32, Listing>>>,
 | 
			
		||||
    // Bids are often part of Listings, so a separate HashMap for Bids might not be needed
 | 
			
		||||
    // unless we want to query bids globally by a unique bid ID.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl MockDb {
 | 
			
		||||
    fn new() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            accounts: Arc::new(Mutex::new(HashMap::new())),
 | 
			
		||||
            assets: Arc::new(Mutex::new(HashMap::new())),
 | 
			
		||||
            listings: Arc::new(Mutex::new(HashMap::new())),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() -> Result<(), Box<EvalAltResult>> {
 | 
			
		||||
    println!("--- Finance Rhai Example ---");
 | 
			
		||||
 | 
			
		||||
    let mut engine = Engine::new();
 | 
			
		||||
    let mut scope = Scope::new();
 | 
			
		||||
 | 
			
		||||
    let mock_db = Arc::new(MockDb::new());
 | 
			
		||||
 | 
			
		||||
    // Register finance functions and types with the engine
 | 
			
		||||
    register_rhai_engine_functions(
 | 
			
		||||
        &mut engine, 
 | 
			
		||||
        Arc::clone(&mock_db.accounts),
 | 
			
		||||
        Arc::clone(&mock_db.assets),
 | 
			
		||||
        Arc::clone(&mock_db.listings) 
 | 
			
		||||
    );
 | 
			
		||||
    println!("Rhai functions registered.");
 | 
			
		||||
 | 
			
		||||
    scope.push("db_instance", mock_db.clone());
 | 
			
		||||
 | 
			
		||||
    let script_path = "examples/finance_rhai/finance.rhai";
 | 
			
		||||
    println!("Loading script: {}", script_path);
 | 
			
		||||
    let script = match fs::read_to_string(script_path) {
 | 
			
		||||
        Ok(s) => s,
 | 
			
		||||
        Err(e) => {
 | 
			
		||||
            eprintln!("Error reading script file '{}': {}", script_path, e);
 | 
			
		||||
            return Err(Box::new(EvalAltResult::ErrorSystem(
 | 
			
		||||
                "Failed to read script".to_string(),
 | 
			
		||||
                Box::new(e),
 | 
			
		||||
            )));
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    println!("Executing script...");
 | 
			
		||||
    match engine.run_with_scope(&mut scope, &script) {
 | 
			
		||||
        Ok(_) => println!("Script executed successfully!"),
 | 
			
		||||
        Err(e) => {
 | 
			
		||||
            eprintln!("Script execution failed: {:?}", e);
 | 
			
		||||
            return Err(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Print final state of Accounts
 | 
			
		||||
    let final_accounts = mock_db.accounts.lock().unwrap();
 | 
			
		||||
    println!("\n--- Final Mock DB State (Accounts) ---");
 | 
			
		||||
    if final_accounts.is_empty() {
 | 
			
		||||
        println!("No accounts in mock DB.");
 | 
			
		||||
    }
 | 
			
		||||
    for (id, account) in final_accounts.iter() {
 | 
			
		||||
        println!("Account ID: {}, Name: '{}', User ID: {}, Assets: {}", 
 | 
			
		||||
                 id, account.name, account.user_id, account.assets.len());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Print final state of Assets
 | 
			
		||||
    let final_assets = mock_db.assets.lock().unwrap();
 | 
			
		||||
    println!("\n--- Final Mock DB State (Assets) ---");
 | 
			
		||||
    if final_assets.is_empty() {
 | 
			
		||||
        println!("No assets in mock DB.");
 | 
			
		||||
    }
 | 
			
		||||
    for (id, asset) in final_assets.iter() {
 | 
			
		||||
        println!("Asset ID: {}, Name: '{}', Amount: {}, Type: {:?}", 
 | 
			
		||||
                 id, asset.name, asset.amount, asset.asset_type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Print final state of Listings
 | 
			
		||||
    let final_listings = mock_db.listings.lock().unwrap();
 | 
			
		||||
    println!("\n--- Final Mock DB State (Listings) ---");
 | 
			
		||||
    if final_listings.is_empty() {
 | 
			
		||||
        println!("No listings in mock DB.");
 | 
			
		||||
    }
 | 
			
		||||
    for (id, listing) in final_listings.iter() {
 | 
			
		||||
        println!(
 | 
			
		||||
            "Listing ID: {}, Title: '{}', Type: {:?}, Status: {:?}, Price: {}, Bids: {}", 
 | 
			
		||||
            id, listing.title, listing.listing_type, listing.status, listing.price, listing.bids.len()
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										142
									
								
								heromodels/examples/finance_rhai/finance.rhai
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								heromodels/examples/finance_rhai/finance.rhai
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,142 @@
 | 
			
		||||
// Finance Rhai Script Example
 | 
			
		||||
 | 
			
		||||
print("--- Starting Finance Rhai Script ---");
 | 
			
		||||
 | 
			
		||||
// 1. Create an Account
 | 
			
		||||
let acc1_id = 101;
 | 
			
		||||
let user1_id = 1;
 | 
			
		||||
let acc1 = new_account(acc1_id, "User1 Main Account", user1_id, "Primary account for User 1", "LedgerX", "0x123MainSt", "pubkeyUser1");
 | 
			
		||||
print(`Created account: ${acc1.name} with ID ${acc1.id}`);
 | 
			
		||||
 | 
			
		||||
// 2. Save Account to Mock DB
 | 
			
		||||
set_account(acc1);
 | 
			
		||||
print(`Account ${acc1.id} saved to DB.`);
 | 
			
		||||
 | 
			
		||||
// 3. Retrieve Account from Mock DB
 | 
			
		||||
let fetched_acc1 = get_account_by_id(acc1_id);
 | 
			
		||||
print(`Fetched account from DB: ${fetched_acc1.name}, User ID: ${fetched_acc1.user_id}`);
 | 
			
		||||
 | 
			
		||||
// 4. Create an Asset
 | 
			
		||||
let asset1_id = 201;
 | 
			
		||||
let asset1 = new_asset(asset1_id, "HeroCoin", "Utility token for Hero Platform", 1000.0, "0xTokenContract", "Erc20", 18);
 | 
			
		||||
print(`Created asset: ${asset1.name} (ID: ${asset1.id}), Amount: ${asset1.amount}, Type: ${asset1.asset_type_str}`);
 | 
			
		||||
 | 
			
		||||
// 5. Save Asset to Mock DB
 | 
			
		||||
set_asset(asset1);
 | 
			
		||||
print(`Asset ${asset1.id} saved to DB.`);
 | 
			
		||||
 | 
			
		||||
// 6. Retrieve Asset from Mock DB
 | 
			
		||||
let fetched_asset1 = get_asset_by_id(asset1_id);
 | 
			
		||||
print(`Fetched asset from DB: ${fetched_asset1.name}, Address: ${fetched_asset1.address}`);
 | 
			
		||||
 | 
			
		||||
// 7. Add Asset to Account (using the fetched instances)
 | 
			
		||||
// Note: Account::add_asset takes Asset by value. We have 'fetched_asset1'.
 | 
			
		||||
// The 'add_asset' method on the Account object in Rhai should work with the asset object.
 | 
			
		||||
// First, let's ensure fetched_acc1 is mutable if 'add_asset' modifies it directly.
 | 
			
		||||
// Or, if add_asset returns a new Account, we'd do: fetched_acc1 = fetched_acc1.add_asset(fetched_asset1);
 | 
			
		||||
// For now, assuming add_asset modifies in place (Rust methods taking `&mut self` often allow this if the object itself is mutable in Rhai scope)
 | 
			
		||||
// If Account.add_asset was registered as `fn(&mut Account, Asset)` then: 
 | 
			
		||||
// fetched_acc1.add_asset(fetched_asset1);
 | 
			
		||||
// Let's assume for now that `add_asset` is available and works. We'll test this.
 | 
			
		||||
// For the current setup, `Account::add_asset` takes `&mut self`, so the object must be mutable in Rhai.
 | 
			
		||||
// We might need to re-fetch or re-set the account if we modify it and want the DB to know.
 | 
			
		||||
// Let's try to add and then re-save the account.
 | 
			
		||||
 | 
			
		||||
// For simplicity in this first script, let's focus on marketplace.
 | 
			
		||||
// Adding asset to account might require more setup in Rhai regarding object mutability
 | 
			
		||||
// or how the add_asset method is exposed. We can refine this later.
 | 
			
		||||
print("Skipping adding asset to account directly in this script version for brevity, focusing on listing.");
 | 
			
		||||
 | 
			
		||||
// 8. Create a Listing for the Asset
 | 
			
		||||
let listing1_id = 301;
 | 
			
		||||
let current_timestamp = timestamp(); // Rhai's built-in for current unix timestamp (seconds)
 | 
			
		||||
let expires_at_ts = current_timestamp + (24 * 60 * 60 * 7); // Expires in 7 days
 | 
			
		||||
 | 
			
		||||
let listing1 = new_listing(
 | 
			
		||||
    listing1_id, 
 | 
			
		||||
    "Rare HeroCoin Batch", 
 | 
			
		||||
    "100 HeroCoins for sale", 
 | 
			
		||||
    asset1_id.to_string(), // asset_id as string
 | 
			
		||||
    "Erc20",               // asset_type as string
 | 
			
		||||
    user1_id.to_string(),  // seller_id as string
 | 
			
		||||
    50.0,                  // price
 | 
			
		||||
    "USD",                 // currency
 | 
			
		||||
    "FixedPrice",          // listing_type as string
 | 
			
		||||
    expires_at_ts,         // expires_at_ts_opt as i64
 | 
			
		||||
    ["token", "herocoin", "sale"], // tags as array of strings
 | 
			
		||||
    ()                   // image_url_opt as string or ()
 | 
			
		||||
);
 | 
			
		||||
print(`Created listing: ${listing1.title} (ID: ${listing1.id}), Price: ${listing1.price} ${listing1.currency}`);
 | 
			
		||||
print(`Listing type: ${listing1.listing_type_str}, Status: ${listing1.status_str}`);
 | 
			
		||||
print(`Listing expires_at_ts_opt: ${listing1.expires_at_ts_opt}`);
 | 
			
		||||
 | 
			
		||||
// 9. Save Listing to Mock DB
 | 
			
		||||
set_listing(listing1);
 | 
			
		||||
print(`Listing ${listing1.id} saved to DB.`);
 | 
			
		||||
 | 
			
		||||
// 10. Retrieve Listing from Mock DB
 | 
			
		||||
let fetched_listing1 = get_listing_by_id(listing1_id);
 | 
			
		||||
print(`Fetched listing from DB: ${fetched_listing1.title}, Seller ID: ${fetched_listing1.seller_id}`);
 | 
			
		||||
print(`Fetched listing asset_id: ${fetched_listing1.asset_id}, asset_type: ${fetched_listing1.asset_type_str}`);
 | 
			
		||||
 | 
			
		||||
// 11. Demonstrate an auction listing (basic structure)
 | 
			
		||||
let listing2_id = 302;
 | 
			
		||||
let auction_listing = new_listing(
 | 
			
		||||
    listing2_id,
 | 
			
		||||
    "Vintage Hero Figurine",
 | 
			
		||||
    "Rare collectible, starting bid low!",
 | 
			
		||||
    "asset_nft_123", // Mock asset ID for an NFT
 | 
			
		||||
    "Erc721",
 | 
			
		||||
    user1_id.to_string(),
 | 
			
		||||
    10.0, // Starting price
 | 
			
		||||
    "USD",
 | 
			
		||||
    "Auction",
 | 
			
		||||
    (), // No expiration for this example
 | 
			
		||||
    ["collectible", "rare", "auction"],
 | 
			
		||||
    "http://example.com/figurine.png"
 | 
			
		||||
);
 | 
			
		||||
set_listing(auction_listing);
 | 
			
		||||
print(`Created auction listing: ${auction_listing.title} (ID: ${auction_listing.id})`);
 | 
			
		||||
 | 
			
		||||
// 12. Create a Bid for the auction listing
 | 
			
		||||
let bid1 = new_bid(auction_listing.id.to_string(), 2, 12.0, "USD"); // User 2 bids 12 USD
 | 
			
		||||
print(`Created bid for listing ${bid1.listing_id} by bidder ${bid1.bidder_id} for ${bid1.amount} ${bid1.currency}`);
 | 
			
		||||
print(`Bid status: ${bid1.status_str}, Created at: ${bid1.created_at_ts}`);
 | 
			
		||||
 | 
			
		||||
// Add bid to listing - this requires the listing object to be mutable
 | 
			
		||||
// and the add_listing_bid function to be correctly registered to modify it.
 | 
			
		||||
// For now, we'll assume the function works and we'd need to re-set the listing to DB if modified.
 | 
			
		||||
// To test `add_listing_bid` properly, we would typically do:
 | 
			
		||||
// let mut mutable_auction_listing = get_listing_by_id(listing2_id);
 | 
			
		||||
// mutable_auction_listing.add_listing_bid(bid1);
 | 
			
		||||
// set_listing(mutable_auction_listing);
 | 
			
		||||
// print(`Bid added to listing ${mutable_auction_listing.id}. New bid count: ${mutable_auction_listing.bids_cloned.len()}`);
 | 
			
		||||
// For this initial script, we will call the function but acknowledge the db update step for a full flow.
 | 
			
		||||
 | 
			
		||||
// Get the listing again to add a bid
 | 
			
		||||
let auction_listing_for_bid = get_listing_by_id(listing2_id);
 | 
			
		||||
print(`Listing '${auction_listing_for_bid.title}' fetched for bidding. Current price: ${auction_listing_for_bid.price}, Bids: ${auction_listing_for_bid.bids_cloned.len()}`);
 | 
			
		||||
 | 
			
		||||
try {
 | 
			
		||||
    auction_listing_for_bid.add_listing_bid(bid1);
 | 
			
		||||
    print(`Bid added to '${auction_listing_for_bid.title}'. New bid count: ${auction_listing_for_bid.bids_cloned.len()}, New price: ${auction_listing_for_bid.price};`);
 | 
			
		||||
    set_listing(auction_listing_for_bid); // Save updated listing to DB
 | 
			
		||||
    print("Auction listing with new bid saved to DB;");
 | 
			
		||||
} catch (err) {
 | 
			
		||||
    print(`Error adding bid: ${err}`);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Try to complete sale for the fixed price listing
 | 
			
		||||
let listing_to_sell = get_listing_by_id(listing1_id);
 | 
			
		||||
let buyer_user_id = 3;
 | 
			
		||||
print(`Attempting to complete sale for listing: ${listing_to_sell.title} by buyer ${buyer_user_id}`);
 | 
			
		||||
try {
 | 
			
		||||
    listing_to_sell.complete_listing_sale(buyer_user_id.to_string(), listing_to_sell.price);
 | 
			
		||||
    print(`Sale completed for listing ${listing_to_sell.id}. New status: ${listing_to_sell.status_str}`);
 | 
			
		||||
    print(`Buyer ID: ${listing_to_sell.buyer_id_opt}, Sale Price: ${listing_to_sell.sale_price_opt}`);
 | 
			
		||||
    set_listing(listing_to_sell); // Save updated listing
 | 
			
		||||
} catch (err) {
 | 
			
		||||
    print(`Error completing sale: ${err}`);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
print("--- Finance Rhai Script Finished ---");
 | 
			
		||||
		Reference in New Issue
	
	Block a user