wip
This commit is contained in:
232
docs/CREATING_NEW_OBJECTS.md
Normal file
232
docs/CREATING_NEW_OBJECTS.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# Guide: Creating New OSIRIS Objects
|
||||
|
||||
This guide explains how to properly create new object types in OSIRIS that integrate with the Rhai scripting engine and context storage.
|
||||
|
||||
## Step-by-Step Process
|
||||
|
||||
### 1. Create the Object Module
|
||||
|
||||
Create a new file in the appropriate directory under `src/objects/`:
|
||||
- `src/objects/legal/` for legal objects
|
||||
- `src/objects/money/` for financial objects
|
||||
- `src/objects/heroledger/` for HeroLedger objects
|
||||
- etc.
|
||||
|
||||
### 2. Define the Object Struct
|
||||
|
||||
**CRITICAL**: The struct MUST derive `crate::DeriveObject` to automatically implement the `Object` trait.
|
||||
|
||||
```rust
|
||||
use crate::store::BaseData;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Your object description
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, crate::DeriveObject)]
|
||||
pub struct YourObject {
|
||||
/// Base data for object storage (REQUIRED)
|
||||
pub base_data: BaseData,
|
||||
|
||||
/// Your custom fields
|
||||
pub title: String,
|
||||
pub status: YourStatus,
|
||||
// ... other fields
|
||||
}
|
||||
```
|
||||
|
||||
**Required traits:**
|
||||
- `Debug` - for debugging
|
||||
- `Clone` - required by Object trait
|
||||
- `Serialize, Deserialize` - for JSON serialization
|
||||
- `PartialEq` - for comparisons
|
||||
- `crate::DeriveObject` - **CRITICAL** - auto-implements Object trait
|
||||
|
||||
**Required field:**
|
||||
- `base_data: BaseData` - MUST be present for object storage
|
||||
|
||||
### 3. Implement Constructor and Methods
|
||||
|
||||
```rust
|
||||
impl YourObject {
|
||||
/// Create a new object
|
||||
pub fn new(id: u32) -> Self {
|
||||
let base_data = BaseData::with_id(id, String::new());
|
||||
Self {
|
||||
base_data,
|
||||
title: String::new(),
|
||||
status: YourStatus::default(),
|
||||
// ... initialize other fields
|
||||
}
|
||||
}
|
||||
|
||||
/// Fluent builder methods
|
||||
pub fn title(mut self, title: impl ToString) -> Self {
|
||||
self.title = title.to_string();
|
||||
self
|
||||
}
|
||||
|
||||
// ... other methods
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Create Rhai Bindings Module
|
||||
|
||||
Create `rhai.rs` in the same directory:
|
||||
|
||||
```rust
|
||||
use ::rhai::plugin::*;
|
||||
use ::rhai::{CustomType, Dynamic, Engine, EvalAltResult, Module, TypeBuilder};
|
||||
|
||||
use super::{YourObject, YourStatus};
|
||||
|
||||
/// Register your modules with the Rhai engine
|
||||
pub fn register_your_modules(parent_module: &mut Module) {
|
||||
// Register custom types
|
||||
parent_module.set_custom_type::<YourObject>("YourObject");
|
||||
parent_module.set_custom_type::<YourStatus>("YourStatus");
|
||||
|
||||
// Merge functions
|
||||
let your_module = exported_module!(rhai_your_module);
|
||||
parent_module.merge(&your_module);
|
||||
}
|
||||
|
||||
#[export_module]
|
||||
mod rhai_your_module {
|
||||
use super::YourObject;
|
||||
use ::rhai::EvalAltResult;
|
||||
|
||||
// Constructor
|
||||
#[rhai_fn(name = "new_your_object", return_raw)]
|
||||
pub fn new_your_object(id: i64) -> Result<YourObject, Box<EvalAltResult>> {
|
||||
Ok(YourObject::new(id as u32))
|
||||
}
|
||||
|
||||
// Builder methods
|
||||
#[rhai_fn(name = "title", return_raw)]
|
||||
pub fn set_title(
|
||||
obj: YourObject,
|
||||
title: String,
|
||||
) -> Result<YourObject, Box<EvalAltResult>> {
|
||||
Ok(obj.title(title))
|
||||
}
|
||||
|
||||
// Getters
|
||||
#[rhai_fn(name = "title", pure)]
|
||||
pub fn get_title(obj: &mut YourObject) -> String {
|
||||
obj.title.clone()
|
||||
}
|
||||
}
|
||||
|
||||
// CustomType implementations
|
||||
impl CustomType for YourObject {
|
||||
fn build(mut builder: TypeBuilder<Self>) {
|
||||
builder.with_name("YourObject");
|
||||
}
|
||||
}
|
||||
|
||||
impl CustomType for YourStatus {
|
||||
fn build(mut builder: TypeBuilder<Self>) {
|
||||
builder.with_name("YourStatus");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Update Module Exports
|
||||
|
||||
In `mod.rs` of your object category:
|
||||
|
||||
```rust
|
||||
pub mod your_object;
|
||||
pub mod rhai;
|
||||
|
||||
pub use your_object::{YourObject, YourStatus};
|
||||
pub use rhai::register_your_modules;
|
||||
```
|
||||
|
||||
In `src/objects/mod.rs`:
|
||||
|
||||
```rust
|
||||
pub mod your_category;
|
||||
|
||||
pub use your_category::{YourObject, YourStatus};
|
||||
```
|
||||
|
||||
### 6. Register in Engine (CRITICAL STEP)
|
||||
|
||||
In `src/engine.rs`, add the save registration in the `OsirisPackage` definition:
|
||||
|
||||
```rust
|
||||
def_package! {
|
||||
pub OsirisPackage(module) : StandardPackage {
|
||||
// ... existing registrations ...
|
||||
|
||||
// Add your object's save method
|
||||
FuncRegistration::new("save")
|
||||
.set_into_module(module, |ctx: &mut OsirisContext, obj: crate::objects::YourObject| ctx.save_object(obj));
|
||||
|
||||
// ... existing registrations ...
|
||||
|
||||
// Register your modules
|
||||
register_your_modules(module);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Also add the import at the top of `engine.rs`:
|
||||
|
||||
```rust
|
||||
use crate::objects::your_category::rhai::register_your_modules;
|
||||
```
|
||||
|
||||
### 7. Create Example Script
|
||||
|
||||
Create `examples/engine/XX_your_object.rhai`:
|
||||
|
||||
```rhai
|
||||
print("=== Your Object Example ===\n");
|
||||
|
||||
// Get context
|
||||
let ctx = get_context(["alice", "bob"]);
|
||||
|
||||
// Create object
|
||||
let obj = new_your_object(1)
|
||||
.title("Example Title");
|
||||
|
||||
print("Object created: " + obj.title());
|
||||
|
||||
// Store in context
|
||||
ctx.save(obj);
|
||||
print("Object stored");
|
||||
|
||||
print("\n=== Example Complete ===");
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
Before considering your object complete, verify:
|
||||
|
||||
- [ ] Struct derives `crate::DeriveObject`
|
||||
- [ ] Struct has `base_data: BaseData` field
|
||||
- [ ] Rhai module created with `register_*_modules` function
|
||||
- [ ] Custom types registered with `set_custom_type`
|
||||
- [ ] Module exported in `mod.rs` files
|
||||
- [ ] Save method registered in `src/engine.rs`
|
||||
- [ ] Module registration added to `OsirisPackage` in `src/engine.rs`
|
||||
- [ ] Example script created and tested
|
||||
- [ ] Example runs successfully with `cargo run --example engine examples/engine/XX_your_object.rhai`
|
||||
|
||||
## Common Mistakes to Avoid
|
||||
|
||||
1. **Forgetting `crate::DeriveObject`** - Without this, the Object trait won't be implemented
|
||||
2. **Missing `base_data` field** - Required for all storable objects
|
||||
3. **Not registering save in engine.rs** - The save method MUST be in engine.rs, not context.rs
|
||||
4. **Not calling `set_custom_type`** - Rhai won't recognize your type
|
||||
5. **Not merging the exported module** - Your functions won't be available
|
||||
|
||||
## Example: Contract Object
|
||||
|
||||
See the Contract object implementation as a reference:
|
||||
- Struct: `src/objects/legal/contract.rs`
|
||||
- Rhai bindings: `src/objects/legal/rhai.rs`
|
||||
- Module exports: `src/objects/legal/mod.rs` and `src/objects/mod.rs`
|
||||
- Engine registration: `src/engine.rs` (line ~110 and ~138)
|
||||
- Example: `examples/engine/12_contract.rhai`
|
||||
113
docs/FREEZONE_IMPLEMENTATION_TODO.md
Normal file
113
docs/FREEZONE_IMPLEMENTATION_TODO.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Freezone Implementation TODO
|
||||
|
||||
## Summary
|
||||
The freezone.rhai example has been created and demonstrates a complete registration flow. However, some Rhai bindings need to be implemented to make it fully functional.
|
||||
|
||||
## Required Implementations
|
||||
|
||||
### 1. Ethereum Wallet Function
|
||||
**Location:** `src/objects/money/rhai.rs`
|
||||
|
||||
Add a `new_ethereum_wallet()` function that creates an Ethereum wallet:
|
||||
|
||||
```rust
|
||||
#[rhai_fn(name = "new_ethereum_wallet", return_raw)]
|
||||
pub fn new_ethereum_wallet() -> Result<EthereumWallet, Box<EvalAltResult>> {
|
||||
// Generate new Ethereum wallet
|
||||
// Return wallet with address, private key (encrypted), network
|
||||
Ok(EthereumWallet::new())
|
||||
}
|
||||
```
|
||||
|
||||
The wallet should have:
|
||||
- `.owner_id(id)` - set owner
|
||||
- `.network(network)` - set network (mainnet/testnet)
|
||||
- `.get_address()` - get Ethereum address
|
||||
|
||||
### 2. Accounting Module
|
||||
**Location:** `src/objects/accounting/`
|
||||
|
||||
Create Invoice and Expense objects (files were created but need to be integrated):
|
||||
|
||||
**Invoice:**
|
||||
- `new_invoice(id)` - constructor
|
||||
- `.invoice_number(num)`, `.customer_id(id)`, `.amount(amt)`, `.currency(cur)`, `.description(desc)`
|
||||
- `.send()`, `.mark_paid()`, `.mark_overdue()`, `.cancel()`
|
||||
- Getters: `.invoice_number()`, `.customer_id()`, `.amount()`, `.status()`
|
||||
|
||||
**Expense:**
|
||||
- `new_expense(id)` - constructor
|
||||
- `.user_id(id)`, `.amount(amt)`, `.currency(cur)`, `.description(desc)`, `.category(cat)`, `.invoice_id(id)`
|
||||
- `.approve()`, `.mark_paid()`, `.reject()`
|
||||
- Getters: `.user_id()`, `.amount()`, `.status()`, `.category()`
|
||||
|
||||
### 3. Payment Request Enhancements
|
||||
**Location:** `src/objects/money/payments.rs` and `rhai.rs`
|
||||
|
||||
Add `new_payment_request()` function with builder API:
|
||||
- `.amount(amt)`
|
||||
- `.currency(cur)`
|
||||
- `.description(desc)`
|
||||
- `.callback_url(url)`
|
||||
- `.merchant_reference(ref)`
|
||||
|
||||
### 4. KYC Info Enhancements
|
||||
**Location:** `src/objects/kyc/info.rs` and `rhai.rs`
|
||||
|
||||
Add missing builder methods:
|
||||
- `.document_type(type)` - passport, id_card, drivers_license
|
||||
- `.document_number(num)`
|
||||
- `.verified(bool)` - mark as verified
|
||||
|
||||
### 5. Engine Registration
|
||||
**Location:** `src/engine.rs`
|
||||
|
||||
Add to `OsirisPackage`:
|
||||
```rust
|
||||
// Register Accounting modules
|
||||
register_accounting_modules(module);
|
||||
|
||||
// Add save methods for Invoice and Expense
|
||||
FuncRegistration::new("save")
|
||||
.set_into_module(module, |ctx: &mut OsirisContext, invoice: crate::objects::Invoice| ctx.save_object(invoice));
|
||||
FuncRegistration::new("save")
|
||||
.set_into_module(module, |ctx: &mut OsirisContext, expense: crate::objects::Expense| ctx.save_object(expense));
|
||||
```
|
||||
|
||||
### 6. Module Exports
|
||||
**Location:** `src/objects/mod.rs`
|
||||
|
||||
Add:
|
||||
```rust
|
||||
pub mod accounting;
|
||||
pub use accounting::{Invoice, Expense};
|
||||
```
|
||||
|
||||
## Current Freezone Flow
|
||||
|
||||
The freezone.rhai example demonstrates:
|
||||
|
||||
1. **Public Key Registration** - User provides public key
|
||||
2. **Personal Information** - Collect name, email, create KYC info
|
||||
3. **Terms & Conditions** - Create and sign contract
|
||||
4. **Email Verification** - Generate code, send email, verify
|
||||
5. **Crypto Wallet Creation** - Create TFT account + Ethereum wallet
|
||||
6. **Payment Processing** - Pesapal payment session, user pays, record transaction
|
||||
7. **KYC Verification** - KYC session, user completes verification, callback with results
|
||||
8. **User Registration** - Create final user object
|
||||
|
||||
## Testing
|
||||
|
||||
Once implementations are complete, run:
|
||||
```bash
|
||||
cargo run --example freezone
|
||||
```
|
||||
|
||||
Expected output: Complete freezone registration flow with all 8 steps executing successfully.
|
||||
|
||||
## Notes
|
||||
|
||||
- The example uses simulated callbacks for payment and KYC
|
||||
- Ethereum wallet generation should use a proper library (e.g., ethers-rs)
|
||||
- Payment integration with Pesapal is mocked but shows the expected flow
|
||||
- KYC callback demonstrates how verified data would be received and stored
|
||||
Reference in New Issue
Block a user