From ddaed046dce69d1ce1d25c46de60010bab70fd01 Mon Sep 17 00:00:00 2001 From: kieran Date: Mon, 10 Mar 2025 15:09:50 +0000 Subject: [PATCH] feat: alt prices --- src/api/model.rs | 64 ++++++++++++++++++++++++++++++++++++++-------- src/api/routes.rs | 65 ++++++++++++++++++++++------------------------- src/exchange.rs | 20 ++++++++++++--- 3 files changed, 100 insertions(+), 49 deletions(-) diff --git a/src/api/model.rs b/src/api/model.rs index a2d554a..d7b6fa7 100644 --- a/src/api/model.rs +++ b/src/api/model.rs @@ -4,7 +4,10 @@ use crate::status::VmState; use anyhow::{anyhow, bail, Context, Result}; use chrono::{DateTime, Utc}; use ipnetwork::IpNetwork; -use lnvps_db::{LNVpsDb, Vm, VmCostPlan, VmCustomTemplate, VmHost, VmHostRegion, VmTemplate}; +use lnvps_db::{ + LNVpsDb, Vm, VmCostPlan, VmCustomPricing, VmCustomPricingDisk, VmCustomTemplate, VmHost, + VmHostRegion, VmTemplate, +}; use nostr::util::hex; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -141,16 +144,12 @@ impl ApiTemplatesResponse { let rates = rates.list_rates().await?; for mut template in &mut self.templates { - if let Some(list_price) = template.cost_plan.price.first() { - for alt_price in alt_prices( - &rates, - CurrencyAmount(list_price.currency, list_price.amount), - ) { - template.cost_plan.price.push(ApiPrice { - currency: alt_price.0, - amount: alt_price.1, - }); - } + let list_price = CurrencyAmount(template.cost_plan.currency, template.cost_plan.amount); + for alt_price in alt_prices(&rates, list_price) { + template.cost_plan.other_price.push(ApiPrice { + currency: alt_price.0, + amount: alt_price.1, + }); } } Ok(()) @@ -170,6 +169,40 @@ pub struct ApiCustomTemplateParams { pub disks: Vec, } +impl ApiCustomTemplateParams { + pub fn from( + pricing: &VmCustomPricing, + disks: &Vec, + region: &VmHostRegion, + max_cpu: u16, + max_memory: u64, + max_disk: u64, + ) -> Result { + const GB: u64 = 1024 * 1024 * 1024; + Ok(ApiCustomTemplateParams { + id: pricing.id, + name: pricing.name.clone(), + region: ApiVmHostRegion { + id: region.id, + name: region.name.clone(), + }, + max_cpu, + min_cpu: 1, + min_memory: GB, + max_memory, + min_disk: GB * 5, + max_disk, + disks: disks + .iter() + .filter(|d| d.pricing_id == pricing.id) + .map(|d| ApiCustomTemplateDiskParam { + disk_type: d.kind.into(), + disk_interface: d.interface.into(), + }) + .collect(), + }) + } +} #[derive(Clone, Serialize, Deserialize, JsonSchema)] pub struct ApiCustomTemplateDiskParam { pub disk_type: DiskType, @@ -215,6 +248,15 @@ pub struct ApiPrice { pub amount: f32, } +impl From for ApiPrice { + fn from(value: CurrencyAmount) -> Self { + Self { + currency: value.0, + amount: value.1, + } + } +} + #[derive(Serialize, Deserialize, JsonSchema)] pub struct ApiVmTemplate { pub id: u64, diff --git a/src/api/routes.rs b/src/api/routes.rs index 7c5d99d..4d4c4a2 100644 --- a/src/api/routes.rs +++ b/src/api/routes.rs @@ -1,9 +1,10 @@ use crate::api::model::{ - AccountPatchRequest, ApiPrice, ApiCustomTemplateDiskParam, ApiCustomTemplateParams, - ApiCustomVmOrder, ApiCustomVmRequest, ApiTemplatesResponse, ApiUserSshKey, ApiVmHostRegion, + AccountPatchRequest, ApiCustomTemplateDiskParam, ApiCustomTemplateParams, ApiCustomVmOrder, + ApiCustomVmRequest, ApiPrice, ApiTemplatesResponse, ApiUserSshKey, ApiVmHostRegion, ApiVmIpAssignment, ApiVmOsImage, ApiVmPayment, ApiVmStatus, ApiVmTemplate, CreateSshKey, CreateVmRequest, VMPatchRequest, }; +use crate::exchange::ExchangeRateService; use crate::host::{get_host_client, FullVmInfo, TimeSeries, TimeSeriesData}; use crate::nip98::Nip98Auth; use crate::provisioner::{HostCapacityService, LNVpsProvisioner, PricingEngine}; @@ -266,7 +267,10 @@ async fn v1_list_vm_images(db: &State>) -> ApiResult>) -> ApiResult { +async fn v1_list_vm_templates( + db: &State>, + rates: &State>, +) -> ApiResult { let hc = HostCapacityService::new((*db).clone()); let templates = hc.list_available_vm_templates().await?; @@ -322,49 +326,42 @@ async fn v1_list_vm_templates(db: &State>) -> ApiResult, source: CurrencyAmount) -> Vec { - // TODO: return all alt prices by cross-converting all currencies - rates + let mut ret: Vec = rates .iter() .filter_map(|r| r.convert(source).ok()) - .collect() + .collect(); + + let mut ret2 = vec![]; + for y in rates.iter() { + for x in ret.iter() { + if let Ok(r1) = y.convert(x.clone()) { + if r1.0 != source.0 { + ret2.push(r1); + } + } + } + } + ret.append(&mut ret2); + ret } #[derive(Clone, Default)]