diff --git a/actix_mvc_app/Cargo.lock b/actix_mvc_app/Cargo.lock index d3cbc8b..d1e3b73 100644 --- a/actix_mvc_app/Cargo.lock +++ b/actix_mvc_app/Cargo.lock @@ -263,6 +263,7 @@ dependencies = [ "serde", "serde_json", "tera", + "urlencoding", "uuid", ] @@ -2655,6 +2656,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf16_iter" version = "1.0.5" diff --git a/actix_mvc_app/Cargo.toml b/actix_mvc_app/Cargo.toml index 47f2a0b..482ced4 100644 --- a/actix_mvc_app/Cargo.toml +++ b/actix_mvc_app/Cargo.toml @@ -23,3 +23,4 @@ uuid = { version = "1.6.1", features = ["v4", "serde"] } lazy_static = "1.4.0" redis = { version = "0.23.0", features = ["tokio-comp"] } jsonwebtoken = "8.3.0" +urlencoding = "2.1.3" diff --git a/actix_mvc_app/src/controllers/defi.rs b/actix_mvc_app/src/controllers/defi.rs new file mode 100644 index 0000000..e4018c7 --- /dev/null +++ b/actix_mvc_app/src/controllers/defi.rs @@ -0,0 +1,369 @@ +use actix_web::{web, HttpResponse, Result}; +use actix_web::HttpRequest; +use tera::{Context, Tera}; +use chrono::{Utc, Duration}; +use serde::Deserialize; +use uuid::Uuid; + +use crate::models::asset::{Asset, AssetType, AssetStatus}; +use crate::models::defi::{DefiPosition, DefiPositionType, DefiPositionStatus, LendingPosition, BorrowingPosition, DEFI_DB}; +use crate::utils::render_template; + +// Form structs for DeFi operations +#[derive(Debug, Deserialize)] +pub struct LendingForm { + pub asset_id: String, + pub amount: f64, + pub duration: i32, +} + +#[derive(Debug, Deserialize)] +pub struct BorrowingForm { + pub collateral_asset_id: String, + pub collateral_amount: f64, + pub amount: f64, + pub duration: i32, +} + +#[derive(Debug, Deserialize)] +pub struct LiquidityForm { + pub first_token: String, + pub first_amount: f64, + pub second_token: String, + pub second_amount: f64, + pub pool_fee: f64, +} + +#[derive(Debug, Deserialize)] +pub struct StakingForm { + pub asset_id: String, + pub amount: f64, + pub staking_period: i32, +} + +#[derive(Debug, Deserialize)] +pub struct SwapForm { + pub from_token: String, + pub from_amount: f64, + pub to_token: String, +} + +#[derive(Debug, Deserialize)] +pub struct CollateralForm { + pub asset_id: String, + pub amount: f64, + pub purpose: String, + pub loan_amount: Option, + pub loan_term: Option, +} + +pub struct DefiController; + +impl DefiController { + // Display the DeFi dashboard + pub async fn index(tmpl: web::Data, req: HttpRequest) -> Result { + let mut context = Context::new(); + + println!("DEBUG: Starting DeFi dashboard rendering"); + + // Get mock assets for the dropdown selectors + let assets = Self::get_mock_assets(); + println!("DEBUG: Generated {} mock assets", assets.len()); + + // Add active_page for navigation highlighting + context.insert("active_page", &"defi"); + + // Add DeFi stats + let defi_stats = Self::get_defi_stats(); + context.insert("defi_stats", &serde_json::to_value(defi_stats).unwrap()); + + // Add recent assets for selection in forms + let recent_assets: Vec> = assets + .iter() + .take(5) + .map(|a| Self::asset_to_json(a)) + .collect(); + + context.insert("recent_assets", &recent_assets); + + // Get user's lending positions + let db = DEFI_DB.lock().unwrap(); + let lending_positions = db.get_user_lending_positions("user123"); + let lending_positions_json: Vec = lending_positions + .iter() + .map(|p| serde_json::to_value(p).unwrap()) + .collect(); + context.insert("lending_positions", &lending_positions_json); + + // Get user's borrowing positions + let borrowing_positions = db.get_user_borrowing_positions("user123"); + let borrowing_positions_json: Vec = borrowing_positions + .iter() + .map(|p| serde_json::to_value(p).unwrap()) + .collect(); + context.insert("borrowing_positions", &borrowing_positions_json); + + // Add success message if present in query params + if let Some(success) = req.query_string().strip_prefix("success=") { + let decoded = urlencoding::decode(success).unwrap_or_else(|_| success.into()); + context.insert("success_message", &decoded); + } + + println!("DEBUG: Rendering DeFi dashboard template"); + let response = render_template(&tmpl, "defi/index.html", &context); + println!("DEBUG: Finished rendering DeFi dashboard template"); + response + } + + // Process lending request + pub async fn create_lending(_tmpl: web::Data, form: web::Form) -> Result { + println!("DEBUG: Processing lending request: {:?}", form); + + // Get the asset details (in a real app, this would come from a database) + let assets = Self::get_mock_assets(); + let asset = assets.iter().find(|a| a.id == form.asset_id); + + if let Some(asset) = asset { + // Calculate interest and return amount + let apy = match form.duration { + 7 => 2.5, + 30 => 4.2, + 90 => 6.8, + 180 => 8.5, + 365 => 12.0, + _ => 4.2, // Default to 30 days rate + }; + + let interest = form.amount * (apy / 100.0) * (form.duration as f64 / 365.0); + let return_amount = form.amount + interest; + + // Create a new lending position + let lending_position = LendingPosition { + base: DefiPosition { + id: Uuid::new_v4().to_string(), + position_type: DefiPositionType::Lending, + status: DefiPositionStatus::Active, + asset_id: asset.id.clone(), + asset_name: asset.name.clone(), + asset_symbol: asset.asset_type.as_str().to_string(), // Using asset_type as symbol for now + amount: form.amount, + value_usd: form.amount * asset.latest_valuation().map_or(0.5, |v| v.value), // Assuming 0.5 USD per token if no valuation + apy, + created_at: Utc::now(), + expires_at: Some(Utc::now() + Duration::days(form.duration as i64)), + user_id: "user123".to_string(), // Hardcoded user ID for now + }, + duration_days: form.duration, + interest_earned: interest, + return_amount, + }; + + // Add the position to the database + { + let mut db = DEFI_DB.lock().unwrap(); + db.add_lending_position(lending_position); + } + + // Redirect with success message + let success_message = format!("Successfully lent {} {} at {}% APY", form.amount, asset.name, apy); + Ok(HttpResponse::SeeOther() + .append_header(("Location", format!("/defi?success={}", urlencoding::encode(&success_message)))) + .finish()) + } else { + // Asset not found, redirect with error + Ok(HttpResponse::SeeOther() + .append_header(("Location", "/defi?error=Asset not found")) + .finish()) + } + } + + // Process borrowing request + pub async fn create_borrowing(_tmpl: web::Data, form: web::Form) -> Result { + println!("DEBUG: Processing borrowing request: {:?}", form); + + // Get the asset details (in a real app, this would come from a database) + let assets = Self::get_mock_assets(); + let collateral_asset = assets.iter().find(|a| a.id == form.collateral_asset_id); + + if let Some(collateral_asset) = collateral_asset { + // Calculate interest rate based on duration + let interest_rate = match form.duration { + 7 => 3.5, + 30 => 5.0, + 90 => 6.5, + 180 => 8.0, + 365 => 10.0, + _ => 5.0, // Default to 30 days rate + }; + + // Calculate interest and total to repay + let interest = form.amount * (interest_rate / 100.0) * (form.duration as f64 / 365.0); + let total_to_repay = form.amount + interest; + + // Calculate collateral value and ratio + let collateral_value = form.collateral_amount * collateral_asset.latest_valuation().map_or(0.5, |v| v.value); + let collateral_ratio = (collateral_value / form.amount) * 100.0; + + // Create a new borrowing position + let borrowing_position = BorrowingPosition { + base: DefiPosition { + id: Uuid::new_v4().to_string(), + position_type: DefiPositionType::Borrowing, + status: DefiPositionStatus::Active, + asset_id: "ZAZ".to_string(), // Hardcoded for now, in a real app this would be a parameter + asset_name: "Zanzibar Token".to_string(), + asset_symbol: "ZAZ".to_string(), + amount: form.amount, + value_usd: form.amount * 0.5, // Assuming 0.5 USD per ZAZ + apy: interest_rate, + created_at: Utc::now(), + expires_at: Some(Utc::now() + Duration::days(form.duration as i64)), + user_id: "user123".to_string(), // Hardcoded user ID for now + }, + collateral_asset_id: collateral_asset.id.clone(), + collateral_asset_name: collateral_asset.name.clone(), + collateral_asset_symbol: collateral_asset.asset_type.as_str().to_string(), + collateral_amount: form.collateral_amount, + collateral_value_usd: collateral_value, + duration_days: form.duration, + interest_rate, + interest_owed: interest, + total_to_repay, + collateral_ratio, + }; + + // Add the position to the database + { + let mut db = DEFI_DB.lock().unwrap(); + db.add_borrowing_position(borrowing_position); + } + + // Redirect with success message + let success_message = format!("Successfully borrowed {} ZAZ using {} {} as collateral", + form.amount, form.collateral_amount, collateral_asset.name); + Ok(HttpResponse::SeeOther() + .append_header(("Location", format!("/defi?success={}", urlencoding::encode(&success_message)))) + .finish()) + } else { + // Asset not found, redirect with error + Ok(HttpResponse::SeeOther() + .append_header(("Location", "/defi?error=Collateral asset not found")) + .finish()) + } + } + + // Process liquidity provision + pub async fn add_liquidity(_tmpl: web::Data, form: web::Form) -> Result { + println!("DEBUG: Processing liquidity provision: {:?}", form); + + // In a real application, this would add liquidity to a pool in the database + // For now, we'll just redirect back to the DeFi dashboard with a success message + + let success_message = format!("Successfully added liquidity: {} {} and {} {}", + form.first_amount, form.first_token, form.second_amount, form.second_token); + + Ok(HttpResponse::SeeOther() + .append_header(("Location", format!("/defi?success={}", urlencoding::encode(&success_message)))) + .finish()) + } + + // Process staking request + pub async fn create_staking(_tmpl: web::Data, form: web::Form) -> Result { + println!("DEBUG: Processing staking request: {:?}", form); + + // In a real application, this would create a staking position in the database + // For now, we'll just redirect back to the DeFi dashboard with a success message + + let success_message = format!("Successfully staked {} {}", form.amount, form.asset_id); + + Ok(HttpResponse::SeeOther() + .append_header(("Location", format!("/defi?success={}", urlencoding::encode(&success_message)))) + .finish()) + } + + // Process token swap + pub async fn swap_tokens(_tmpl: web::Data, form: web::Form) -> Result { + println!("DEBUG: Processing token swap: {:?}", form); + + // In a real application, this would perform a token swap in the database + // For now, we'll just redirect back to the DeFi dashboard with a success message + + let success_message = format!("Successfully swapped {} {} to {}", + form.from_amount, form.from_token, form.to_token); + + Ok(HttpResponse::SeeOther() + .append_header(("Location", format!("/defi?success={}", urlencoding::encode(&success_message)))) + .finish()) + } + + // Process collateral position creation + pub async fn create_collateral(_tmpl: web::Data, form: web::Form) -> Result { + println!("DEBUG: Processing collateral creation: {:?}", form); + + // In a real application, this would create a collateral position in the database + // For now, we'll just redirect back to the DeFi dashboard with a success message + + let purpose_str = match form.purpose.as_str() { + "loan" => "secure a loan", + "synthetic" => "generate synthetic assets", + "leverage" => "leverage trading", + _ => "collateralization", + }; + + let success_message = format!("Successfully collateralized {} {} for {}", + form.amount, form.asset_id, purpose_str); + + Ok(HttpResponse::SeeOther() + .append_header(("Location", format!("/defi?success={}", urlencoding::encode(&success_message)))) + .finish()) + } + + // Helper method to get DeFi statistics + fn get_defi_stats() -> serde_json::Map { + let mut stats = serde_json::Map::new(); + + // Handle Option by unwrapping with expect + stats.insert("total_value_locked".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(1250000.0).expect("Valid float"))); + stats.insert("lending_volume".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(450000.0).expect("Valid float"))); + stats.insert("borrowing_volume".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(320000.0).expect("Valid float"))); + stats.insert("liquidity_pools_count".to_string(), serde_json::Value::Number(serde_json::Number::from(12))); + stats.insert("active_stakers".to_string(), serde_json::Value::Number(serde_json::Number::from(156))); + stats.insert("total_swap_volume".to_string(), serde_json::Value::Number(serde_json::Number::from_f64(780000.0).expect("Valid float"))); + + stats + } + + // Helper method to convert Asset to a JSON object for templates + fn asset_to_json(asset: &Asset) -> serde_json::Map { + let mut map = serde_json::Map::new(); + + map.insert("id".to_string(), serde_json::Value::String(asset.id.clone())); + map.insert("name".to_string(), serde_json::Value::String(asset.name.clone())); + map.insert("description".to_string(), serde_json::Value::String(asset.description.clone())); + map.insert("asset_type".to_string(), serde_json::Value::String(asset.asset_type.as_str().to_string())); + map.insert("status".to_string(), serde_json::Value::String(asset.status.as_str().to_string())); + + // Add current valuation + if let Some(latest) = asset.latest_valuation() { + if let Some(num) = serde_json::Number::from_f64(latest.value) { + map.insert("current_valuation".to_string(), serde_json::Value::Number(num)); + } else { + map.insert("current_valuation".to_string(), serde_json::Value::Number(serde_json::Number::from(0))); + } + map.insert("valuation_currency".to_string(), serde_json::Value::String(latest.currency.clone())); + map.insert("valuation_date".to_string(), serde_json::Value::String(latest.date.format("%Y-%m-%d").to_string())); + } else { + map.insert("current_valuation".to_string(), serde_json::Value::Number(serde_json::Number::from(0))); + map.insert("valuation_currency".to_string(), serde_json::Value::String("USD".to_string())); + map.insert("valuation_date".to_string(), serde_json::Value::String("N/A".to_string())); + } + + map + } + + // Generate mock assets for testing + fn get_mock_assets() -> Vec { + // Reuse the asset controller's mock data function + crate::controllers::asset::AssetController::get_mock_assets() + } +} diff --git a/actix_mvc_app/src/controllers/mod.rs b/actix_mvc_app/src/controllers/mod.rs index 18054d0..e400af3 100644 --- a/actix_mvc_app/src/controllers/mod.rs +++ b/actix_mvc_app/src/controllers/mod.rs @@ -7,6 +7,7 @@ pub mod governance; pub mod flow; pub mod contract; pub mod asset; +pub mod defi; pub mod marketplace; // Re-export controllers for easier imports diff --git a/actix_mvc_app/src/main.rs b/actix_mvc_app/src/main.rs index a8bc923..b129b76 100644 --- a/actix_mvc_app/src/main.rs +++ b/actix_mvc_app/src/main.rs @@ -16,6 +16,7 @@ mod utils; // Import middleware components use middleware::{RequestTimer, SecurityHeaders, JwtAuth}; use utils::redis_service; +use models::initialize_mock_data; // Initialize lazy_static for in-memory storage extern crate lazy_static; @@ -72,6 +73,10 @@ async fn main() -> io::Result<()> { log::info!("Redis client initialized successfully"); } + // Initialize mock data for DeFi operations + initialize_mock_data(); + log::info!("DeFi mock data initialized successfully"); + log::info!("Starting server at http://{}", bind_address); // Create and configure the HTTP server diff --git a/actix_mvc_app/src/models/defi.rs b/actix_mvc_app/src/models/defi.rs new file mode 100644 index 0000000..c6c1b9f --- /dev/null +++ b/actix_mvc_app/src/models/defi.rs @@ -0,0 +1,206 @@ +use chrono::{DateTime, Utc}; +use serde::{Serialize, Deserialize}; +use std::sync::{Arc, Mutex}; +use std::collections::HashMap; +use lazy_static::lazy_static; +use uuid::Uuid; + +// DeFi position status +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub enum DefiPositionStatus { + Active, + Completed, + Liquidated, + Cancelled +} + +impl DefiPositionStatus { + pub fn as_str(&self) -> &str { + match self { + DefiPositionStatus::Active => "Active", + DefiPositionStatus::Completed => "Completed", + DefiPositionStatus::Liquidated => "Liquidated", + DefiPositionStatus::Cancelled => "Cancelled", + } + } +} + +// DeFi position type +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +pub enum DefiPositionType { + Lending, + Borrowing, + Liquidity, + Staking, + Collateral, +} + +impl DefiPositionType { + pub fn as_str(&self) -> &str { + match self { + DefiPositionType::Lending => "Lending", + DefiPositionType::Borrowing => "Borrowing", + DefiPositionType::Liquidity => "Liquidity", + DefiPositionType::Staking => "Staking", + DefiPositionType::Collateral => "Collateral", + } + } +} + +// Base DeFi position +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DefiPosition { + pub id: String, + pub position_type: DefiPositionType, + pub status: DefiPositionStatus, + pub asset_id: String, + pub asset_name: String, + pub asset_symbol: String, + pub amount: f64, + pub value_usd: f64, + pub apy: f64, + pub created_at: DateTime, + pub expires_at: Option>, + pub user_id: String, +} + +// Lending position +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LendingPosition { + pub base: DefiPosition, + pub duration_days: i32, + pub interest_earned: f64, + pub return_amount: f64, +} + +// Borrowing position +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BorrowingPosition { + pub base: DefiPosition, + pub collateral_asset_id: String, + pub collateral_asset_name: String, + pub collateral_asset_symbol: String, + pub collateral_amount: f64, + pub collateral_value_usd: f64, + pub duration_days: i32, + pub interest_rate: f64, + pub interest_owed: f64, + pub total_to_repay: f64, + pub collateral_ratio: f64, +} + +// In-memory database for DeFi positions +pub struct DefiDatabase { + lending_positions: HashMap, + borrowing_positions: HashMap, +} + +impl DefiDatabase { + pub fn new() -> Self { + Self { + lending_positions: HashMap::new(), + borrowing_positions: HashMap::new(), + } + } + + // Lending operations + pub fn add_lending_position(&mut self, position: LendingPosition) { + self.lending_positions.insert(position.base.id.clone(), position); + } + + pub fn get_lending_position(&self, id: &str) -> Option<&LendingPosition> { + self.lending_positions.get(id) + } + + pub fn get_all_lending_positions(&self) -> Vec<&LendingPosition> { + self.lending_positions.values().collect() + } + + pub fn get_user_lending_positions(&self, user_id: &str) -> Vec<&LendingPosition> { + self.lending_positions + .values() + .filter(|p| p.base.user_id == user_id) + .collect() + } + + // Borrowing operations + pub fn add_borrowing_position(&mut self, position: BorrowingPosition) { + self.borrowing_positions.insert(position.base.id.clone(), position); + } + + pub fn get_borrowing_position(&self, id: &str) -> Option<&BorrowingPosition> { + self.borrowing_positions.get(id) + } + + pub fn get_all_borrowing_positions(&self) -> Vec<&BorrowingPosition> { + self.borrowing_positions.values().collect() + } + + pub fn get_user_borrowing_positions(&self, user_id: &str) -> Vec<&BorrowingPosition> { + self.borrowing_positions + .values() + .filter(|p| p.base.user_id == user_id) + .collect() + } +} + +// Global instance of the DeFi database +lazy_static! { + pub static ref DEFI_DB: Arc> = Arc::new(Mutex::new(DefiDatabase::new())); +} + +// Initialize the database with mock data +pub fn initialize_mock_data() { + let mut db = DEFI_DB.lock().unwrap(); + + // Add mock lending positions + let lending_position = LendingPosition { + base: DefiPosition { + id: Uuid::new_v4().to_string(), + position_type: DefiPositionType::Lending, + status: DefiPositionStatus::Active, + asset_id: "TFT".to_string(), + asset_name: "ThreeFold Token".to_string(), + asset_symbol: "TFT".to_string(), + amount: 1000.0, + value_usd: 500.0, + apy: 4.2, + created_at: Utc::now(), + expires_at: Some(Utc::now() + chrono::Duration::days(30)), + user_id: "user123".to_string(), + }, + duration_days: 30, + interest_earned: 3.5, + return_amount: 1003.5, + }; + db.add_lending_position(lending_position); + + // Add mock borrowing positions + let borrowing_position = BorrowingPosition { + base: DefiPosition { + id: Uuid::new_v4().to_string(), + position_type: DefiPositionType::Borrowing, + status: DefiPositionStatus::Active, + asset_id: "ZAZ".to_string(), + asset_name: "Zanzibar Token".to_string(), + asset_symbol: "ZAZ".to_string(), + amount: 500.0, + value_usd: 250.0, + apy: 5.8, + created_at: Utc::now(), + expires_at: Some(Utc::now() + chrono::Duration::days(90)), + user_id: "user123".to_string(), + }, + collateral_asset_id: "TFT".to_string(), + collateral_asset_name: "ThreeFold Token".to_string(), + collateral_asset_symbol: "TFT".to_string(), + collateral_amount: 1500.0, + collateral_value_usd: 750.0, + duration_days: 90, + interest_rate: 5.8, + interest_owed: 3.625, + total_to_repay: 503.625, + collateral_ratio: 300.0, + }; + db.add_borrowing_position(borrowing_position); +} diff --git a/actix_mvc_app/src/models/mod.rs b/actix_mvc_app/src/models/mod.rs index 8d7fff0..b32c1c0 100644 --- a/actix_mvc_app/src/models/mod.rs +++ b/actix_mvc_app/src/models/mod.rs @@ -7,9 +7,11 @@ pub mod flow; pub mod contract; pub mod asset; pub mod marketplace; +pub mod defi; // Re-export models for easier imports pub use user::User; pub use ticket::{Ticket, TicketComment, TicketStatus, TicketPriority}; pub use calendar::{CalendarEvent, CalendarViewMode}; pub use marketplace::{Listing, ListingStatus, ListingType, Bid, BidStatus, MarketplaceStatistics}; +pub use defi::{DefiPosition, DefiPositionType, DefiPositionStatus, LendingPosition, BorrowingPosition, DEFI_DB, initialize_mock_data}; diff --git a/actix_mvc_app/src/routes/mod.rs b/actix_mvc_app/src/routes/mod.rs index 10981da..2df0d7a 100644 --- a/actix_mvc_app/src/routes/mod.rs +++ b/actix_mvc_app/src/routes/mod.rs @@ -9,6 +9,7 @@ use crate::controllers::flow::FlowController; use crate::controllers::contract::ContractController; use crate::controllers::asset::AssetController; use crate::controllers::marketplace::MarketplaceController; +use crate::controllers::defi::DefiController; use crate::middleware::JwtAuth; use crate::SESSION_KEY; @@ -120,6 +121,18 @@ pub fn configure_routes(cfg: &mut web::ServiceConfig) { .route("/{id}/purchase", web::post().to(MarketplaceController::purchase_listing)) .route("/{id}/cancel", web::post().to(MarketplaceController::cancel_listing)) ) + + // DeFi routes + .service( + web::scope("/defi") + .route("", web::get().to(DefiController::index)) + .route("/lending", web::post().to(DefiController::create_lending)) + .route("/borrowing", web::post().to(DefiController::create_borrowing)) + .route("/liquidity", web::post().to(DefiController::add_liquidity)) + .route("/staking", web::post().to(DefiController::create_staking)) + .route("/swap", web::post().to(DefiController::swap_tokens)) + .route("/collateral", web::post().to(DefiController::create_collateral)) + ) ); // Keep the /protected scope for any future routes that should be under that path diff --git a/actix_mvc_app/src/views/assets/index.html b/actix_mvc_app/src/views/assets/index.html index 8fcbe01..004519d 100644 --- a/actix_mvc_app/src/views/assets/index.html +++ b/actix_mvc_app/src/views/assets/index.html @@ -62,1511 +62,6 @@ - -
-
- - DeFi Platform -
-
- - -
- -
-
-

Welcome to the ZAZ DeFi Platform!

-

Our decentralized finance platform allows you to maximize the value of your digital assets through various financial services.

-
-

Use the tabs above to explore lending, borrowing, liquidity pools, staking, swapping, and collateralization features.

-
-
- - -
-
-
-
-
- Lend Your Assets -
-
-

Earn interest by lending your digital assets to the ZAZ DeFi platform.

- -
-
- - -
- -
- -
- - TFT -
-
- -
- - -
- -
-
- Estimated Interest: - 0.00 TFT -
-
- Return Amount: - 0.00 TFT -
-
- -
- -
-
-
-
-
- -
-
-
- Borrow Against Assets -
-
-

Borrow digital assets using your existing assets as collateral.

- -
-
- - -
- -
- - -
- -
- -
- - TFT -
-
You can borrow up to 70% of your collateral value.
-
- -
- - -
- -
-
- Collateral Ratio: - 0% -
-
- Interest Due: - 0.00 TFT -
-
- Total Repayment: - 0.00 TFT -
-
-
-
-
- -
- -
-
-
-
-
-
- - -
-
- Your Active Positions -
-
- - -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AssetAmountInterest RateStart DateEnd DateEarned InterestStatusActions
ThreeFold Token (TFT)1,000 TFT4.2% APY2025-04-012025-05-013.5 TFTActive - -
Zanzibar Token (ZAZ)500 ZAZ6.8% APY2025-03-152025-06-158.5 ZAZActive - -
-
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
Borrowed AssetAmountCollateralCollateral RatioInterest RateStart DateDue DateActions
ThreeFold Token (TFT)500 TFTBeach Property NFT -
-
-
-
- 65% -
-
5.2% APR2025-04-102025-05-10 - -
-
-
-
-
-
-
- - -
-
-
-
-
About Liquidity Pools
-

Liquidity pools are collections of tokens locked in smart contracts that provide liquidity for decentralized trading. By adding your assets to a liquidity pool, you earn a share of the trading fees generated by the pool.

-
-
-
- - -
-
-
-
- Available Liquidity Pools -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PoolTotal Liquidity24h VolumeAPYYour LiquidityYour ShareActions
-
-
- TFT - ZAZ -
- TFT-ZAZ -
-
$1,250,000$45,00012.5%$2,5000.2% -
- - -
-
-
-
- TFT - USDT -
- TFT-USDT -
-
$3,750,000$125,0008.2%$00% -
- - -
-
-
-
- ZAZ - USDT -
- ZAZ-USDT -
-
$850,000$32,00015.8%$5,0000.59% -
- - -
-
-
-
- BTC - USDT -
- BTC-USDT -
-
$5,250,000$450,0006.5%$00% -
- - -
-
-
-
- ETH - USDT -
- ETH-USDT -
-
$4,100,000$320,0007.2%$00% -
- - -
-
-
-
-
-
-
- - -
-
-
-
- Your Liquidity Positions -
-
-
- -
-
-
-
-
- TFT - ZAZ -
- TFT-ZAZ -
-
-
-
- Your Liquidity: - $2,500 -
-
- Pool Share: - 0.2% -
-
- TFT: - 500 TFT -
-
- ZAZ: - 1,250 ZAZ -
-
- Earned Fees: - $45.20 -
-
- APY: - 12.5% -
-
- - - -
-
-
-
- - -
-
-
-
-
- ZAZ - USDT -
- ZAZ-USDT -
-
-
-
- Your Liquidity: - $5,000 -
-
- Pool Share: - 0.59% -
-
- ZAZ: - 2,500 ZAZ -
-
- USDT: - 2,500 USDT -
-
- Earned Fees: - $128.75 -
-
- APY: - 15.8% -
-
- - - -
-
-
-
-
-
-
-
-
- - -
-
-
-
- Create New Liquidity Pool -
-
-
-
-
-
- - -
-
- -
- - TFT -
-
-
-
-
- - -
-
- -
- - ZAZ -
-
-
-
-
- -
- 1 - TFT - = - - ZAZ -
-
-
- - -
This fee is charged on each trade and distributed to liquidity providers.
-
-
- -
-
-
-
-
-
-
- - -
-
-
-
-
About Swapping
-

Swap allows you to exchange one token for another at the current market rate. Swaps are executed through liquidity pools with a small fee that goes to liquidity providers.

-
-
-
- -
-
- -
-
- Swap Tokens -
-
- -
- - -
- - -
- -
- - -
- -
-
- -
- Balance: 5,000 ZAZ - ≈ $2,500.00 -
-
-
-
- - -
-
-
- Exchange Rate: - 1 TFT = 0.5 ZAZ -
-
- Minimum Received: - 0 ZAZ -
-
- Price Impact: - < 0.1% -
-
- Liquidity Provider Fee: - 0.3% -
-
-
- - -
- -
-
-
-
- -
- -
-
- Recent Swaps -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TimeFromToValue
2025-04-15 14:32 -
- TFT - 500 TFT -
-
-
- ZAZ - 250 ZAZ -
-
$250.00
2025-04-14 09:17 -
- USDT - 1,000 USDT -
-
-
- TFT - 2,000 TFT -
-
$1,000.00
2025-04-12 16:45 -
- ZAZ - 100 ZAZ -
-
-
- USDT - 50 USDT -
-
$50.00
-
-
-
- - -
-
- Market Rates -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PairRate24h ChangeVolume (24h)
-
-
- TFT - ZAZ -
- TFT/ZAZ -
-
0.5+2.3%$125,000
-
-
- TFT - USDT -
- TFT/USDT -
-
0.5-1.2%$250,000
-
-
- ZAZ - USDT -
- ZAZ/USDT -
-
0.5+3.7%$175,000
-
-
-
-
-
-
- - -
-
-
-
-
About Collateralization
-

Use your digital assets as collateral to secure loans or generate synthetic assets. Maintain a healthy collateral ratio to avoid liquidation.

-
-
-
- -
-
- -
-
- Collateralize Assets -
-
-
- -
- - -
- - -
- -
- - TFT -
-
- Available: 10,000 TFT ($5,000) -
-
- - -
- -
- $ - -
-
- - -
- - -
- - -
- - -
- - -
- -
- $ - - -
-
- Maximum Loan: $0.00 -
-
- - - - - - - - -
- -
- - - - -
-
- - -
- -
- $ - - per TFT -
-
- Your collateral will be liquidated if the price falls below this level. -
-
- - -
- -
-
-
-
-
- -
- -
-
- Your Active Collateral Positions -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AssetCollateral ValueBorrowed/GeneratedCollateral RatioLiquidation PriceStatusActions
-
- TFT - 2,000 TFT -
-
$1,000$700 (Loan) -
-
-
-
- 143% -
-
$0.35Healthy -
- - -
-
-
- - Beach Property NFT -
-
$25,00010,000 sUSD -
-
-
-
- 250% -
-
$10,000Warning -
- - -
-
-
- ZAZ - 1,000 ZAZ -
-
$5000.1 sBTC -
-
-
-
- 333% -
-
$0.15Healthy -
- - -
-
-
-
-
- - -
-
- Collateral Health -
-
-
-
Overall Collateral Health
-
-
60%
-
-
- Health score represents the overall safety of your collateral positions. Higher is better. -
-
- -
-
-
-
-
Total Collateral Value
-

$26,500

-
-
-
-
-
-
-
Total Borrowed/Generated
-

$11,150

-
-
-
-
- -
- Your Beach Property NFT collateral is close to the liquidation threshold. Consider adding more collateral or repaying part of your synthetic assets. -
-
-
-
-
-
- - -
-
-
-
-
About Staking
-

Staking allows you to lock your digital assets for a period of time to support network operations and earn rewards. The longer you stake, the higher rewards you can earn.

-
-
-
- - -
-
-
-
- Available Staking Options -
-
-
- -
-
-
-
- TFT -
ThreeFold Token (TFT)
-
-
-
-
- Total Staked: - 5,250,000 TFT -
-
- Your Stake: - 1,000 TFT -
-
- APY: - 8.5% -
- -
- - -
- -
- -
- - TFT -
-
- -
-
- Estimated Rewards: - 0 TFT -
-
- -
- -
-
-
-
- - -
-
-
-
- ZAZ -
Zanzibar Token (ZAZ)
-
-
-
-
- Total Staked: - 2,750,000 ZAZ -
-
- Your Stake: - 500 ZAZ -
-
- APY: - 12.0% -
- -
- - -
- -
- -
- - ZAZ -
-
- -
-
- Estimated Rewards: - 0 ZAZ -
-
- -
- -
-
-
-
- - -
-
-
-
- -
Digital Asset Staking
-
-
-
-

Stake your NFTs and other digital assets to earn passive income.

- -
- - -
- -
- - -
- -
-
- Estimated Rewards: - $0.00 -
-
- Reward Token: - ZAZ -
-
- -
- -
-
-
-
-
-
-
-
-
- - -
-
-
-
- Your Active Stakes -
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AssetAmountValueStart DateEnd DateAPYEarned RewardsStatusActions
-
- TFT - ThreeFold Token (TFT) -
-
1,000 TFT$5002025-03-152025-06-1510.2%22.5 TFTActive - -
-
- ZAZ - Zanzibar Token (ZAZ) -
-
500 ZAZ$2502025-04-012025-05-0112.0%5.0 ZAZActive - -
-
- - Beach Property NFT -
-
1 NFT$25,0002025-02-102026-02-1010.0%450 ZAZActive - -
-
-
-
-
-
-
-
-
-
-
diff --git a/actix_mvc_app/src/views/base.html b/actix_mvc_app/src/views/base.html index 9eeb986..57de939 100644 --- a/actix_mvc_app/src/views/base.html +++ b/actix_mvc_app/src/views/base.html @@ -150,6 +150,11 @@ Digital Assets +