add heroledger models

This commit is contained in:
Timur Gordon
2025-08-08 09:46:30 +02:00
parent 0cffda37a7
commit 6727c7498d
58 changed files with 507 additions and 10894 deletions

View File

@@ -10,8 +10,8 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
bincode = { version = "2", features = ["serde"] }
chrono = { version = "0.4", features = ["serde"] }
ourdb = { path = "../ourdb" }
tst = { path = "../tst" }
ourdb = { path = "../../herolib_rust/packages/data/ourdb" }
tst = { path = "../../herolib_rust/packages/data/tst" }
heromodels-derive = { path = "../heromodels-derive" }
heromodels_core = { path = "../heromodels_core" }
rhai = { version = "1.21.0", features = [

View File

@@ -52,7 +52,6 @@ pub mut:
use heromodels_core::{Model, BaseModelData, IndexKey};
use heromodels_derive::model;
use rhai::CustomType;
use rhailib_derive::RhaiApi;
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
```

View File

@@ -0,0 +1,53 @@
// heroledger.rhai - Demonstration of HeroLedger models in Rhai
print("=== HeroLedger Models Demo ===");
// Create a new user
print("\n--- Creating User ---");
let new_user = new_user()
.name("Alice Johnson")
.email("alice@herocode.com")
.pubkey("0x1234567890abcdef")
.status("Active")
.save_user();
print("Created user: " + new_user.get_name());
print("User ID: " + new_user.get_id());
print("User email: " + new_user.get_email());
print("User pubkey: " + new_user.get_pubkey());
// Create a new group
print("\n--- Creating Group ---");
let new_group = new_group()
.name("HeroCode Developers")
.description("A group for HeroCode development team members")
.visibility("Public")
.save_group();
print("Created group: " + new_group.get_name());
print("Group ID: " + new_group.get_id());
print("Group description: " + new_group.get_description());
// Create a new account
print("\n--- Creating Account ---");
let new_account = new_account()
.name("Alice's Main Account")
.description("Primary account for Alice Johnson")
.currency("USD")
.save_account();
print("Created account: " + new_account.get_name());
print("Account ID: " + new_account.get_id());
print("Account currency: " + new_account.get_currency());
// Create a new DNS zone
print("\n--- Creating DNS Zone ---");
let new_dns_zone = new_dns_zone()
.name("herocode.com")
.description("Main domain for HeroCode")
.save_dns_zone();
print("Created DNS zone: " + new_dns_zone.get_name());
print("DNS zone ID: " + new_dns_zone.get_id());
print("\n=== Demo Complete ===");

View File

@@ -0,0 +1,50 @@
use heromodels_core::db::hero::OurDB;
use rhai::{Dynamic, Engine};
use heromodels::models::heroledger::rhai::register_heroledger_rhai_modules;
use std::sync::Arc;
use std::{fs, path::Path};
const CALLER_ID: &str = "example_caller";
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize Rhai engine
let mut engine = Engine::new();
// Initialize database with OurDB
let db_path = "temp_heroledger_db";
// Clean up previous database file if it exists
if Path::new(db_path).exists() {
fs::remove_dir_all(db_path)?;
}
let _db = Arc::new(OurDB::new(db_path, true).expect("Failed to create database"));
// Register the heroledger modules with Rhai
register_heroledger_rhai_modules(&mut engine);
let mut db_config = rhai::Map::new();
db_config.insert("DB_PATH".into(), db_path.into());
db_config.insert("CALLER_ID".into(), CALLER_ID.into());
db_config.insert("CONTEXT_ID".into(), CALLER_ID.into());
engine.set_default_tag(Dynamic::from(db_config)); // Or pass via CallFnOptions
// Load and evaluate the Rhai script
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let script_path = Path::new(manifest_dir)
.join("examples")
.join("heroledger")
.join("heroledger.rhai");
println!("Script path: {}", script_path.display());
let script = fs::read_to_string(&script_path)?;
println!("--- Running HeroLedger Rhai Script ---");
match engine.eval::<()>(&script) {
Ok(_) => println!("\n--- Script executed successfully! ---"),
Err(e) => eprintln!("\n--- Script execution failed: {} ---", e),
}
// Clean up the database file
fs::remove_dir_all(db_path)?;
println!("--- Cleaned up temporary database. ---");
Ok(())
}

View File

@@ -7,6 +7,7 @@ pub mod dnsrecord;
pub mod secretbox;
pub mod signature;
pub mod user_kvs;
pub mod rhai;
// Re-export key types for convenience
pub use user::{User, UserStatus, UserProfile, KYCInfo, KYCStatus, SecretBox};

View File

@@ -0,0 +1,330 @@
use ::rhai::plugin::*;
use ::rhai::{Array, Dynamic, Engine, EvalAltResult, Map, Module};
use std::mem;
use crate::models::heroledger::*;
// ============================================================================
// User Module
// ============================================================================
type RhaiUser = User;
#[export_module]
mod rhai_user_module {
use super::RhaiUser;
#[rhai_fn(name = "new_user", return_raw)]
pub fn new_user() -> Result<RhaiUser, Box<EvalAltResult>> {
Ok(User::new(0))
}
#[rhai_fn(name = "username", return_raw)]
pub fn set_username(
user: &mut RhaiUser,
username: String,
) -> Result<RhaiUser, Box<EvalAltResult>> {
let owned = std::mem::take(user);
*user = owned.username(username);
Ok(user.clone())
}
#[rhai_fn(name = "add_email", return_raw)]
pub fn add_email(
user: &mut RhaiUser,
email: String,
) -> Result<RhaiUser, Box<EvalAltResult>> {
let owned = std::mem::take(user);
*user = owned.add_email(email);
Ok(user.clone())
}
#[rhai_fn(name = "pubkey", return_raw)]
pub fn set_pubkey(
user: &mut RhaiUser,
pubkey: String,
) -> Result<RhaiUser, Box<EvalAltResult>> {
let owned = std::mem::take(user);
*user = owned.pubkey(pubkey);
Ok(user.clone())
}
#[rhai_fn(name = "status", return_raw)]
pub fn set_status(
user: &mut RhaiUser,
status: String,
) -> Result<RhaiUser, Box<EvalAltResult>> {
let status_enum = match status.as_str() {
"Active" => UserStatus::Active,
"Inactive" => UserStatus::Inactive,
"Suspended" => UserStatus::Suspended,
"Archived" => UserStatus::Archived,
_ => return Err(format!("Invalid user status: {}", status).into()),
};
let owned = std::mem::take(user);
*user = owned.status(status_enum);
Ok(user.clone())
}
#[rhai_fn(name = "save_user", return_raw)]
pub fn save_user(user: &mut RhaiUser) -> Result<RhaiUser, Box<EvalAltResult>> {
// This would integrate with the database save functionality
// For now, just return the user as-is
Ok(user.clone())
}
// Getters
#[rhai_fn(name = "get_id")]
pub fn get_id(user: &mut RhaiUser) -> i64 {
user.base_data.id as i64
}
#[rhai_fn(name = "get_username")]
pub fn get_username(user: &mut RhaiUser) -> String {
user.username.clone().unwrap_or_else(|| String::new())
}
#[rhai_fn(name = "get_email")]
pub fn get_email(user: &mut RhaiUser) -> String {
if let Some(first_email) = user.email.first() {
first_email.clone()
} else {
String::new()
}
}
#[rhai_fn(name = "get_pubkey")]
pub fn get_pubkey(user: &mut RhaiUser) -> String {
user.pubkey.clone().unwrap_or_else(|| String::new())
}
}
// ============================================================================
// Group Module
// ============================================================================
type RhaiGroup = Group;
#[export_module]
mod rhai_group_module {
use super::RhaiGroup;
#[rhai_fn(name = "new_group", return_raw)]
pub fn new_group() -> Result<RhaiGroup, Box<EvalAltResult>> {
Ok(Group::new(0))
}
#[rhai_fn(name = "name", return_raw)]
pub fn set_name(
group: &mut RhaiGroup,
name: String,
) -> Result<RhaiGroup, Box<EvalAltResult>> {
let owned = std::mem::take(group);
*group = owned.name(name);
Ok(group.clone())
}
#[rhai_fn(name = "description", return_raw)]
pub fn set_description(
group: &mut RhaiGroup,
description: String,
) -> Result<RhaiGroup, Box<EvalAltResult>> {
let owned = std::mem::take(group);
*group = owned.description(description);
Ok(group.clone())
}
#[rhai_fn(name = "visibility", return_raw)]
pub fn set_visibility(
group: &mut RhaiGroup,
visibility: String,
) -> Result<RhaiGroup, Box<EvalAltResult>> {
let visibility_enum = match visibility.as_str() {
"Public" => Visibility::Public,
"Private" => Visibility::Private,
_ => return Err(format!("Invalid visibility: {}", visibility).into()),
};
let owned = std::mem::take(group);
*group = owned.visibility(visibility_enum);
Ok(group.clone())
}
#[rhai_fn(name = "save_group", return_raw)]
pub fn save_group(group: &mut RhaiGroup) -> Result<RhaiGroup, Box<EvalAltResult>> {
Ok(group.clone())
}
// Getters
#[rhai_fn(name = "get_id")]
pub fn get_id(group: &mut RhaiGroup) -> i64 {
group.base_data.id as i64
}
#[rhai_fn(name = "get_name")]
pub fn get_name(group: &mut RhaiGroup) -> String {
group.name.clone().unwrap_or_else(|| String::new())
}
#[rhai_fn(name = "get_description")]
pub fn get_description(group: &mut RhaiGroup) -> String {
group.description.clone().unwrap_or_else(|| String::new())
}
}
// ============================================================================
// Account Module (from money.rs)
// ============================================================================
type RhaiAccount = Account;
#[export_module]
mod rhai_account_module {
use super::RhaiAccount;
#[rhai_fn(name = "new_account", return_raw)]
pub fn new_account() -> Result<RhaiAccount, Box<EvalAltResult>> {
Ok(Account::new(0))
}
#[rhai_fn(name = "owner_id", return_raw)]
pub fn set_owner_id(
account: &mut RhaiAccount,
owner_id: i64,
) -> Result<RhaiAccount, Box<EvalAltResult>> {
let owned = std::mem::take(account);
*account = owned.owner_id(owner_id as u32);
Ok(account.clone())
}
#[rhai_fn(name = "address", return_raw)]
pub fn set_address(
account: &mut RhaiAccount,
address: String,
) -> Result<RhaiAccount, Box<EvalAltResult>> {
let owned = std::mem::take(account);
*account = owned.address(address);
Ok(account.clone())
}
#[rhai_fn(name = "currency", return_raw)]
pub fn set_currency(
account: &mut RhaiAccount,
currency: String,
) -> Result<RhaiAccount, Box<EvalAltResult>> {
let owned = std::mem::take(account);
*account = owned.currency(currency);
Ok(account.clone())
}
#[rhai_fn(name = "save_account", return_raw)]
pub fn save_account(account: &mut RhaiAccount) -> Result<RhaiAccount, Box<EvalAltResult>> {
Ok(account.clone())
}
// Getters
#[rhai_fn(name = "get_id")]
pub fn get_id(account: &mut RhaiAccount) -> i64 {
account.base_data.id as i64
}
#[rhai_fn(name = "get_address")]
pub fn get_address(account: &mut RhaiAccount) -> String {
account.address.clone()
}
#[rhai_fn(name = "get_currency")]
pub fn get_currency(account: &mut RhaiAccount) -> String {
account.currency.clone()
}
}
// ============================================================================
// DNS Zone Module
// ============================================================================
type RhaiDNSZone = DNSZone;
#[export_module]
mod rhai_dns_zone_module {
use super::RhaiDNSZone;
#[rhai_fn(name = "new_dns_zone", return_raw)]
pub fn new_dns_zone() -> Result<RhaiDNSZone, Box<EvalAltResult>> {
Ok(DNSZone::new(0))
}
#[rhai_fn(name = "name", return_raw)]
pub fn set_name(
zone: &mut RhaiDNSZone,
name: String,
) -> Result<RhaiDNSZone, Box<EvalAltResult>> {
let owned = std::mem::take(zone);
*zone = owned.name(name);
Ok(zone.clone())
}
#[rhai_fn(name = "description", return_raw)]
pub fn set_description(
zone: &mut RhaiDNSZone,
description: String,
) -> Result<RhaiDNSZone, Box<EvalAltResult>> {
let owned = std::mem::take(zone);
*zone = owned.description(description);
Ok(zone.clone())
}
#[rhai_fn(name = "save_dns_zone", return_raw)]
pub fn save_dns_zone(zone: &mut RhaiDNSZone) -> Result<RhaiDNSZone, Box<EvalAltResult>> {
Ok(zone.clone())
}
// Setters
#[rhai_fn(name = "set_domain")]
pub fn set_domain(zone: &mut RhaiDNSZone, domain: &str) {
let owned = std::mem::take(zone);
*zone = owned.domain(domain);
}
// Getters
#[rhai_fn(name = "get_id")]
pub fn get_id(zone: &mut RhaiDNSZone) -> i64 {
zone.base_data.id as i64
}
#[rhai_fn(name = "get_domain")]
pub fn get_domain(zone: &mut RhaiDNSZone) -> String {
zone.domain.clone()
}
}
// ============================================================================
// Registration Functions
// ============================================================================
// Registration functions
pub fn register_user_functions(engine: &mut Engine) {
let module = exported_module!(user_module);
engine.register_static_module("user", module.into());
}
pub fn register_group_functions(engine: &mut Engine) {
let module = exported_module!(group_module);
engine.register_static_module("group", module.into());
}
pub fn register_account_functions(engine: &mut Engine) {
let module = exported_module!(account_module);
engine.register_static_module("account", module.into());
}
pub fn register_dnszone_functions(engine: &mut Engine) {
let module = exported_module!(dnszone_module);
engine.register_static_module("dnszone", module.into());
}
/// Register all heroledger Rhai modules with the engine
pub fn register_heroledger_rhai_modules(engine: &mut Engine) {
register_user_functions(engine);
register_group_functions(engine);
register_account_functions(engine);
register_dnszone_functions(engine);
}

View File

@@ -1,5 +1,6 @@
// Export contact module
// Export object module
pub mod object;
pub mod object_rhai_dsl;
// Re-export contact, Group from the inner contact module (contact.rs) within src/models/contact/mod.rs
// Re-export Object from the inner object module (object.rs) within src/models/object/mod.rs
pub use self::object::Object;

View File

@@ -0,0 +1,56 @@
use rhai::plugin::*;
use rhai::{CustomType, Dynamic, Engine, EvalAltResult, Module};
use super::Object;
type RhaiObject = Object;
#[export_module]
pub mod generated_rhai_module {
use super::*;
/// Create a new Object
#[rhai_fn(name = "new_object")]
pub fn new_object() -> RhaiObject {
Object::new()
}
/// Set the title of an Object
#[rhai_fn(name = "object_title")]
pub fn object_title(
object: &mut RhaiObject,
title: String,
) -> RhaiObject {
let mut result = object.clone();
result.title = title;
result
}
/// Set the description of an Object
#[rhai_fn(name = "object_description")]
pub fn object_description(
object: &mut RhaiObject,
description: String,
) -> RhaiObject {
let mut result = object.clone();
result.description = description;
result
}
/// Get the ID of an Object
#[rhai_fn(name = "get_object_id")]
pub fn get_object_id(object: &mut RhaiObject) -> i64 {
object.id() as i64
}
/// Get the title of an Object
#[rhai_fn(name = "get_object_title")]
pub fn get_object_title(object: &mut RhaiObject) -> String {
object.title.clone()
}
/// Get the description of an Object
#[rhai_fn(name = "get_object_description")]
pub fn get_object_description(object: &mut RhaiObject) -> String {
object.description.clone()
}
}