fmt, fixes and additions
This commit is contained in:
@@ -68,10 +68,26 @@ fn main() {
|
||||
.build();
|
||||
|
||||
// Save all users to database and get their assigned IDs and updated models
|
||||
let (user1_id, db_user1) = db.collection().expect("can open user collection").set(&user1).expect("can set user");
|
||||
let (user2_id, db_user2) = db.collection().expect("can open user collection").set(&user2).expect("can set user");
|
||||
let (user3_id, db_user3) = db.collection().expect("can open user collection").set(&user3).expect("can set user");
|
||||
let (user4_id, db_user4) = db.collection().expect("can open user collection").set(&user4).expect("can set user");
|
||||
let (user1_id, db_user1) = db
|
||||
.collection()
|
||||
.expect("can open user collection")
|
||||
.set(&user1)
|
||||
.expect("can set user");
|
||||
let (user2_id, db_user2) = db
|
||||
.collection()
|
||||
.expect("can open user collection")
|
||||
.set(&user2)
|
||||
.expect("can set user");
|
||||
let (user3_id, db_user3) = db
|
||||
.collection()
|
||||
.expect("can open user collection")
|
||||
.set(&user3)
|
||||
.expect("can set user");
|
||||
let (user4_id, db_user4) = db
|
||||
.collection()
|
||||
.expect("can open user collection")
|
||||
.set(&user4)
|
||||
.expect("can set user");
|
||||
|
||||
println!("User 1 assigned ID: {}", user1_id);
|
||||
println!("User 2 assigned ID: {}", user2_id);
|
||||
@@ -170,7 +186,8 @@ fn main() {
|
||||
.build();
|
||||
|
||||
// Save the comment and get its assigned ID and updated model
|
||||
let (comment_id, db_comment) = db.collection()
|
||||
let (comment_id, db_comment) = db
|
||||
.collection()
|
||||
.expect("can open comment collection")
|
||||
.set(&comment)
|
||||
.expect("can set comment");
|
||||
@@ -186,7 +203,8 @@ fn main() {
|
||||
updated_user.base_data.add_comment(db_comment.get_id());
|
||||
|
||||
// Save the updated user and get the new version
|
||||
let (_, user_with_comment) = db.collection::<User>()
|
||||
let (_, user_with_comment) = db
|
||||
.collection::<User>()
|
||||
.expect("can open user collection")
|
||||
.set(&updated_user)
|
||||
.expect("can set updated user");
|
||||
|
@@ -1,8 +1,8 @@
|
||||
use rhai::{Engine, EvalAltResult, Scope};
|
||||
use std::sync::Arc;
|
||||
use heromodels::db::hero::OurDB; // Corrected path for OurDB
|
||||
use heromodels::models::biz::register_biz_rhai_module; // Corrected path
|
||||
use rhai::{Engine, EvalAltResult, Scope};
|
||||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
println!("Executing Rhai script: examples/biz_rhai/biz.rhai");
|
||||
@@ -20,8 +20,12 @@ fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
|
||||
// Read the Rhai script from file
|
||||
let script_path = "examples/biz_rhai/biz.rhai";
|
||||
let script_content = fs::read_to_string(script_path)
|
||||
.map_err(|e| Box::new(EvalAltResult::ErrorSystem(format!("Cannot read script file: {}", script_path), e.into())))?;
|
||||
let script_content = fs::read_to_string(script_path).map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorSystem(
|
||||
format!("Cannot read script file: {}", script_path),
|
||||
e.into(),
|
||||
))
|
||||
})?;
|
||||
|
||||
// Create a new scope
|
||||
let mut scope = Scope::new();
|
||||
|
@@ -1,6 +1,6 @@
|
||||
use chrono::{Duration, Utc};
|
||||
use heromodels::db::{Collection, Db};
|
||||
use heromodels::models::calendar::{Attendee, AttendanceStatus, Calendar, Event};
|
||||
use heromodels::models::calendar::{AttendanceStatus, Attendee, Calendar, Event};
|
||||
use heromodels_core::Model;
|
||||
|
||||
fn main() {
|
||||
@@ -12,10 +12,8 @@ fn main() {
|
||||
println!("====================================");
|
||||
|
||||
// --- Create Attendees ---
|
||||
let attendee1 = Attendee::new("user_123".to_string())
|
||||
.status(AttendanceStatus::Accepted);
|
||||
let attendee2 = Attendee::new("user_456".to_string())
|
||||
.status(AttendanceStatus::Tentative);
|
||||
let attendee1 = Attendee::new("user_123".to_string()).status(AttendanceStatus::Accepted);
|
||||
let attendee2 = Attendee::new("user_456".to_string()).status(AttendanceStatus::Tentative);
|
||||
let attendee3 = Attendee::new("user_789".to_string()); // Default NoResponse
|
||||
|
||||
// --- Create Events ---
|
||||
@@ -45,7 +43,7 @@ fn main() {
|
||||
"event_gamma".to_string(),
|
||||
"Client Call",
|
||||
now + Duration::days(2),
|
||||
now + Duration::days(2) + Duration::seconds(3600)
|
||||
now + Duration::days(2) + Duration::seconds(3600),
|
||||
);
|
||||
|
||||
// --- Create Calendars ---
|
||||
@@ -58,25 +56,43 @@ fn main() {
|
||||
.add_event(event2.clone());
|
||||
|
||||
// Create a calendar with auto-generated ID (explicit IDs are no longer supported)
|
||||
let calendar2 = Calendar::new(None, "Personal Calendar")
|
||||
.add_event(event3_for_calendar2.clone());
|
||||
|
||||
let calendar2 =
|
||||
Calendar::new(None, "Personal Calendar").add_event(event3_for_calendar2.clone());
|
||||
|
||||
// --- Store Calendars in DB ---
|
||||
let cal_collection = db.collection::<Calendar>().expect("can open calendar collection");
|
||||
let cal_collection = db
|
||||
.collection::<Calendar>()
|
||||
.expect("can open calendar collection");
|
||||
|
||||
let (_, calendar1) = cal_collection.set(&calendar1).expect("can set calendar1");
|
||||
let (_, calendar2) = cal_collection.set(&calendar2).expect("can set calendar2");
|
||||
|
||||
println!("Created calendar1 (ID: {}): Name - '{}'", calendar1.get_id(), calendar1.name);
|
||||
println!("Created calendar2 (ID: {}): Name - '{}'", calendar2.get_id(), calendar2.name);
|
||||
println!(
|
||||
"Created calendar1 (ID: {}): Name - '{}'",
|
||||
calendar1.get_id(),
|
||||
calendar1.name
|
||||
);
|
||||
println!(
|
||||
"Created calendar2 (ID: {}): Name - '{}'",
|
||||
calendar2.get_id(),
|
||||
calendar2.name
|
||||
);
|
||||
|
||||
// --- Retrieve a Calendar by ID ---
|
||||
let stored_calendar1_opt = cal_collection.get_by_id(calendar1.get_id()).expect("can try to load calendar1");
|
||||
assert!(stored_calendar1_opt.is_some(), "Calendar1 should be found in DB");
|
||||
let stored_calendar1_opt = cal_collection
|
||||
.get_by_id(calendar1.get_id())
|
||||
.expect("can try to load calendar1");
|
||||
assert!(
|
||||
stored_calendar1_opt.is_some(),
|
||||
"Calendar1 should be found in DB"
|
||||
);
|
||||
let mut stored_calendar1 = stored_calendar1_opt.unwrap();
|
||||
|
||||
println!("\nRetrieved calendar1 from DB: Name - '{}', Events count: {}", stored_calendar1.name, stored_calendar1.events.len());
|
||||
println!(
|
||||
"\nRetrieved calendar1 from DB: Name - '{}', Events count: {}",
|
||||
stored_calendar1.name,
|
||||
stored_calendar1.events.len()
|
||||
);
|
||||
assert_eq!(stored_calendar1.name, "Work Calendar");
|
||||
assert_eq!(stored_calendar1.events.len(), 2);
|
||||
assert_eq!(stored_calendar1.events[0].title, "Team Meeting");
|
||||
@@ -84,49 +100,83 @@ fn main() {
|
||||
// --- Modify a Calendar (Reschedule an Event) ---
|
||||
let event_id_to_reschedule = event1.id.as_str();
|
||||
let new_start_time = now + Duration::seconds(10800); // 3 hours from now
|
||||
let new_end_time = now + Duration::seconds(14400); // 4 hours from now
|
||||
let new_end_time = now + Duration::seconds(14400); // 4 hours from now
|
||||
|
||||
stored_calendar1 = stored_calendar1.update_event(event_id_to_reschedule, |event_to_update| {
|
||||
println!("Rescheduling event '{}'...", event_to_update.title);
|
||||
event_to_update.reschedule(new_start_time, new_end_time)
|
||||
});
|
||||
|
||||
let rescheduled_event = stored_calendar1.events.iter().find(|e| e.id == event_id_to_reschedule)
|
||||
let rescheduled_event = stored_calendar1
|
||||
.events
|
||||
.iter()
|
||||
.find(|e| e.id == event_id_to_reschedule)
|
||||
.expect("Rescheduled event should exist");
|
||||
assert_eq!(rescheduled_event.start_time, new_start_time);
|
||||
assert_eq!(rescheduled_event.end_time, new_end_time);
|
||||
println!("Event '{}' rescheduled in stored_calendar1.", rescheduled_event.title);
|
||||
println!(
|
||||
"Event '{}' rescheduled in stored_calendar1.",
|
||||
rescheduled_event.title
|
||||
);
|
||||
|
||||
// --- Store the modified calendar ---
|
||||
let (_, mut stored_calendar1) = cal_collection.set(&stored_calendar1).expect("can set modified calendar1");
|
||||
let re_retrieved_calendar1_opt = cal_collection.get_by_id(calendar1.get_id()).expect("can try to load modified calendar1");
|
||||
let (_, mut stored_calendar1) = cal_collection
|
||||
.set(&stored_calendar1)
|
||||
.expect("can set modified calendar1");
|
||||
let re_retrieved_calendar1_opt = cal_collection
|
||||
.get_by_id(calendar1.get_id())
|
||||
.expect("can try to load modified calendar1");
|
||||
let re_retrieved_calendar1 = re_retrieved_calendar1_opt.unwrap();
|
||||
let re_retrieved_event = re_retrieved_calendar1.events.iter().find(|e| e.id == event_id_to_reschedule)
|
||||
let re_retrieved_event = re_retrieved_calendar1
|
||||
.events
|
||||
.iter()
|
||||
.find(|e| e.id == event_id_to_reschedule)
|
||||
.expect("Rescheduled event should exist in re-retrieved calendar");
|
||||
assert_eq!(re_retrieved_event.start_time, new_start_time, "Reschedule not persisted correctly");
|
||||
assert_eq!(
|
||||
re_retrieved_event.start_time, new_start_time,
|
||||
"Reschedule not persisted correctly"
|
||||
);
|
||||
|
||||
println!("\nModified and re-saved calendar1. Rescheduled event start time: {}", re_retrieved_event.start_time);
|
||||
println!(
|
||||
"\nModified and re-saved calendar1. Rescheduled event start time: {}",
|
||||
re_retrieved_event.start_time
|
||||
);
|
||||
|
||||
// --- Add a new event to an existing calendar ---
|
||||
let event4_new = Event::new(
|
||||
"event_delta".to_string(),
|
||||
"1-on-1",
|
||||
now + Duration::days(3),
|
||||
now + Duration::days(3) + Duration::seconds(1800) // 30 minutes
|
||||
now + Duration::days(3) + Duration::seconds(1800), // 30 minutes
|
||||
);
|
||||
stored_calendar1 = stored_calendar1.add_event(event4_new);
|
||||
assert_eq!(stored_calendar1.events.len(), 3);
|
||||
let (_, stored_calendar1) = cal_collection.set(&stored_calendar1).expect("can set calendar1 after adding new event");
|
||||
println!("Added new event '1-on-1' to stored_calendar1. Total events: {}", stored_calendar1.events.len());
|
||||
let (_, stored_calendar1) = cal_collection
|
||||
.set(&stored_calendar1)
|
||||
.expect("can set calendar1 after adding new event");
|
||||
println!(
|
||||
"Added new event '1-on-1' to stored_calendar1. Total events: {}",
|
||||
stored_calendar1.events.len()
|
||||
);
|
||||
|
||||
// --- Delete a Calendar ---
|
||||
cal_collection.delete_by_id(calendar2.get_id()).expect("can delete calendar2");
|
||||
let deleted_calendar2_opt = cal_collection.get_by_id(calendar2.get_id()).expect("can try to load deleted calendar2");
|
||||
assert!(deleted_calendar2_opt.is_none(), "Calendar2 should be deleted from DB");
|
||||
cal_collection
|
||||
.delete_by_id(calendar2.get_id())
|
||||
.expect("can delete calendar2");
|
||||
let deleted_calendar2_opt = cal_collection
|
||||
.get_by_id(calendar2.get_id())
|
||||
.expect("can try to load deleted calendar2");
|
||||
assert!(
|
||||
deleted_calendar2_opt.is_none(),
|
||||
"Calendar2 should be deleted from DB"
|
||||
);
|
||||
|
||||
println!("\nDeleted calendar2 (ID: {}) from DB.", calendar2.get_id());
|
||||
println!("Calendar model DB Prefix: {}", Calendar::db_prefix());
|
||||
|
||||
println!("\nExample finished. DB stored at {}", db_path);
|
||||
println!("To clean up, you can manually delete the directory: {}", db_path);
|
||||
println!(
|
||||
"To clean up, you can manually delete the directory: {}",
|
||||
db_path
|
||||
);
|
||||
}
|
||||
|
@@ -1,18 +1,17 @@
|
||||
use heromodels::db::hero::OurDB;
|
||||
use heromodels::models::calendar::{Attendee, AttendanceStatus, Calendar, Event};
|
||||
use heromodels::models::calendar::rhai::register_rhai_engine_functions;
|
||||
use heromodels::models::calendar::{AttendanceStatus, Attendee, Calendar, Event};
|
||||
use rhai::Engine;
|
||||
use rhai_wrapper::wrap_vec_return;
|
||||
use std::sync::Arc;
|
||||
use std::{fs, path::Path};
|
||||
use rhai_wrapper::wrap_vec_return;
|
||||
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Initialize Rhai engine
|
||||
let mut engine = Engine::new();
|
||||
|
||||
// Initialize database with OurDB
|
||||
let db = Arc::new(OurDB::new("temp_calendar_db", true).expect("Failed to create database"));
|
||||
let db = Arc::new(OurDB::new("temp_calendar_db", true).expect("Failed to create database"));
|
||||
|
||||
// Register the Calendar type with Rhai
|
||||
// This function is generated by the #[rhai_model_export] attribute
|
||||
@@ -29,9 +28,12 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
});
|
||||
|
||||
// Register setter methods for Calendar properties
|
||||
engine.register_fn("set_description", |calendar: &mut Calendar, desc: String| {
|
||||
calendar.description = Some(desc);
|
||||
});
|
||||
engine.register_fn(
|
||||
"set_description",
|
||||
|calendar: &mut Calendar, desc: String| {
|
||||
calendar.description = Some(desc);
|
||||
},
|
||||
);
|
||||
|
||||
// Register getter methods for Calendar properties
|
||||
engine.register_fn("get_description", |calendar: Calendar| -> String {
|
||||
@@ -49,10 +51,13 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Calendar saved: {}", _calendar.name);
|
||||
});
|
||||
|
||||
engine.register_fn("get_calendar_by_id", |_db: Arc<OurDB>, id: i64| -> Calendar {
|
||||
// In a real implementation, this would retrieve the calendar from the database
|
||||
Calendar::new(Some(id as u32), "Retrieved Calendar")
|
||||
});
|
||||
engine.register_fn(
|
||||
"get_calendar_by_id",
|
||||
|_db: Arc<OurDB>, id: i64| -> Calendar {
|
||||
// In a real implementation, this would retrieve the calendar from the database
|
||||
Calendar::new(Some(id as u32), "Retrieved Calendar")
|
||||
},
|
||||
);
|
||||
|
||||
// Register a function to check if a calendar exists
|
||||
engine.register_fn("calendar_exists", |_db: Arc<OurDB>, id: i64| -> bool {
|
||||
@@ -63,11 +68,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Define the function separately to use with the wrap_vec_return macro
|
||||
fn get_all_calendars(_db: Arc<OurDB>) -> Vec<Calendar> {
|
||||
// In a real implementation, this would retrieve all calendars from the database
|
||||
vec![Calendar::new(Some(1), "Calendar 1"), Calendar::new(Some(2), "Calendar 2")]
|
||||
vec![
|
||||
Calendar::new(Some(1), "Calendar 1"),
|
||||
Calendar::new(Some(2), "Calendar 2"),
|
||||
]
|
||||
}
|
||||
|
||||
// Register the function with the wrap_vec_return macro
|
||||
engine.register_fn("get_all_calendars", wrap_vec_return!(get_all_calendars, Arc<OurDB> => Calendar));
|
||||
engine.register_fn(
|
||||
"get_all_calendars",
|
||||
wrap_vec_return!(get_all_calendars, Arc<OurDB> => Calendar),
|
||||
);
|
||||
|
||||
engine.register_fn("delete_calendar_by_id", |_db: Arc<OurDB>, _id: i64| {
|
||||
// In a real implementation, this would delete the calendar from the database
|
||||
@@ -84,4 +95,4 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@@ -41,11 +41,16 @@ fn main() {
|
||||
println!("Before saving - CustomUser DB Keys: {:?}", user.db_keys());
|
||||
|
||||
// Save the model to the database
|
||||
let collection = db.collection::<CustomUser>().expect("can open user collection");
|
||||
let collection = db
|
||||
.collection::<CustomUser>()
|
||||
.expect("can open user collection");
|
||||
let (user_id, saved_user) = collection.set(&user).expect("can save user");
|
||||
|
||||
println!("\nAfter saving - CustomUser ID: {}", saved_user.get_id());
|
||||
println!("After saving - CustomUser DB Keys: {:?}", saved_user.db_keys());
|
||||
println!(
|
||||
"After saving - CustomUser DB Keys: {:?}",
|
||||
saved_user.db_keys()
|
||||
);
|
||||
println!("Returned ID: {}", user_id);
|
||||
|
||||
// Verify that the ID was auto-generated
|
||||
@@ -53,5 +58,8 @@ fn main() {
|
||||
assert_ne!(saved_user.get_id(), 0);
|
||||
|
||||
println!("\nExample finished. DB stored at {}", db_path);
|
||||
println!("To clean up, you can manually delete the directory: {}", db_path);
|
||||
println!(
|
||||
"To clean up, you can manually delete the directory: {}",
|
||||
db_path
|
||||
);
|
||||
}
|
||||
|
@@ -1,8 +1,10 @@
|
||||
// heromodels/examples/finance_example/main.rs
|
||||
|
||||
use chrono::{Utc, Duration};
|
||||
use chrono::{Duration, Utc};
|
||||
use heromodels::models::finance::marketplace::{
|
||||
Bid, BidStatus, Listing, ListingStatus, ListingType,
|
||||
};
|
||||
use heromodels::models::finance::{Account, Asset, AssetType};
|
||||
use heromodels::models::finance::marketplace::{Listing, ListingType, ListingStatus, Bid, BidStatus};
|
||||
|
||||
fn main() {
|
||||
println!("Finance Models Example\n");
|
||||
@@ -12,16 +14,19 @@ fn main() {
|
||||
|
||||
// Create a new account with auto-generated ID
|
||||
let mut account = Account::new(
|
||||
None, // id (auto-generated)
|
||||
"Main ETH Wallet", // name
|
||||
1001, // user_id
|
||||
"My primary Ethereum wallet", // description
|
||||
"ethereum", // ledger
|
||||
None, // id (auto-generated)
|
||||
"Main ETH Wallet", // name
|
||||
1001, // user_id
|
||||
"My primary Ethereum wallet", // description
|
||||
"ethereum", // ledger
|
||||
"0x1234567890abcdef1234567890abcdef12345678", // address
|
||||
"0xpubkey123456789" // pubkey
|
||||
"0xpubkey123456789", // pubkey
|
||||
);
|
||||
|
||||
println!("Created Account: '{}' (ID: {})", account.name, account.base_data.id);
|
||||
println!(
|
||||
"Created Account: '{}' (ID: {})",
|
||||
account.name, account.base_data.id
|
||||
);
|
||||
println!("Owner: User {}", account.user_id);
|
||||
println!("Blockchain: {}", account.ledger);
|
||||
println!("Address: {}", account.address);
|
||||
@@ -30,34 +35,34 @@ fn main() {
|
||||
// Create some assets
|
||||
// Asset with auto-generated ID
|
||||
let eth_asset = Asset::new(
|
||||
None, // id (auto-generated)
|
||||
"Ethereum", // name
|
||||
"Native ETH cryptocurrency", // description
|
||||
1.5, // amount
|
||||
None, // id (auto-generated)
|
||||
"Ethereum", // name
|
||||
"Native ETH cryptocurrency", // description
|
||||
1.5, // amount
|
||||
"0x0000000000000000000000000000000000000000", // address (ETH has no contract address)
|
||||
AssetType::Native, // asset_type
|
||||
18, // decimals
|
||||
AssetType::Native, // asset_type
|
||||
18, // decimals
|
||||
);
|
||||
|
||||
// Assets with explicit IDs
|
||||
let usdc_asset = Asset::new(
|
||||
Some(102), // id
|
||||
"USDC", // name
|
||||
"USD Stablecoin on Ethereum", // description
|
||||
1000.0, // amount
|
||||
Some(102), // id
|
||||
"USDC", // name
|
||||
"USD Stablecoin on Ethereum", // description
|
||||
1000.0, // amount
|
||||
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // address (USDC contract)
|
||||
AssetType::Erc20, // asset_type
|
||||
6, // decimals
|
||||
AssetType::Erc20, // asset_type
|
||||
6, // decimals
|
||||
);
|
||||
|
||||
let nft_asset = Asset::new(
|
||||
Some(103), // id
|
||||
"CryptoPunk #1234", // name
|
||||
"Rare digital collectible", // description
|
||||
1.0, // amount
|
||||
Some(103), // id
|
||||
"CryptoPunk #1234", // name
|
||||
"Rare digital collectible", // description
|
||||
1.0, // amount
|
||||
"0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb", // address (CryptoPunks contract)
|
||||
AssetType::Erc721, // asset_type
|
||||
0, // decimals
|
||||
AssetType::Erc721, // asset_type
|
||||
0, // decimals
|
||||
);
|
||||
|
||||
// Add assets to the account
|
||||
@@ -67,7 +72,12 @@ fn main() {
|
||||
|
||||
println!("Added Assets to Account:");
|
||||
for asset in &account.assets {
|
||||
println!("- {} ({:?}): {} units", asset.name, asset.asset_type, asset.formatted_amount());
|
||||
println!(
|
||||
"- {} ({:?}): {} units",
|
||||
asset.name,
|
||||
asset.asset_type,
|
||||
asset.formatted_amount()
|
||||
);
|
||||
}
|
||||
|
||||
println!("\nTotal Account Value (raw sum): {}", account.total_value());
|
||||
@@ -75,10 +85,10 @@ fn main() {
|
||||
|
||||
// Update account details
|
||||
account = account.update_details(
|
||||
Some("Primary Ethereum Wallet"), // new name
|
||||
None::<String>, // keep same description
|
||||
None::<String>, // keep same address
|
||||
Some("0xnewpubkey987654321"), // new pubkey
|
||||
Some("Primary Ethereum Wallet"), // new name
|
||||
None::<String>, // keep same description
|
||||
None::<String>, // keep same address
|
||||
Some("0xnewpubkey987654321"), // new pubkey
|
||||
);
|
||||
|
||||
println!("Updated Account Details:");
|
||||
@@ -99,23 +109,32 @@ fn main() {
|
||||
|
||||
// Create a fixed price listing with auto-generated ID
|
||||
let mut fixed_price_listing = Listing::new(
|
||||
None, // id (auto-generated)
|
||||
"1000 USDC for Sale", // title
|
||||
"Selling 1000 USDC tokens at fixed price", // description
|
||||
"102", // asset_id (referencing the USDC asset)
|
||||
AssetType::Erc20, // asset_type
|
||||
"1001", // seller_id
|
||||
1.05, // price (in ETH)
|
||||
"ETH", // currency
|
||||
ListingType::FixedPrice, // listing_type
|
||||
None, // id (auto-generated)
|
||||
"1000 USDC for Sale", // title
|
||||
"Selling 1000 USDC tokens at fixed price", // description
|
||||
"102", // asset_id (referencing the USDC asset)
|
||||
AssetType::Erc20, // asset_type
|
||||
"1001", // seller_id
|
||||
1.05, // price (in ETH)
|
||||
"ETH", // currency
|
||||
ListingType::FixedPrice, // listing_type
|
||||
Some(Utc::now() + Duration::days(7)), // expires_at (7 days from now)
|
||||
vec!["token".to_string(), "stablecoin".to_string()], // tags
|
||||
Some("https://example.com/usdc.png"), // image_url
|
||||
);
|
||||
|
||||
println!("Created Fixed Price Listing: '{}' (ID: {})", fixed_price_listing.title, fixed_price_listing.base_data.id);
|
||||
println!("Price: {} {}", fixed_price_listing.price, fixed_price_listing.currency);
|
||||
println!("Type: {:?}, Status: {:?}", fixed_price_listing.listing_type, fixed_price_listing.status);
|
||||
println!(
|
||||
"Created Fixed Price Listing: '{}' (ID: {})",
|
||||
fixed_price_listing.title, fixed_price_listing.base_data.id
|
||||
);
|
||||
println!(
|
||||
"Price: {} {}",
|
||||
fixed_price_listing.price, fixed_price_listing.currency
|
||||
);
|
||||
println!(
|
||||
"Type: {:?}, Status: {:?}",
|
||||
fixed_price_listing.listing_type, fixed_price_listing.status
|
||||
);
|
||||
println!("Expires: {}", fixed_price_listing.expires_at.unwrap());
|
||||
println!("");
|
||||
|
||||
@@ -126,54 +145,71 @@ fn main() {
|
||||
println!("Fixed Price Sale Completed:");
|
||||
println!("Status: {:?}", fixed_price_listing.status);
|
||||
println!("Buyer: {}", fixed_price_listing.buyer_id.unwrap());
|
||||
println!("Sale Price: {} {}", fixed_price_listing.sale_price.unwrap(), fixed_price_listing.currency);
|
||||
println!(
|
||||
"Sale Price: {} {}",
|
||||
fixed_price_listing.sale_price.unwrap(),
|
||||
fixed_price_listing.currency
|
||||
);
|
||||
println!("Sold At: {}", fixed_price_listing.sold_at.unwrap());
|
||||
println!("");
|
||||
},
|
||||
}
|
||||
Err(e) => println!("Error completing sale: {}", e),
|
||||
}
|
||||
|
||||
// Create an auction listing for the NFT with explicit ID
|
||||
let mut auction_listing = Listing::new(
|
||||
Some(202), // id (explicit)
|
||||
"CryptoPunk #1234 Auction", // title
|
||||
"Rare CryptoPunk NFT for auction", // description
|
||||
"103", // asset_id (referencing the NFT asset)
|
||||
AssetType::Erc721, // asset_type
|
||||
"1001", // seller_id
|
||||
10.0, // starting_price (in ETH)
|
||||
"ETH", // currency
|
||||
ListingType::Auction, // listing_type
|
||||
Some(202), // id (explicit)
|
||||
"CryptoPunk #1234 Auction", // title
|
||||
"Rare CryptoPunk NFT for auction", // description
|
||||
"103", // asset_id (referencing the NFT asset)
|
||||
AssetType::Erc721, // asset_type
|
||||
"1001", // seller_id
|
||||
10.0, // starting_price (in ETH)
|
||||
"ETH", // currency
|
||||
ListingType::Auction, // listing_type
|
||||
Some(Utc::now() + Duration::days(3)), // expires_at (3 days from now)
|
||||
vec!["nft".to_string(), "collectible".to_string(), "cryptopunk".to_string()], // tags
|
||||
vec![
|
||||
"nft".to_string(),
|
||||
"collectible".to_string(),
|
||||
"cryptopunk".to_string(),
|
||||
], // tags
|
||||
Some("https://example.com/cryptopunk1234.png"), // image_url
|
||||
);
|
||||
|
||||
println!("Created Auction Listing: '{}' (ID: {})", auction_listing.title, auction_listing.base_data.id);
|
||||
println!("Starting Price: {} {}", auction_listing.price, auction_listing.currency);
|
||||
println!("Type: {:?}, Status: {:?}", auction_listing.listing_type, auction_listing.status);
|
||||
println!(
|
||||
"Created Auction Listing: '{}' (ID: {})",
|
||||
auction_listing.title, auction_listing.base_data.id
|
||||
);
|
||||
println!(
|
||||
"Starting Price: {} {}",
|
||||
auction_listing.price, auction_listing.currency
|
||||
);
|
||||
println!(
|
||||
"Type: {:?}, Status: {:?}",
|
||||
auction_listing.listing_type, auction_listing.status
|
||||
);
|
||||
println!("");
|
||||
|
||||
// Create some bids
|
||||
let bid1 = Bid::new(
|
||||
auction_listing.base_data.id.to_string(), // listing_id
|
||||
2001, // bidder_id
|
||||
11.0, // amount
|
||||
"ETH", // currency
|
||||
2001, // bidder_id
|
||||
11.0, // amount
|
||||
"ETH", // currency
|
||||
);
|
||||
|
||||
let bid2 = Bid::new(
|
||||
auction_listing.base_data.id.to_string(), // listing_id
|
||||
2002, // bidder_id
|
||||
12.5, // amount
|
||||
"ETH", // currency
|
||||
2002, // bidder_id
|
||||
12.5, // amount
|
||||
"ETH", // currency
|
||||
);
|
||||
|
||||
let bid3 = Bid::new(
|
||||
auction_listing.base_data.id.to_string(), // listing_id
|
||||
2003, // bidder_id
|
||||
15.0, // amount
|
||||
"ETH", // currency
|
||||
2003, // bidder_id
|
||||
15.0, // amount
|
||||
"ETH", // currency
|
||||
);
|
||||
|
||||
// Add bids to the auction
|
||||
@@ -184,7 +220,7 @@ fn main() {
|
||||
Ok(updated_listing) => {
|
||||
auction_listing = updated_listing;
|
||||
println!("- Bid added: 11.0 ETH from User 2001");
|
||||
},
|
||||
}
|
||||
Err(e) => println!("Error adding bid: {}", e),
|
||||
}
|
||||
|
||||
@@ -192,7 +228,7 @@ fn main() {
|
||||
Ok(updated_listing) => {
|
||||
auction_listing = updated_listing;
|
||||
println!("- Bid added: 12.5 ETH from User 2002");
|
||||
},
|
||||
}
|
||||
Err(e) => println!("Error adding bid: {}", e),
|
||||
}
|
||||
|
||||
@@ -200,18 +236,21 @@ fn main() {
|
||||
Ok(updated_listing) => {
|
||||
auction_listing = updated_listing;
|
||||
println!("- Bid added: 15.0 ETH from User 2003");
|
||||
},
|
||||
}
|
||||
Err(e) => println!("Error adding bid: {}", e),
|
||||
}
|
||||
|
||||
println!("\nCurrent Auction Status:");
|
||||
println!("Current Price: {} {}", auction_listing.price, auction_listing.currency);
|
||||
println!(
|
||||
"Current Price: {} {}",
|
||||
auction_listing.price, auction_listing.currency
|
||||
);
|
||||
|
||||
if let Some(highest_bid) = auction_listing.highest_bid() {
|
||||
println!("Highest Bid: {} {} from User {}",
|
||||
highest_bid.amount,
|
||||
highest_bid.currency,
|
||||
highest_bid.bidder_id);
|
||||
println!(
|
||||
"Highest Bid: {} {} from User {}",
|
||||
highest_bid.amount, highest_bid.currency, highest_bid.bidder_id
|
||||
);
|
||||
}
|
||||
|
||||
println!("Total Bids: {}", auction_listing.bids.len());
|
||||
@@ -223,42 +262,57 @@ fn main() {
|
||||
auction_listing = updated_listing;
|
||||
println!("Auction Completed:");
|
||||
println!("Status: {:?}", auction_listing.status);
|
||||
println!("Winner: User {}", auction_listing.buyer_id.as_ref().unwrap());
|
||||
println!("Winning Bid: {} {}", auction_listing.sale_price.as_ref().unwrap(), auction_listing.currency);
|
||||
println!(
|
||||
"Winner: User {}",
|
||||
auction_listing.buyer_id.as_ref().unwrap()
|
||||
);
|
||||
println!(
|
||||
"Winning Bid: {} {}",
|
||||
auction_listing.sale_price.as_ref().unwrap(),
|
||||
auction_listing.currency
|
||||
);
|
||||
println!("");
|
||||
|
||||
println!("Final Bid Statuses:");
|
||||
for bid in &auction_listing.bids {
|
||||
println!("- User {}: {} {} (Status: {:?})",
|
||||
bid.bidder_id,
|
||||
bid.amount,
|
||||
bid.currency,
|
||||
bid.status);
|
||||
println!(
|
||||
"- User {}: {} {} (Status: {:?})",
|
||||
bid.bidder_id, bid.amount, bid.currency, bid.status
|
||||
);
|
||||
}
|
||||
println!("");
|
||||
},
|
||||
}
|
||||
Err(e) => println!("Error completing auction: {}", e),
|
||||
}
|
||||
|
||||
// Create an exchange listing with auto-generated ID
|
||||
let exchange_listing = Listing::new(
|
||||
None, // id (auto-generated)
|
||||
"ETH for BTC Exchange", // title
|
||||
"Looking to exchange ETH for BTC", // description
|
||||
"101", // asset_id (referencing the ETH asset)
|
||||
AssetType::Native, // asset_type
|
||||
"1001", // seller_id
|
||||
1.0, // amount (1 ETH)
|
||||
"BTC", // currency (what they want in exchange)
|
||||
ListingType::Exchange, // listing_type
|
||||
Some(Utc::now() + Duration::days(14)), // expires_at (14 days from now)
|
||||
None, // id (auto-generated)
|
||||
"ETH for BTC Exchange", // title
|
||||
"Looking to exchange ETH for BTC", // description
|
||||
"101", // asset_id (referencing the ETH asset)
|
||||
AssetType::Native, // asset_type
|
||||
"1001", // seller_id
|
||||
1.0, // amount (1 ETH)
|
||||
"BTC", // currency (what they want in exchange)
|
||||
ListingType::Exchange, // listing_type
|
||||
Some(Utc::now() + Duration::days(14)), // expires_at (14 days from now)
|
||||
vec!["exchange".to_string(), "crypto".to_string()], // tags
|
||||
None::<String>, // image_url
|
||||
None::<String>, // image_url
|
||||
);
|
||||
|
||||
println!("Created Exchange Listing: '{}' (ID: {})", exchange_listing.title, exchange_listing.base_data.id);
|
||||
println!("Offering: Asset {} ({:?})", exchange_listing.asset_id, exchange_listing.asset_type);
|
||||
println!("Wanted: {} {}", exchange_listing.price, exchange_listing.currency);
|
||||
println!(
|
||||
"Created Exchange Listing: '{}' (ID: {})",
|
||||
exchange_listing.title, exchange_listing.base_data.id
|
||||
);
|
||||
println!(
|
||||
"Offering: Asset {} ({:?})",
|
||||
exchange_listing.asset_id, exchange_listing.asset_type
|
||||
);
|
||||
println!(
|
||||
"Wanted: {} {}",
|
||||
exchange_listing.price, exchange_listing.currency
|
||||
);
|
||||
println!("");
|
||||
|
||||
// --- PART 3: DEMONSTRATING EDGE CASES ---
|
||||
@@ -266,26 +320,26 @@ fn main() {
|
||||
|
||||
// Create a new auction listing for edge case testing with explicit ID
|
||||
let test_auction = Listing::new(
|
||||
Some(205), // id (explicit)
|
||||
"Test Auction", // title
|
||||
"For testing edge cases", // description
|
||||
"101", // asset_id
|
||||
AssetType::Native, // asset_type
|
||||
"1001", // seller_id
|
||||
10.0, // starting_price
|
||||
"ETH", // currency
|
||||
ListingType::Auction, // listing_type
|
||||
Some(205), // id (explicit)
|
||||
"Test Auction", // title
|
||||
"For testing edge cases", // description
|
||||
"101", // asset_id
|
||||
AssetType::Native, // asset_type
|
||||
"1001", // seller_id
|
||||
10.0, // starting_price
|
||||
"ETH", // currency
|
||||
ListingType::Auction, // listing_type
|
||||
Some(Utc::now() + Duration::days(1)), // expires_at
|
||||
vec![], // tags
|
||||
None::<String>, // image_url
|
||||
vec![], // tags
|
||||
None::<String>, // image_url
|
||||
);
|
||||
|
||||
// Try to add a bid that's too low
|
||||
let low_bid = Bid::new(
|
||||
test_auction.base_data.id.to_string(), // listing_id
|
||||
2004, // bidder_id
|
||||
5.0, // amount (lower than starting price)
|
||||
"ETH", // currency
|
||||
2004, // bidder_id
|
||||
5.0, // amount (lower than starting price)
|
||||
"ETH", // currency
|
||||
);
|
||||
|
||||
println!("Attempting to add a bid that's too low (5.0 ETH):");
|
||||
@@ -305,21 +359,24 @@ fn main() {
|
||||
|
||||
// Create a listing that will expire with auto-generated ID
|
||||
let mut expiring_listing = Listing::new(
|
||||
None, // id (auto-generated)
|
||||
"About to Expire", // title
|
||||
None, // id (auto-generated)
|
||||
"About to Expire", // title
|
||||
"This listing will expire immediately", // description
|
||||
"101", // asset_id
|
||||
AssetType::Native, // asset_type
|
||||
"1001", // seller_id
|
||||
0.1, // price
|
||||
"ETH", // currency
|
||||
ListingType::FixedPrice, // listing_type
|
||||
Some(Utc::now() - Duration::hours(1)), // expires_at (1 hour ago)
|
||||
vec![], // tags
|
||||
None::<String>, // image_url
|
||||
"101", // asset_id
|
||||
AssetType::Native, // asset_type
|
||||
"1001", // seller_id
|
||||
0.1, // price
|
||||
"ETH", // currency
|
||||
ListingType::FixedPrice, // listing_type
|
||||
Some(Utc::now() - Duration::hours(1)), // expires_at (1 hour ago)
|
||||
vec![], // tags
|
||||
None::<String>, // image_url
|
||||
);
|
||||
|
||||
println!("Created Expiring Listing: '{}' (ID: {})", expiring_listing.title, expiring_listing.base_data.id);
|
||||
println!(
|
||||
"Created Expiring Listing: '{}' (ID: {})",
|
||||
expiring_listing.title, expiring_listing.base_data.id
|
||||
);
|
||||
println!("Initial Status: {:?}", expiring_listing.status);
|
||||
|
||||
// Check expiration
|
||||
|
@@ -1,12 +1,12 @@
|
||||
use rhai::{Engine, Scope, EvalAltResult};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use rhai::{Engine, EvalAltResult, Scope};
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
// 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::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
|
||||
@@ -39,10 +39,10 @@ fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
|
||||
// Register finance functions and types with the engine
|
||||
register_rhai_engine_functions(
|
||||
&mut engine,
|
||||
&mut engine,
|
||||
Arc::clone(&mock_db.accounts),
|
||||
Arc::clone(&mock_db.assets),
|
||||
Arc::clone(&mock_db.listings)
|
||||
Arc::clone(&mock_db.listings),
|
||||
);
|
||||
println!("Rhai functions registered.");
|
||||
|
||||
@@ -77,8 +77,13 @@ fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
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());
|
||||
println!(
|
||||
"Account ID: {}, Name: '{}', User ID: {}, Assets: {}",
|
||||
id,
|
||||
account.name,
|
||||
account.user_id,
|
||||
account.assets.len()
|
||||
);
|
||||
}
|
||||
|
||||
// Print final state of Assets
|
||||
@@ -88,8 +93,10 @@ fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
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);
|
||||
println!(
|
||||
"Asset ID: {}, Name: '{}', Amount: {}, Type: {:?}",
|
||||
id, asset.name, asset.amount, asset.asset_type
|
||||
);
|
||||
}
|
||||
|
||||
// Print final state of Listings
|
||||
@@ -100,8 +107,13 @@ fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
}
|
||||
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()
|
||||
"Listing ID: {}, Title: '{}', Type: {:?}, Status: {:?}, Price: {}, Bids: {}",
|
||||
id,
|
||||
listing.title,
|
||||
listing.listing_type,
|
||||
listing.status,
|
||||
listing.price,
|
||||
listing.bids.len()
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -9,8 +9,8 @@ use heromodels_core::Model;
|
||||
|
||||
fn main() {
|
||||
// Create a new DB instance in /tmp/ourdb_flowbroker, and reset before every run
|
||||
let db = heromodels::db::hero::OurDB::new("/tmp/ourdb_flowbroker", true)
|
||||
.expect("Can create DB");
|
||||
let db =
|
||||
heromodels::db::hero::OurDB::new("/tmp/ourdb_flowbroker", true).expect("Can create DB");
|
||||
|
||||
println!("Hero Models - Flow Example");
|
||||
println!("===========================");
|
||||
@@ -20,56 +20,71 @@ fn main() {
|
||||
let new_flow_uuid = "a1b2c3d4-e5f6-7890-1234-567890abcdef"; // Example UUID
|
||||
|
||||
let flow1 = Flow::new(
|
||||
1, // id
|
||||
new_flow_uuid, // flow_uuid
|
||||
"Document Approval Flow", // name
|
||||
"Pending", // status
|
||||
1, // id
|
||||
new_flow_uuid, // flow_uuid
|
||||
"Document Approval Flow", // name
|
||||
"Pending", // status
|
||||
);
|
||||
db.collection().expect("can open flow collection").set(&flow1).expect("can set flow1");
|
||||
db.collection()
|
||||
.expect("can open flow collection")
|
||||
.set(&flow1)
|
||||
.expect("can set flow1");
|
||||
println!("Created Flow: {:?}", flow1);
|
||||
println!("Flow ID: {}", flow1.get_id());
|
||||
println!("Flow DB Prefix: {}", Flow::db_prefix());
|
||||
|
||||
// --- Create FlowSteps for Flow1 ---
|
||||
let step1_flow1 = FlowStep::new(
|
||||
101, // id
|
||||
flow1.get_id(), // flow_id
|
||||
1, // step_order
|
||||
"Pending", // status
|
||||
101, // id
|
||||
flow1.get_id(), // flow_id
|
||||
1, // step_order
|
||||
"Pending", // status
|
||||
)
|
||||
.description("Initial review by manager");
|
||||
db.collection().expect("can open flow_step collection").set(&step1_flow1).expect("can set step1_flow1");
|
||||
db.collection()
|
||||
.expect("can open flow_step collection")
|
||||
.set(&step1_flow1)
|
||||
.expect("can set step1_flow1");
|
||||
println!("Created FlowStep: {:?}", step1_flow1);
|
||||
|
||||
let step2_flow1 = FlowStep::new(
|
||||
102, // id
|
||||
flow1.get_id(), // flow_id
|
||||
2, // step_order
|
||||
"Pending", // status
|
||||
102, // id
|
||||
flow1.get_id(), // flow_id
|
||||
2, // step_order
|
||||
"Pending", // status
|
||||
)
|
||||
.description("Legal team sign-off");
|
||||
db.collection().expect("can open flow_step collection").set(&step2_flow1).expect("can set step2_flow1");
|
||||
db.collection()
|
||||
.expect("can open flow_step collection")
|
||||
.set(&step2_flow1)
|
||||
.expect("can set step2_flow1");
|
||||
println!("Created FlowStep: {:?}", step2_flow1);
|
||||
|
||||
// --- Create SignatureRequirements for step2_flow1 ---
|
||||
let sig_req1_step2 = SignatureRequirement::new(
|
||||
201, // id
|
||||
step2_flow1.get_id(), // flow_step_id
|
||||
"pubkey_legal_team_lead_hex", // public_key
|
||||
201, // id
|
||||
step2_flow1.get_id(), // flow_step_id
|
||||
"pubkey_legal_team_lead_hex", // public_key
|
||||
"I approve this document for legal compliance.", // message
|
||||
"Pending", // status
|
||||
"Pending", // status
|
||||
);
|
||||
db.collection().expect("can open sig_req collection").set(&sig_req1_step2).expect("can set sig_req1_step2");
|
||||
db.collection()
|
||||
.expect("can open sig_req collection")
|
||||
.set(&sig_req1_step2)
|
||||
.expect("can set sig_req1_step2");
|
||||
println!("Created SignatureRequirement: {:?}", sig_req1_step2);
|
||||
|
||||
let sig_req2_step2 = SignatureRequirement::new(
|
||||
202, // id
|
||||
step2_flow1.get_id(), // flow_step_id
|
||||
"pubkey_general_counsel_hex", // public_key
|
||||
202, // id
|
||||
step2_flow1.get_id(), // flow_step_id
|
||||
"pubkey_general_counsel_hex", // public_key
|
||||
"I, as General Counsel, approve this document.", // message
|
||||
"Pending", // status
|
||||
"Pending", // status
|
||||
);
|
||||
db.collection().expect("can open sig_req collection").set(&sig_req2_step2).expect("can set sig_req2_step2");
|
||||
db.collection()
|
||||
.expect("can open sig_req collection")
|
||||
.set(&sig_req2_step2)
|
||||
.expect("can set sig_req2_step2");
|
||||
println!("Created SignatureRequirement: {:?}", sig_req2_step2);
|
||||
|
||||
// --- Retrieve and Verify ---
|
||||
@@ -101,9 +116,18 @@ fn main() {
|
||||
.get::<flow_step_flow_id_idx, _>(&retrieved_flow.get_id())
|
||||
.expect("can load steps for flow1");
|
||||
assert_eq!(steps_for_flow1.len(), 2);
|
||||
println!("Retrieved {} FlowSteps for Flow ID {}:", steps_for_flow1.len(), retrieved_flow.get_id());
|
||||
println!(
|
||||
"Retrieved {} FlowSteps for Flow ID {}:",
|
||||
steps_for_flow1.len(),
|
||||
retrieved_flow.get_id()
|
||||
);
|
||||
for step in &steps_for_flow1 {
|
||||
println!(" - Step ID: {}, Order: {}, Desc: {:?}", step.get_id(), step.step_order, step.description);
|
||||
println!(
|
||||
" - Step ID: {}, Order: {}, Desc: {:?}",
|
||||
step.get_id(),
|
||||
step.step_order,
|
||||
step.description
|
||||
);
|
||||
}
|
||||
|
||||
// --- Update a SignatureRequirement (simulate signing) ---
|
||||
@@ -114,12 +138,18 @@ fn main() {
|
||||
.expect("can load sig_req1")
|
||||
.unwrap();
|
||||
|
||||
println!("\nUpdating SignatureRequirement ID: {}", retrieved_sig_req1.get_id());
|
||||
println!(
|
||||
"\nUpdating SignatureRequirement ID: {}",
|
||||
retrieved_sig_req1.get_id()
|
||||
);
|
||||
retrieved_sig_req1.status = "Signed".to_string();
|
||||
retrieved_sig_req1.signed_by = Some("pubkey_legal_team_lead_hex_actual_signer".to_string());
|
||||
retrieved_sig_req1.signature = Some("mock_signature_base64_encoded".to_string());
|
||||
|
||||
db.collection().expect("can open sig_req collection").set(&retrieved_sig_req1).expect("can update sig_req1");
|
||||
db.collection()
|
||||
.expect("can open sig_req collection")
|
||||
.set(&retrieved_sig_req1)
|
||||
.expect("can update sig_req1");
|
||||
|
||||
let updated_sig_req1 = db
|
||||
.collection::<SignatureRequirement>()
|
||||
@@ -129,10 +159,13 @@ fn main() {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(updated_sig_req1.status, "Signed");
|
||||
assert_eq!(updated_sig_req1.signature.as_deref(), Some("mock_signature_base64_encoded"));
|
||||
assert_eq!(
|
||||
updated_sig_req1.signature.as_deref(),
|
||||
Some("mock_signature_base64_encoded")
|
||||
);
|
||||
println!("Updated SignatureRequirement: {:?}", updated_sig_req1);
|
||||
|
||||
// --- Delete a FlowStep ---
|
||||
// --- Delete a FlowStep ---
|
||||
// (In a real app, you might also want to delete associated SignatureRequirements first, or handle via DB constraints/cascade if supported)
|
||||
let step1_id_to_delete = step1_flow1.get_id();
|
||||
db.collection::<FlowStep>()
|
||||
@@ -157,7 +190,11 @@ fn main() {
|
||||
.expect("can load remaining steps for flow1");
|
||||
assert_eq!(remaining_steps_for_flow1.len(), 1);
|
||||
assert_eq!(remaining_steps_for_flow1[0].get_id(), step2_flow1.get_id());
|
||||
println!("Remaining FlowSteps for Flow ID {}: count = {}", retrieved_flow.get_id(), remaining_steps_for_flow1.len());
|
||||
println!(
|
||||
"Remaining FlowSteps for Flow ID {}: count = {}",
|
||||
retrieved_flow.get_id(),
|
||||
remaining_steps_for_flow1.len()
|
||||
);
|
||||
|
||||
println!("\nFlow example finished successfully!");
|
||||
}
|
||||
|
@@ -20,13 +20,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let script_path = Path::new(script_path_str);
|
||||
if !script_path.exists() {
|
||||
eprintln!("Error: Rhai script not found at {}", script_path_str);
|
||||
eprintln!("Please ensure the script 'flow.rhai' exists in the 'examples/flow_rhai/' directory.");
|
||||
return Err(Box::new(std::io::Error::new(std::io::ErrorKind::NotFound, format!("Rhai script not found: {}", script_path_str))));
|
||||
eprintln!(
|
||||
"Please ensure the script 'flow.rhai' exists in the 'examples/flow_rhai/' directory."
|
||||
);
|
||||
return Err(Box::new(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
format!("Rhai script not found: {}", script_path_str),
|
||||
)));
|
||||
}
|
||||
|
||||
println!("Executing Rhai script: {}", script_path_str);
|
||||
let script = fs::read_to_string(script_path)?;
|
||||
|
||||
|
||||
match engine.eval::<()>(&script) {
|
||||
Ok(_) => println!("\nRhai script executed successfully!"),
|
||||
Err(e) => eprintln!("\nRhai script execution failed: {}\nDetails: {:#?}", e, e),
|
||||
|
@@ -101,23 +101,23 @@ fn main() {
|
||||
|
||||
// Example of voting with comments using the cast_vote_with_comment method
|
||||
println!("Adding votes with comments...");
|
||||
|
||||
|
||||
// User 7 votes for 'Approve Allocation' with a comment
|
||||
proposal = proposal.cast_vote_with_comment(
|
||||
Some(110), // ballot_id
|
||||
7, // user_id
|
||||
1, // chosen_option_id (Approve Allocation)
|
||||
80, // shares
|
||||
"I strongly support this proposal because it aligns with our community values."
|
||||
7, // user_id
|
||||
1, // chosen_option_id (Approve Allocation)
|
||||
80, // shares
|
||||
"I strongly support this proposal because it aligns with our community values.",
|
||||
);
|
||||
|
||||
|
||||
// User 8 votes for 'Reject Allocation' with a comment
|
||||
proposal = proposal.cast_vote_with_comment(
|
||||
Some(111), // ballot_id
|
||||
8, // user_id
|
||||
2, // chosen_option_id (Reject Allocation)
|
||||
60, // shares
|
||||
"I have concerns about the allocation priorities."
|
||||
8, // user_id
|
||||
2, // chosen_option_id (Reject Allocation)
|
||||
60, // shares
|
||||
"I have concerns about the allocation priorities.",
|
||||
);
|
||||
|
||||
println!("\nBallots with Comments:");
|
||||
@@ -218,34 +218,34 @@ fn main() {
|
||||
|
||||
// Example of voting with comments on a private proposal
|
||||
println!("\nAdding votes with comments to private proposal...");
|
||||
|
||||
|
||||
// User 20 (eligible) votes with a comment
|
||||
private_proposal = private_proposal.cast_vote_with_comment(
|
||||
Some(202), // ballot_id
|
||||
20, // user_id (eligible)
|
||||
1, // chosen_option_id
|
||||
75, // shares
|
||||
"I support this restructuring plan with some reservations."
|
||||
Some(202), // ballot_id
|
||||
20, // user_id (eligible)
|
||||
1, // chosen_option_id
|
||||
75, // shares
|
||||
"I support this restructuring plan with some reservations.",
|
||||
);
|
||||
|
||||
|
||||
// User 30 (eligible) votes with a comment
|
||||
private_proposal = private_proposal.cast_vote_with_comment(
|
||||
Some(203), // ballot_id
|
||||
30, // user_id (eligible)
|
||||
2, // chosen_option_id
|
||||
90, // shares
|
||||
"I believe we should reconsider the timing of these changes."
|
||||
Some(203), // ballot_id
|
||||
30, // user_id (eligible)
|
||||
2, // chosen_option_id
|
||||
90, // shares
|
||||
"I believe we should reconsider the timing of these changes.",
|
||||
);
|
||||
|
||||
|
||||
// User 40 (ineligible) tries to vote with a comment
|
||||
private_proposal = private_proposal.cast_vote_with_comment(
|
||||
Some(204), // ballot_id
|
||||
40, // user_id (ineligible)
|
||||
1, // chosen_option_id
|
||||
50, // shares
|
||||
"This restructuring seems unnecessary."
|
||||
Some(204), // ballot_id
|
||||
40, // user_id (ineligible)
|
||||
1, // chosen_option_id
|
||||
50, // shares
|
||||
"This restructuring seems unnecessary.",
|
||||
);
|
||||
|
||||
|
||||
println!("Eligible users 20 and 30 added votes with comments.");
|
||||
println!("Ineligible user 40 attempted to vote with a comment (should be rejected).");
|
||||
|
||||
|
@@ -1,10 +1,12 @@
|
||||
use chrono::{Duration, Utc};
|
||||
use heromodels::db::hero::OurDB;
|
||||
use heromodels::models::governance::{Proposal, ProposalStatus, VoteEventStatus, VoteOption, Ballot};
|
||||
use heromodels::models::governance::{
|
||||
Ballot, Proposal, ProposalStatus, VoteEventStatus, VoteOption,
|
||||
};
|
||||
use rhai::Engine;
|
||||
use rhai_client_macros::rhai;
|
||||
use rhai_wrapper::wrap_vec_return;
|
||||
use std::sync::Arc;
|
||||
use chrono::{Utc, Duration};
|
||||
use rhai_client_macros::rhai;
|
||||
|
||||
// Define the functions we want to expose to Rhai
|
||||
// We'll only use the #[rhai] attribute on functions with simple types
|
||||
@@ -13,7 +15,14 @@ use rhai_client_macros::rhai;
|
||||
fn create_proposal(id: i64, creator_id: String, title: String, description: String) -> Proposal {
|
||||
let start_date = Utc::now();
|
||||
let end_date = start_date + Duration::days(14);
|
||||
Proposal::new(id as u32, creator_id, title, description, start_date, end_date)
|
||||
Proposal::new(
|
||||
id as u32,
|
||||
creator_id,
|
||||
title,
|
||||
description,
|
||||
start_date,
|
||||
end_date,
|
||||
)
|
||||
}
|
||||
|
||||
// Getter functions for Proposal properties
|
||||
@@ -46,7 +55,13 @@ fn add_option_to_proposal(proposal: Proposal, option_id: i64, option_text: Strin
|
||||
proposal.add_option(option_id as u8, option_text)
|
||||
}
|
||||
|
||||
fn cast_vote_on_proposal(proposal: Proposal, ballot_id: i64, user_id: i64, option_id: i64, shares: i64) -> Proposal {
|
||||
fn cast_vote_on_proposal(
|
||||
proposal: Proposal,
|
||||
ballot_id: i64,
|
||||
user_id: i64,
|
||||
option_id: i64,
|
||||
shares: i64,
|
||||
) -> Proposal {
|
||||
proposal.cast_vote(ballot_id as u32, user_id as u32, option_id as u8, shares)
|
||||
}
|
||||
|
||||
@@ -119,14 +134,24 @@ fn get_ballot_shares(ballot: &Ballot) -> i64 {
|
||||
|
||||
// Simple functions that we can use with the #[rhai] attribute
|
||||
#[rhai]
|
||||
fn create_proposal_wrapper(id: i64, creator_id: String, title: String, description: String) -> String {
|
||||
fn create_proposal_wrapper(
|
||||
id: i64,
|
||||
creator_id: String,
|
||||
title: String,
|
||||
description: String,
|
||||
) -> String {
|
||||
let proposal = create_proposal(id, creator_id, title, description);
|
||||
format!("Created proposal with ID: {}", proposal.base_data.id)
|
||||
}
|
||||
|
||||
#[rhai]
|
||||
fn add_option_wrapper(id: i64, option_id: i64, option_text: String) -> String {
|
||||
let proposal = create_proposal(id, "user".to_string(), "title".to_string(), "description".to_string());
|
||||
let proposal = create_proposal(
|
||||
id,
|
||||
"user".to_string(),
|
||||
"title".to_string(),
|
||||
"description".to_string(),
|
||||
);
|
||||
let updated = add_option_to_proposal(proposal, option_id, option_text.clone());
|
||||
format!("Added option '{}' to proposal {}", option_text, id)
|
||||
}
|
||||
@@ -141,8 +166,22 @@ fn get_all_proposals(_db: Arc<OurDB>) -> Vec<Proposal> {
|
||||
let start_date = Utc::now();
|
||||
let end_date = start_date + Duration::days(14);
|
||||
vec![
|
||||
Proposal::new(1, "Creator 1", "Proposal 1", "Description 1", start_date, end_date),
|
||||
Proposal::new(2, "Creator 2", "Proposal 2", "Description 2", start_date, end_date)
|
||||
Proposal::new(
|
||||
1,
|
||||
"Creator 1",
|
||||
"Proposal 1",
|
||||
"Description 1",
|
||||
start_date,
|
||||
end_date,
|
||||
),
|
||||
Proposal::new(
|
||||
2,
|
||||
"Creator 2",
|
||||
"Proposal 2",
|
||||
"Description 2",
|
||||
start_date,
|
||||
end_date,
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -161,31 +200,49 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Register the Proposal type with Rhai
|
||||
// This function is generated by the #[rhai_model_export] attribute
|
||||
Proposal::register_rhai_bindings_for_proposal(&mut engine, db.clone());
|
||||
|
||||
|
||||
// Register the Ballot type with Rhai
|
||||
Ballot::register_rhai_bindings_for_ballot(&mut engine, db.clone());
|
||||
|
||||
// Create a clone of db for use in the get_db function
|
||||
let db_for_get_db = db.clone();
|
||||
|
||||
|
||||
// Register a function to get the database instance
|
||||
engine.register_fn("get_db", move || db_for_get_db.clone());
|
||||
|
||||
|
||||
// Register builder functions for Proposal and related types
|
||||
engine.register_fn("create_proposal", |id: i64, creator_id: String, title: String, description: String| {
|
||||
let start_date = Utc::now();
|
||||
let end_date = start_date + Duration::days(14);
|
||||
Proposal::new(id as u32, creator_id, title, description, start_date, end_date)
|
||||
});
|
||||
|
||||
engine.register_fn(
|
||||
"create_proposal",
|
||||
|id: i64, creator_id: String, title: String, description: String| {
|
||||
let start_date = Utc::now();
|
||||
let end_date = start_date + Duration::days(14);
|
||||
Proposal::new(
|
||||
id as u32,
|
||||
creator_id,
|
||||
title,
|
||||
description,
|
||||
start_date,
|
||||
end_date,
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
engine.register_fn("create_vote_option", |id: i64, text: String| {
|
||||
VoteOption::new(id as u8, text)
|
||||
});
|
||||
|
||||
engine.register_fn("create_ballot", |id: i64, user_id: i64, vote_option_id: i64, shares_count: i64| {
|
||||
Ballot::new(id as u32, user_id as u32, vote_option_id as u8, shares_count)
|
||||
});
|
||||
|
||||
|
||||
engine.register_fn(
|
||||
"create_ballot",
|
||||
|id: i64, user_id: i64, vote_option_id: i64, shares_count: i64| {
|
||||
Ballot::new(
|
||||
id as u32,
|
||||
user_id as u32,
|
||||
vote_option_id as u8,
|
||||
shares_count,
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
// Register getter and setter methods for Proposal properties
|
||||
engine.register_fn("get_title", get_title);
|
||||
engine.register_fn("get_description", get_description);
|
||||
@@ -193,34 +250,47 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
engine.register_fn("get_id", get_id);
|
||||
engine.register_fn("get_status", get_status);
|
||||
engine.register_fn("get_vote_status", get_vote_status);
|
||||
|
||||
|
||||
// Register methods for proposal operations
|
||||
engine.register_fn("add_option_to_proposal", add_option_to_proposal);
|
||||
engine.register_fn("cast_vote_on_proposal", cast_vote_on_proposal);
|
||||
engine.register_fn("change_proposal_status", change_proposal_status);
|
||||
engine.register_fn("change_vote_event_status", change_vote_event_status);
|
||||
|
||||
|
||||
// Register functions for database operations
|
||||
engine.register_fn("save_proposal", save_proposal);
|
||||
|
||||
engine.register_fn("get_proposal_by_id", |_db: Arc<OurDB>, id: i64| -> Proposal {
|
||||
// In a real implementation, this would retrieve the proposal from the database
|
||||
let start_date = Utc::now();
|
||||
let end_date = start_date + Duration::days(14);
|
||||
Proposal::new(id as u32, "Retrieved Creator", "Retrieved Proposal", "Retrieved Description", start_date, end_date)
|
||||
});
|
||||
|
||||
|
||||
engine.register_fn(
|
||||
"get_proposal_by_id",
|
||||
|_db: Arc<OurDB>, id: i64| -> Proposal {
|
||||
// In a real implementation, this would retrieve the proposal from the database
|
||||
let start_date = Utc::now();
|
||||
let end_date = start_date + Duration::days(14);
|
||||
Proposal::new(
|
||||
id as u32,
|
||||
"Retrieved Creator",
|
||||
"Retrieved Proposal",
|
||||
"Retrieved Description",
|
||||
start_date,
|
||||
end_date,
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
// Register a function to check if a proposal exists
|
||||
engine.register_fn("proposal_exists", |_db: Arc<OurDB>, id: i64| -> bool {
|
||||
// In a real implementation, this would check if the proposal exists in the database
|
||||
id == 1 || id == 2
|
||||
});
|
||||
|
||||
|
||||
// Register the function with the wrap_vec_return macro
|
||||
engine.register_fn("get_all_proposals", wrap_vec_return!(get_all_proposals, Arc<OurDB> => Proposal));
|
||||
|
||||
engine.register_fn(
|
||||
"get_all_proposals",
|
||||
wrap_vec_return!(get_all_proposals, Arc<OurDB> => Proposal),
|
||||
);
|
||||
|
||||
engine.register_fn("delete_proposal_by_id", delete_proposal_by_id);
|
||||
|
||||
|
||||
// Register helper functions for accessing proposal options and ballots
|
||||
engine.register_fn("get_option_count", get_option_count);
|
||||
engine.register_fn("get_option_at", get_option_at);
|
||||
@@ -231,96 +301,108 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
engine.register_fn("get_ballot_user_id", get_ballot_user_id);
|
||||
engine.register_fn("get_ballot_option_id", get_ballot_option_id);
|
||||
engine.register_fn("get_ballot_shares", get_ballot_shares);
|
||||
|
||||
|
||||
// Register our wrapper functions that use the #[rhai] attribute
|
||||
engine.register_fn("create_proposal_wrapper", create_proposal_wrapper);
|
||||
engine.register_fn("add_option_wrapper", add_option_wrapper);
|
||||
|
||||
// Now instead of loading and evaluating a Rhai script, we'll use direct function calls
|
||||
// to implement the same functionality
|
||||
|
||||
|
||||
// Use the database instance
|
||||
|
||||
|
||||
// Create a new proposal
|
||||
let proposal = create_proposal(1,
|
||||
"user_creator_123".to_string(),
|
||||
"Community Fund Allocation for Q3".to_string(),
|
||||
"Proposal to allocate funds for community projects in the third quarter.".to_string());
|
||||
|
||||
println!("Created Proposal: '{}' (ID: {})",
|
||||
get_title(&proposal),
|
||||
get_id(&proposal));
|
||||
println!("Status: {}, Vote Status: {}",
|
||||
get_status(&proposal),
|
||||
get_vote_status(&proposal));
|
||||
|
||||
let proposal = create_proposal(
|
||||
1,
|
||||
"user_creator_123".to_string(),
|
||||
"Community Fund Allocation for Q3".to_string(),
|
||||
"Proposal to allocate funds for community projects in the third quarter.".to_string(),
|
||||
);
|
||||
|
||||
println!(
|
||||
"Created Proposal: '{}' (ID: {})",
|
||||
get_title(&proposal),
|
||||
get_id(&proposal)
|
||||
);
|
||||
println!(
|
||||
"Status: {}, Vote Status: {}",
|
||||
get_status(&proposal),
|
||||
get_vote_status(&proposal)
|
||||
);
|
||||
|
||||
// Add vote options
|
||||
let mut proposal_with_options = add_option_to_proposal(
|
||||
proposal, 1, "Approve Allocation".to_string());
|
||||
proposal_with_options = add_option_to_proposal(
|
||||
proposal_with_options, 2, "Reject Allocation".to_string());
|
||||
proposal_with_options = add_option_to_proposal(
|
||||
proposal_with_options, 3, "Abstain".to_string());
|
||||
|
||||
let mut proposal_with_options =
|
||||
add_option_to_proposal(proposal, 1, "Approve Allocation".to_string());
|
||||
proposal_with_options =
|
||||
add_option_to_proposal(proposal_with_options, 2, "Reject Allocation".to_string());
|
||||
proposal_with_options = add_option_to_proposal(proposal_with_options, 3, "Abstain".to_string());
|
||||
|
||||
println!("\nAdded Vote Options:");
|
||||
let option_count = get_option_count(&proposal_with_options);
|
||||
for i in 0..option_count {
|
||||
let option = get_option_at(&proposal_with_options, i);
|
||||
println!("- Option ID: {}, Text: '{}', Votes: {}",
|
||||
i, get_option_text(&option),
|
||||
get_option_votes(&option));
|
||||
println!(
|
||||
"- Option ID: {}, Text: '{}', Votes: {}",
|
||||
i,
|
||||
get_option_text(&option),
|
||||
get_option_votes(&option)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Save the proposal to the database
|
||||
save_proposal(db.clone(), proposal_with_options.clone());
|
||||
println!("\nProposal saved to database");
|
||||
|
||||
|
||||
// Simulate casting votes
|
||||
println!("\nSimulating Votes...");
|
||||
// User 1 votes for 'Approve Allocation' with 100 shares
|
||||
let mut proposal_with_votes = cast_vote_on_proposal(
|
||||
proposal_with_options, 101, 1, 1, 100);
|
||||
let mut proposal_with_votes = cast_vote_on_proposal(proposal_with_options, 101, 1, 1, 100);
|
||||
// User 2 votes for 'Reject Allocation' with 50 shares
|
||||
proposal_with_votes = cast_vote_on_proposal(
|
||||
proposal_with_votes, 102, 2, 2, 50);
|
||||
proposal_with_votes = cast_vote_on_proposal(proposal_with_votes, 102, 2, 2, 50);
|
||||
// User 3 votes for 'Approve Allocation' with 75 shares
|
||||
proposal_with_votes = cast_vote_on_proposal(
|
||||
proposal_with_votes, 103, 3, 1, 75);
|
||||
proposal_with_votes = cast_vote_on_proposal(proposal_with_votes, 103, 3, 1, 75);
|
||||
// User 4 abstains with 20 shares
|
||||
proposal_with_votes = cast_vote_on_proposal(
|
||||
proposal_with_votes, 104, 4, 3, 20);
|
||||
|
||||
proposal_with_votes = cast_vote_on_proposal(proposal_with_votes, 104, 4, 3, 20);
|
||||
|
||||
println!("\nVote Counts After Simulation:");
|
||||
let option_count = get_option_count(&proposal_with_votes);
|
||||
for i in 0..option_count {
|
||||
let option = get_option_at(&proposal_with_votes, i);
|
||||
println!("- Option ID: {}, Text: '{}', Votes: {}",
|
||||
i, get_option_text(&option),
|
||||
get_option_votes(&option));
|
||||
println!(
|
||||
"- Option ID: {}, Text: '{}', Votes: {}",
|
||||
i,
|
||||
get_option_text(&option),
|
||||
get_option_votes(&option)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
println!("\nBallots Cast:");
|
||||
let ballot_count = get_ballot_count(&proposal_with_votes);
|
||||
for i in 0..ballot_count {
|
||||
let ballot = get_ballot_at(&proposal_with_votes, i);
|
||||
println!("- Ballot ID: {}, User ID: {}, Option ID: {}, Shares: {}",
|
||||
i, get_ballot_user_id(&ballot),
|
||||
get_ballot_option_id(&ballot),
|
||||
get_ballot_shares(&ballot));
|
||||
println!(
|
||||
"- Ballot ID: {}, User ID: {}, Option ID: {}, Shares: {}",
|
||||
i,
|
||||
get_ballot_user_id(&ballot),
|
||||
get_ballot_option_id(&ballot),
|
||||
get_ballot_shares(&ballot)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Change proposal status
|
||||
let active_proposal = change_proposal_status(
|
||||
proposal_with_votes, "Active".to_string());
|
||||
println!("\nChanged Proposal Status to: {}",
|
||||
get_status(&active_proposal));
|
||||
|
||||
let active_proposal = change_proposal_status(proposal_with_votes, "Active".to_string());
|
||||
println!(
|
||||
"\nChanged Proposal Status to: {}",
|
||||
get_status(&active_proposal)
|
||||
);
|
||||
|
||||
// Simulate closing the vote
|
||||
let closed_proposal = change_vote_event_status(
|
||||
active_proposal, "Closed".to_string());
|
||||
println!("Changed Vote Event Status to: {}",
|
||||
get_vote_status(&closed_proposal));
|
||||
|
||||
let closed_proposal = change_vote_event_status(active_proposal, "Closed".to_string());
|
||||
println!(
|
||||
"Changed Vote Event Status to: {}",
|
||||
get_vote_status(&closed_proposal)
|
||||
);
|
||||
|
||||
// Final proposal state
|
||||
println!("\nFinal Proposal State:");
|
||||
println!("Title: '{}'", get_title(&closed_proposal));
|
||||
@@ -330,37 +412,46 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let option_count = get_option_count(&closed_proposal);
|
||||
for i in 0..option_count {
|
||||
let option = get_option_at(&closed_proposal, i);
|
||||
println!(" - {}: {} (Votes: {})",
|
||||
i, get_option_text(&option),
|
||||
get_option_votes(&option));
|
||||
println!(
|
||||
" - {}: {} (Votes: {})",
|
||||
i,
|
||||
get_option_text(&option),
|
||||
get_option_votes(&option)
|
||||
);
|
||||
}
|
||||
println!("Total Ballots: {}", get_ballot_count(&closed_proposal));
|
||||
|
||||
|
||||
// Get all proposals from the database
|
||||
let all_proposals = get_all_proposals(db.clone());
|
||||
println!("\nTotal Proposals in Database: {}", all_proposals.len());
|
||||
for proposal in all_proposals {
|
||||
println!("Proposal ID: {}, Title: '{}'",
|
||||
get_id(&proposal),
|
||||
get_title(&proposal));
|
||||
println!(
|
||||
"Proposal ID: {}, Title: '{}'",
|
||||
get_id(&proposal),
|
||||
get_title(&proposal)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Delete a proposal
|
||||
delete_proposal_by_id(db.clone(), 1);
|
||||
println!("\nDeleted proposal with ID 1");
|
||||
|
||||
|
||||
// Demonstrate the use of Rhai client functions for simple types
|
||||
println!("\nUsing Rhai client functions for simple types:");
|
||||
let create_result = create_proposal_wrapper_rhai_client(&engine, 2,
|
||||
"rhai_user".to_string(),
|
||||
"Rhai Proposal".to_string(),
|
||||
"This proposal was created using a Rhai client function".to_string());
|
||||
let create_result = create_proposal_wrapper_rhai_client(
|
||||
&engine,
|
||||
2,
|
||||
"rhai_user".to_string(),
|
||||
"Rhai Proposal".to_string(),
|
||||
"This proposal was created using a Rhai client function".to_string(),
|
||||
);
|
||||
println!("{}", create_result);
|
||||
|
||||
let add_option_result = add_option_wrapper_rhai_client(&engine, 2, 4, "Rhai Option".to_string());
|
||||
|
||||
let add_option_result =
|
||||
add_option_wrapper_rhai_client(&engine, 2, 4, "Rhai Option".to_string());
|
||||
println!("{}", add_option_result);
|
||||
|
||||
|
||||
println!("\nGovernance Proposal Example Finished.");
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -70,7 +70,7 @@ fn main() {
|
||||
.add_signer(signer2.clone())
|
||||
.add_revision(revision1.clone())
|
||||
.add_revision(revision2.clone());
|
||||
|
||||
|
||||
// The `#[model]` derive handles `created_at` and `updated_at` in `base_data`.
|
||||
// `base_data.touch()` might be called internally by setters or needs explicit call if fields are set directly.
|
||||
// For builder pattern, the final state of `base_data.updated_at` reflects the time of the last builder call if `touch()` is implicit.
|
||||
@@ -87,7 +87,7 @@ fn main() {
|
||||
|
||||
println!("\n--- Contract Details After Signing ---");
|
||||
println!("{:#?}", contract);
|
||||
|
||||
|
||||
println!("\n--- Accessing Specific Fields ---");
|
||||
println!("Contract Title: {}", contract.title);
|
||||
println!("Contract Status: {:?}", contract.status);
|
||||
@@ -97,7 +97,10 @@ fn main() {
|
||||
println!("Updated At (timestamp): {}", contract.base_data.modified_at); // From BaseModelData
|
||||
|
||||
if let Some(first_signer_details) = contract.signers.first() {
|
||||
println!("\nFirst Signer: {} ({})", first_signer_details.name, first_signer_details.email);
|
||||
println!(
|
||||
"\nFirst Signer: {} ({})",
|
||||
first_signer_details.name, first_signer_details.email
|
||||
);
|
||||
println!(" Status: {:?}", first_signer_details.status);
|
||||
if let Some(signed_time) = first_signer_details.signed_at {
|
||||
println!(" Signed At: {}", signed_time);
|
||||
@@ -110,6 +113,6 @@ fn main() {
|
||||
println!(" Created By: {}", latest_rev.created_by);
|
||||
println!(" Revision Created At: {}", latest_rev.created_at);
|
||||
}
|
||||
|
||||
|
||||
println!("\nLegal Contract Model demonstration complete.");
|
||||
}
|
||||
|
@@ -22,13 +22,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
if !script_path.exists() {
|
||||
eprintln!("Error: Rhai script not found at {}", script_path_str);
|
||||
eprintln!("Please ensure the script 'legal.rhai' exists in the 'examples/legal_rhai/' directory.");
|
||||
return Err(Box::new(std::io::Error::new(std::io::ErrorKind::NotFound, format!("Rhai script not found: {}", script_path_str))));
|
||||
eprintln!(
|
||||
"Please ensure the script 'legal.rhai' exists in the 'examples/legal_rhai/' directory."
|
||||
);
|
||||
return Err(Box::new(std::io::Error::new(
|
||||
std::io::ErrorKind::NotFound,
|
||||
format!("Rhai script not found: {}", script_path_str),
|
||||
)));
|
||||
}
|
||||
|
||||
println!("Executing Rhai script: {}", script_path_str);
|
||||
let script = fs::read_to_string(script_path)?;
|
||||
|
||||
|
||||
match engine.eval::<()>(&script) {
|
||||
Ok(_) => println!("\nRhai script executed successfully!"),
|
||||
Err(e) => {
|
||||
|
@@ -33,6 +33,5 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
fs::remove_dir_all(db_path)?;
|
||||
println!("--- Cleaned up temporary database. ---");
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -59,21 +59,39 @@ fn main() {
|
||||
println!("Before saving - SimpleUser DB Keys: {:?}", user.db_keys());
|
||||
|
||||
println!("\nBefore saving - CustomUser ID: {}", custom_user.get_id());
|
||||
println!("Before saving - CustomUser DB Keys: {:?}", custom_user.db_keys());
|
||||
println!(
|
||||
"Before saving - CustomUser DB Keys: {:?}",
|
||||
custom_user.db_keys()
|
||||
);
|
||||
|
||||
// Save the models to the database
|
||||
let simple_collection = db.collection::<SimpleUser>().expect("can open simple user collection");
|
||||
let custom_collection = db.collection::<CustomUser>().expect("can open custom user collection");
|
||||
let simple_collection = db
|
||||
.collection::<SimpleUser>()
|
||||
.expect("can open simple user collection");
|
||||
let custom_collection = db
|
||||
.collection::<CustomUser>()
|
||||
.expect("can open custom user collection");
|
||||
|
||||
let (user_id, saved_user) = simple_collection.set(&user).expect("can save simple user");
|
||||
let (custom_user_id, saved_custom_user) = custom_collection.set(&custom_user).expect("can save custom user");
|
||||
let (custom_user_id, saved_custom_user) = custom_collection
|
||||
.set(&custom_user)
|
||||
.expect("can save custom user");
|
||||
|
||||
println!("\nAfter saving - SimpleUser ID: {}", saved_user.get_id());
|
||||
println!("After saving - SimpleUser DB Keys: {:?}", saved_user.db_keys());
|
||||
println!(
|
||||
"After saving - SimpleUser DB Keys: {:?}",
|
||||
saved_user.db_keys()
|
||||
);
|
||||
println!("Returned SimpleUser ID: {}", user_id);
|
||||
|
||||
println!("\nAfter saving - CustomUser ID: {}", saved_custom_user.get_id());
|
||||
println!("After saving - CustomUser DB Keys: {:?}", saved_custom_user.db_keys());
|
||||
println!(
|
||||
"\nAfter saving - CustomUser ID: {}",
|
||||
saved_custom_user.get_id()
|
||||
);
|
||||
println!(
|
||||
"After saving - CustomUser DB Keys: {:?}",
|
||||
saved_custom_user.db_keys()
|
||||
);
|
||||
println!("Returned CustomUser ID: {}", custom_user_id);
|
||||
|
||||
// Verify that the IDs were auto-generated
|
||||
@@ -83,5 +101,8 @@ fn main() {
|
||||
assert_ne!(saved_custom_user.get_id(), 0);
|
||||
|
||||
println!("\nExample finished. DB stored at {}", db_path);
|
||||
println!("To clean up, you can manually delete the directory: {}", db_path);
|
||||
println!(
|
||||
"To clean up, you can manually delete the directory: {}",
|
||||
db_path
|
||||
);
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
use rhai::{Engine, EvalAltResult, Scope};
|
||||
use std::sync::Arc;
|
||||
use heromodels::db::hero::OurDB;
|
||||
use heromodels::models::projects::register_projects_rhai_module;
|
||||
use rhai::{Engine, EvalAltResult, Scope};
|
||||
use std::fs;
|
||||
use std::sync::Arc;
|
||||
|
||||
fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
println!("Executing Rhai script: examples/project_rhai/project_test.rhai");
|
||||
@@ -18,8 +18,12 @@ fn main() -> Result<(), Box<EvalAltResult>> {
|
||||
|
||||
// Read the Rhai script from file
|
||||
let script_path = "examples/project_rhai/project_test.rhai";
|
||||
let script_content = fs::read_to_string(script_path)
|
||||
.map_err(|e| Box::new(EvalAltResult::ErrorSystem(format!("Cannot read script file: {}", script_path), e.into())))?;
|
||||
let script_content = fs::read_to_string(script_path).map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorSystem(
|
||||
format!("Cannot read script file: {}", script_path),
|
||||
e.into(),
|
||||
))
|
||||
})?;
|
||||
|
||||
// Create a new scope
|
||||
let mut scope = Scope::new();
|
||||
|
@@ -34,11 +34,16 @@ fn main() {
|
||||
println!("Before saving - SimpleUser DB Keys: {:?}", user.db_keys());
|
||||
|
||||
// Save the user to the database
|
||||
let collection = db.collection::<SimpleUser>().expect("can open user collection");
|
||||
let collection = db
|
||||
.collection::<SimpleUser>()
|
||||
.expect("can open user collection");
|
||||
let (user_id, saved_user) = collection.set(&user).expect("can save user");
|
||||
|
||||
println!("\nAfter saving - SimpleUser ID: {}", saved_user.get_id());
|
||||
println!("After saving - SimpleUser DB Keys: {:?}", saved_user.db_keys());
|
||||
println!(
|
||||
"After saving - SimpleUser DB Keys: {:?}",
|
||||
saved_user.db_keys()
|
||||
);
|
||||
println!("Returned ID: {}", user_id);
|
||||
|
||||
// Verify that the ID was auto-generated
|
||||
@@ -46,6 +51,8 @@ fn main() {
|
||||
assert_ne!(saved_user.get_id(), 0);
|
||||
|
||||
println!("\nExample finished. DB stored at {}", db_path);
|
||||
println!("To clean up, you can manually delete the directory: {}", db_path);
|
||||
println!(
|
||||
"To clean up, you can manually delete the directory: {}",
|
||||
db_path
|
||||
);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user