sdk

Radroots SDK and bindings
git clone https://radroots.dev/git/sdk.git
Log | Files | Refs | README

commit 05c68dc8409efe6f552341a70bbe5fd10bedcd10
parent 2e11d8e70521579b908b500188f3cf3e208ec7e9
Author: triesap <tyson@radroots.org>
Date:   Wed, 24 Jun 2026 08:42:43 +0000

trade: render bindings from dto registry

Diffstat:
MCargo.lock | 5++++-
Mcrates/trade_bindings/Cargo.toml | 5+++--
Acrates/trade_bindings/src/dto.rs | 484+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/trade_bindings/src/lib.rs | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Dcrates/trade_bindings/src/model.rs | 750-------------------------------------------------------------------------------
Mpackages/trade-bindings/src/generated/types.ts | 30+++++++++---------------------
Mtools/xtask/src/dto_render.rs | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtools/xtask/src/dto_roots.rs | 133++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mtools/xtask/src/output.rs | 49+++++++++++++++++++++++++------------------------
9 files changed, 770 insertions(+), 821 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -2122,6 +2122,8 @@ name = "radroots_trade" version = "0.1.0-alpha.2" dependencies = [ "base64 0.22.1", + "dto_bindgen", + "dto_bindgen_core", "hex", "radroots_authority", "radroots_core", @@ -2138,7 +2140,8 @@ dependencies = [ name = "radroots_trade_bindings" version = "0.1.0" dependencies = [ - "radroots_sdk_binding_model", + "dto_bindgen", + "dto_bindgen_core", "radroots_trade", ] diff --git a/crates/trade_bindings/Cargo.toml b/crates/trade_bindings/Cargo.toml @@ -9,5 +9,6 @@ homepage.workspace = true publish = false [dependencies] -radroots_sdk_binding_model = { path = "../binding_model" } -radroots_trade = { workspace = true } +dto_bindgen = { workspace = true } +dto_bindgen_core = { workspace = true } +radroots_trade = { workspace = true, features = ["dto-bindgen"] } diff --git a/crates/trade_bindings/src/dto.rs b/crates/trade_bindings/src/dto.rs @@ -0,0 +1,484 @@ +use dto_bindgen_core::{ + BackendId, DescribeCtx, Dto, EnumDef, EnumRepr, FieldDef, IdentName, RootDescriptor, + RustTypeId, SourceSpan, TargetFieldNames, TargetOverride, TypeDef, TypeRef, VariantDef, + VariantShape, WireFieldNames, +}; +use radroots_trade::listing::model::RadrootsTradeListingTotal; + +pub fn dto_roots() -> Vec<RootDescriptor> { + let mut roots = radroots_trade::dto::dto_roots() + .into_iter() + .collect::<Vec<_>>(); + roots.extend([ + RootDescriptor::new::<RadrootsTradeFacetCount>(), + RootDescriptor::new::<RadrootsTradeListingBackofficeOverlay>(), + RootDescriptor::new::<RadrootsTradeListingBackofficeQuery>(), + RootDescriptor::new::<RadrootsTradeListingBackofficeView>(), + RootDescriptor::new::<RadrootsTradeListingBinProjection>(), + RootDescriptor::new::<RadrootsTradeListingFacets>(), + RootDescriptor::new::<RadrootsTradeListingMarketStatus>(), + RootDescriptor::new::<RadrootsTradeListingProjection>(), + RootDescriptor::new::<RadrootsTradeListingQuery>(), + RootDescriptor::new::<RadrootsTradeListingSort>(), + RootDescriptor::new::<RadrootsTradeListingSortField>(), + RootDescriptor::new::<RadrootsTradeMarketplaceListingSummary>(), + RootDescriptor::new::<RadrootsTradeMarketplaceOrderSummary>(), + RootDescriptor::new::<RadrootsTradeModerationFlag>(), + RootDescriptor::new::<RadrootsTradeModerationSeverity>(), + RootDescriptor::new::<RadrootsTradeModerationStatus>(), + RootDescriptor::new::<RadrootsTradeOrderBackofficeOverlay>(), + RootDescriptor::new::<RadrootsTradeOrderBackofficeQuery>(), + RootDescriptor::new::<RadrootsTradeOrderBackofficeView>(), + RootDescriptor::new::<RadrootsTradeOrderFacets>(), + RootDescriptor::new::<RadrootsTradeOrderQuery>(), + RootDescriptor::new::<RadrootsTradeOrderSort>(), + RootDescriptor::new::<RadrootsTradeOrderSortField>(), + RootDescriptor::new::<RadrootsTradeOrderWorkflowMessage>(), + RootDescriptor::new::<RadrootsTradeOrderWorkflowProjection>(), + RootDescriptor::new::<RadrootsTradeReviewPriority>(), + RootDescriptor::new::<RadrootsTradeReviewQueueEntry>(), + RootDescriptor::new::<RadrootsTradeReviewStatus>(), + RootDescriptor::new::<RadrootsTradeSortDirection>(), + ]); + roots +} + +macro_rules! imported_ts_type { + ($ty:ident, $target:literal) => { + pub struct $ty; + + impl Dto for $ty { + fn describe(_ctx: &mut DescribeCtx) -> TypeRef { + TypeRef::Override(TargetOverride::new(BackendId::TypeScript, $target)) + } + } + }; +} + +imported_ts_type!(RadrootsCoreDecimalImport, "RadrootsCoreDecimal"); +imported_ts_type!(RadrootsCoreDiscountImport, "RadrootsCoreDiscount"); +imported_ts_type!(RadrootsCoreDiscountValueImport, "RadrootsCoreDiscountValue"); +imported_ts_type!(RadrootsCoreMoneyImport, "RadrootsCoreMoney"); +imported_ts_type!(RadrootsCoreQuantityImport, "RadrootsCoreQuantity"); +imported_ts_type!(RadrootsCoreQuantityPriceImport, "RadrootsCoreQuantityPrice"); +imported_ts_type!(RadrootsCoreUnitImport, "RadrootsCoreUnit"); +imported_ts_type!(RadrootsFarmRefImport, "RadrootsFarmRef"); +imported_ts_type!(RadrootsListingImport, "RadrootsListing"); +imported_ts_type!( + RadrootsListingAvailabilityImport, + "RadrootsListingAvailability" +); +imported_ts_type!(RadrootsListingBinImport, "RadrootsListingBin"); +imported_ts_type!( + RadrootsListingDeliveryMethodImport, + "RadrootsListingDeliveryMethod" +); +imported_ts_type!(RadrootsListingImageImport, "RadrootsListingImage"); +imported_ts_type!(RadrootsListingLocationImport, "RadrootsListingLocation"); +imported_ts_type!(RadrootsListingProductImport, "RadrootsListingProduct"); +imported_ts_type!(RadrootsNostrEventPtrImport, "RadrootsNostrEventPtr"); +imported_ts_type!(RadrootsPlotRefImport, "RadrootsPlotRef"); +imported_ts_type!(RadrootsResourceAreaRefImport, "RadrootsResourceAreaRef"); +imported_ts_type!( + RadrootsTradeMessagePayloadImport, + "RadrootsTradeMessagePayload" +); +imported_ts_type!(RadrootsTradeMessageTypeImport, "RadrootsTradeMessageType"); +imported_ts_type!( + RadrootsTradeOrderEconomicLineImport, + "RadrootsTradeOrderEconomicLine" +); +imported_ts_type!(RadrootsTradeOrderItemImport, "RadrootsTradeOrderItem"); +imported_ts_type!(RadrootsTradeOrderStatusImport, "RadrootsTradeOrderStatus"); + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeFacetCount { + pub key: String, + pub count: u32, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeListingBackofficeOverlay { + pub listing_addr: String, + pub review_queue: Option<RadrootsTradeReviewQueueEntry>, + pub moderation_flags: Vec<RadrootsTradeModerationFlag>, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeListingBackofficeQuery { + pub listing: RadrootsTradeListingQuery, + pub requires_review: Option<bool>, + pub has_open_moderation_flags: Option<bool>, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeListingBackofficeView { + pub listing: RadrootsTradeListingProjection, + pub marketplace: Option<RadrootsTradeMarketplaceListingSummary>, + pub overlay: Option<RadrootsTradeListingBackofficeOverlay>, + pub requires_review: bool, + pub open_moderation_flag_count: u32, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeListingBinProjection { + pub bin: RadrootsListingBinImport, + pub one_bin_total: RadrootsTradeListingTotal, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeListingFacets { + pub seller_pubkeys: Vec<RadrootsTradeFacetCount>, + pub farm_pubkeys: Vec<RadrootsTradeFacetCount>, + pub farm_ids: Vec<RadrootsTradeFacetCount>, + pub product_keys: Vec<RadrootsTradeFacetCount>, + pub product_categories: Vec<RadrootsTradeFacetCount>, + pub listing_statuses: Vec<RadrootsTradeFacetCount>, +} + +pub enum RadrootsTradeListingMarketStatus { + Unknown, + Window, + Active, + Sold, + Other { value: String }, +} + +impl Dto for RadrootsTradeListingMarketStatus { + fn describe(ctx: &mut DescribeCtx) -> TypeRef { + let def = EnumDef::new( + "RadrootsTradeListingMarketStatus", + "RadrootsTradeListingMarketStatus", + EnumRepr::External, + span("crates/trade_bindings/src/dto.rs", 140), + ) + .with_variant(unit_variant( + "Unknown", + "unknown", + "crates/trade_bindings/src/dto.rs", + 141, + )) + .with_variant(unit_variant( + "Window", + "window", + "crates/trade_bindings/src/dto.rs", + 142, + )) + .with_variant(unit_variant( + "Active", + "active", + "crates/trade_bindings/src/dto.rs", + 143, + )) + .with_variant(unit_variant( + "Sold", + "sold", + "crates/trade_bindings/src/dto.rs", + 144, + )) + .with_variant(VariantDef::new( + "Other", + "other", + VariantShape::Struct(vec![field( + "value", + "value", + String::describe(ctx), + "crates/trade_bindings/src/dto.rs", + 145, + )]), + span("crates/trade_bindings/src/dto.rs", 145), + )); + register(ctx, "RadrootsTradeListingMarketStatus", TypeDef::Enum(def)) + } +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeListingProjection { + pub listing_addr: String, + pub seller_pubkey: String, + pub listing_id: String, + pub farm: RadrootsFarmRefImport, + pub product: RadrootsListingProductImport, + pub primary_bin_id: String, + pub bins: Vec<RadrootsTradeListingBinProjection>, + pub resource_area: Option<RadrootsResourceAreaRefImport>, + pub plot: Option<RadrootsPlotRefImport>, + pub discounts: Option<Vec<RadrootsCoreDiscountImport>>, + pub inventory_available: Option<RadrootsCoreDecimalImport>, + pub availability: Option<RadrootsListingAvailabilityImport>, + pub delivery_method: Option<RadrootsListingDeliveryMethodImport>, + pub location: Option<RadrootsListingLocationImport>, + pub images: Option<Vec<RadrootsListingImageImport>>, + pub order_count: u32, + pub open_order_count: u32, + pub terminal_order_count: u32, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeListingQuery { + pub seller_pubkey: Option<String>, + pub farm_pubkey: Option<String>, + pub farm_id: Option<String>, + pub product_key: Option<String>, + pub product_category: Option<String>, + pub listing_status: Option<RadrootsTradeListingMarketStatus>, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeListingSort { + pub field: RadrootsTradeListingSortField, + pub direction: RadrootsTradeSortDirection, +} + +#[derive(dto_bindgen::Dto)] +pub enum RadrootsTradeListingSortField { + #[serde(rename = "listing_addr")] + ListingAddr, + #[serde(rename = "product_title")] + ProductTitle, + #[serde(rename = "product_category")] + ProductCategory, + #[serde(rename = "seller_pubkey")] + SellerPubkey, + #[serde(rename = "inventory_available")] + InventoryAvailable, + #[serde(rename = "open_order_count")] + OpenOrderCount, + #[serde(rename = "total_order_count")] + TotalOrderCount, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeMarketplaceListingSummary { + pub listing_addr: String, + pub seller_pubkey: String, + pub farm_pubkey: String, + pub farm_id: String, + pub product_key: String, + pub product_title: String, + pub product_category: String, + pub product_summary: Option<String>, + pub listing_status: RadrootsTradeListingMarketStatus, + pub location_primary: Option<String>, + pub inventory_available: Option<RadrootsCoreDecimalImport>, + pub primary_bin_id: String, + pub primary_bin_label: Option<String>, + pub primary_bin_total: RadrootsTradeListingTotal, + pub order_count: u32, + pub open_order_count: u32, + pub terminal_order_count: u32, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeMarketplaceOrderSummary { + pub order_id: String, + pub listing_addr: String, + pub buyer_pubkey: String, + pub seller_pubkey: String, + pub status: RadrootsTradeOrderStatusImport, + pub last_message_type: RadrootsTradeMessageTypeImport, + pub item_count: u32, + pub total_bin_count: u32, + pub has_requested_discounts: bool, + pub last_reason: Option<String>, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeModerationFlag { + pub code: String, + pub severity: RadrootsTradeModerationSeverity, + pub status: RadrootsTradeModerationStatus, + pub source: Option<String>, + pub reason: Option<String>, +} + +#[derive(dto_bindgen::Dto)] +pub enum RadrootsTradeModerationSeverity { + #[serde(rename = "notice")] + Notice, + #[serde(rename = "warning")] + Warning, + #[serde(rename = "block")] + Block, +} + +#[derive(dto_bindgen::Dto)] +pub enum RadrootsTradeModerationStatus { + #[serde(rename = "open")] + Open, + #[serde(rename = "snoozed")] + Snoozed, + #[serde(rename = "resolved")] + Resolved, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeOrderBackofficeOverlay { + pub order_id: String, + pub review_queue: Option<RadrootsTradeReviewQueueEntry>, + pub moderation_flags: Vec<RadrootsTradeModerationFlag>, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeOrderBackofficeQuery { + pub order: RadrootsTradeOrderQuery, + pub requires_review: Option<bool>, + pub has_open_moderation_flags: Option<bool>, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeOrderBackofficeView { + pub order: RadrootsTradeOrderWorkflowProjection, + pub marketplace: RadrootsTradeMarketplaceOrderSummary, + pub overlay: Option<RadrootsTradeOrderBackofficeOverlay>, + pub requires_review: bool, + pub open_moderation_flag_count: u32, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeOrderFacets { + pub buyer_pubkeys: Vec<RadrootsTradeFacetCount>, + pub seller_pubkeys: Vec<RadrootsTradeFacetCount>, + pub listing_addrs: Vec<RadrootsTradeFacetCount>, + pub statuses: Vec<RadrootsTradeFacetCount>, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeOrderQuery { + pub listing_addr: Option<String>, + pub buyer_pubkey: Option<String>, + pub seller_pubkey: Option<String>, + pub status: Option<RadrootsTradeOrderStatusImport>, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeOrderSort { + pub field: RadrootsTradeOrderSortField, + pub direction: RadrootsTradeSortDirection, +} + +#[derive(dto_bindgen::Dto)] +pub enum RadrootsTradeOrderSortField { + #[serde(rename = "order_id")] + OrderId, + #[serde(rename = "listing_addr")] + ListingAddr, + #[serde(rename = "buyer_pubkey")] + BuyerPubkey, + #[serde(rename = "seller_pubkey")] + SellerPubkey, + #[serde(rename = "status")] + Status, + #[serde(rename = "last_message_type")] + LastMessageType, + #[serde(rename = "total_bin_count")] + TotalBinCount, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeOrderWorkflowMessage { + pub event_id: String, + pub actor_pubkey: String, + pub counterparty_pubkey: String, + pub listing_addr: String, + pub order_id: Option<String>, + pub listing_event: Option<RadrootsNostrEventPtrImport>, + pub root_event_id: Option<String>, + pub prev_event_id: Option<String>, + pub payload: RadrootsTradeMessagePayloadImport, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeOrderWorkflowProjection { + pub order_id: String, + pub listing_addr: String, + pub buyer_pubkey: String, + pub seller_pubkey: String, + pub items: Vec<RadrootsTradeOrderItemImport>, + pub requested_discounts: Option<Vec<RadrootsTradeOrderEconomicLineImport>>, + pub status: RadrootsTradeOrderStatusImport, + pub listing_snapshot: Option<RadrootsNostrEventPtrImport>, + pub root_event_id: String, + pub last_event_id: String, + pub last_discount_request: Option<RadrootsCoreDiscountValueImport>, + pub last_discount_offer: Option<RadrootsCoreDiscountValueImport>, + pub accepted_discount: Option<RadrootsCoreDiscountValueImport>, + pub last_reason: Option<String>, + pub last_discount_decline_reason: Option<String>, + pub question_count: u32, + pub answer_count: u32, + pub revision_count: u32, + pub discount_request_count: u32, + pub discount_offer_count: u32, + pub discount_accept_count: u32, + pub discount_decline_count: u32, + pub cancellation_count: u32, + pub last_message_type: RadrootsTradeMessageTypeImport, + pub last_actor_pubkey: String, +} + +#[derive(dto_bindgen::Dto)] +pub enum RadrootsTradeReviewPriority { + #[serde(rename = "low")] + Low, + #[serde(rename = "normal")] + Normal, + #[serde(rename = "high")] + High, + #[serde(rename = "critical")] + Critical, +} + +#[derive(dto_bindgen::Dto)] +pub struct RadrootsTradeReviewQueueEntry { + pub queue: String, + pub priority: RadrootsTradeReviewPriority, + pub status: RadrootsTradeReviewStatus, + pub assigned_operator: Option<String>, + pub reason: Option<String>, +} + +#[derive(dto_bindgen::Dto)] +pub enum RadrootsTradeReviewStatus { + #[serde(rename = "queued")] + Queued, + #[serde(rename = "in_progress")] + InProgress, + #[serde(rename = "blocked")] + Blocked, + #[serde(rename = "resolved")] + Resolved, +} + +#[derive(dto_bindgen::Dto)] +pub enum RadrootsTradeSortDirection { + #[serde(rename = "asc")] + Asc, + #[serde(rename = "desc")] + Desc, +} + +fn register(ctx: &mut DescribeCtx, rust_ident: &str, type_def: TypeDef) -> TypeRef { + ctx.register_type( + RustTypeId::new("radroots_trade_bindings", rust_ident), + type_def, + ) +} + +fn unit_variant(rust_name: &str, wire_name: &str, file: &str, line: u32) -> VariantDef { + VariantDef::new(rust_name, wire_name, VariantShape::Unit, span(file, line)) +} + +fn field(rust_name: &str, wire_name: &str, ty: TypeRef, file: &str, line: u32) -> FieldDef { + FieldDef::new( + IdentName::new(rust_name), + WireFieldNames::same(wire_name), + TargetFieldNames::new(wire_name, rust_name), + ty, + span(file, line), + ) +} + +fn span(file: &str, line: u32) -> SourceSpan { + SourceSpan::new(file, line, 1) +} diff --git a/crates/trade_bindings/src/lib.rs b/crates/trade_bindings/src/lib.rs @@ -1,8 +1,8 @@ pub use radroots_trade as upstream; -mod model; +pub mod dto; -pub use model::types_module; +pub use dto::dto_roots; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TradeTypeDisposition { @@ -152,29 +152,74 @@ const fn json_number_safe_count( #[cfg(test)] mod tests { use super::{ - TRADE_LARGE_INTEGER_POLICIES, TRADE_TYPE_INVENTORY, TradeTypeDisposition, types_module, + TRADE_LARGE_INTEGER_POLICIES, TRADE_TYPE_INVENTORY, TradeTypeDisposition, dto_roots, }; - const TRADE_BINDINGS_TYPES_TS: &str = - include_str!("../../../packages/trade-bindings/src/generated/types.ts"); - #[test] - fn preserves_trade_type_exports() { - let rendered = types_module().render(); - assert!(rendered.contains("export type RadrootsTradeListingTotal")); - assert!(rendered.contains("export type RadrootsTradeOrderWorkflowProjection")); - assert!(rendered.contains("export type RadrootsTradeMarketplaceOrderSummary")); + fn trade_dto_roots_build_registry() { + let registry = dto_bindgen_core::build_registry(dto_roots()); + + assert!( + !registry.has_errors(), + "trade binding registry has diagnostics: {:?}", + registry.diagnostics + ); } #[test] - fn trade_type_inventory_matches_current_package_surface() { - let actual = type_inventory(TRADE_BINDINGS_TYPES_TS); + fn trade_type_inventory_is_deterministic() { let expected = TRADE_TYPE_INVENTORY .iter() .map(|entry| entry.export_name) .collect::<Vec<_>>(); - assert_eq!(actual, expected); + assert_eq!( + expected, + [ + "RadrootsFarmRef", + "RadrootsListing", + "RadrootsListingAvailability", + "RadrootsListingBin", + "RadrootsListingDeliveryMethod", + "RadrootsListingLocation", + "RadrootsListingProduct", + "RadrootsListingStatus", + "RadrootsTradeFacetCount", + "RadrootsTradeListing", + "RadrootsTradeListingBackofficeOverlay", + "RadrootsTradeListingBackofficeQuery", + "RadrootsTradeListingBackofficeView", + "RadrootsTradeListingBinProjection", + "RadrootsTradeListingFacets", + "RadrootsTradeListingMarketStatus", + "RadrootsTradeListingProjection", + "RadrootsTradeListingQuery", + "RadrootsTradeListingSort", + "RadrootsTradeListingSortField", + "RadrootsTradeListingSubtotal", + "RadrootsTradeListingTotal", + "RadrootsTradeMarketplaceListingSummary", + "RadrootsTradeMarketplaceOrderSummary", + "RadrootsTradeMessageType", + "RadrootsTradeModerationFlag", + "RadrootsTradeModerationSeverity", + "RadrootsTradeModerationStatus", + "RadrootsTradeOrderBackofficeOverlay", + "RadrootsTradeOrderBackofficeQuery", + "RadrootsTradeOrderBackofficeView", + "RadrootsTradeOrderFacets", + "RadrootsTradeOrderQuery", + "RadrootsTradeOrderSort", + "RadrootsTradeOrderSortField", + "RadrootsTradeOrderStatus", + "RadrootsTradeOrderWorkflowMessage", + "RadrootsTradeOrderWorkflowProjection", + "RadrootsTradeReviewPriority", + "RadrootsTradeReviewQueueEntry", + "RadrootsTradeReviewStatus", + "RadrootsTradeSortDirection" + ] + ); } #[test] @@ -332,12 +377,4 @@ mod tests { .map(|entry| entry.disposition) .expect("inventory entry") } - - fn type_inventory(types_ts: &str) -> Vec<&str> { - types_ts - .lines() - .filter_map(|line| line.strip_prefix("export type ")) - .map(|rest| rest.split([' ', '<']).next().expect("type name")) - .collect() - } } diff --git a/crates/trade_bindings/src/model.rs b/crates/trade_bindings/src/model.rs @@ -1,750 +0,0 @@ -use radroots_sdk_binding_model as ts; - -pub fn types_module() -> ts::TsModule { - ts::module(vec![ - ts::type_alias( - "RadrootsFarmRef", - ts::object(vec![ - ts::field("pubkey", ts::string()), - ts::field("d_tag", ts::string()), - ]), - ), - ts::type_alias( - "RadrootsListing", - ts::object(vec![ - ts::field("d_tag", ts::string()), - ts::field("farm", ts::reference("RadrootsFarmRef")), - ts::field("product", ts::reference("RadrootsListingProduct")), - ts::field("primary_bin_id", ts::string()), - ts::field("bins", ts::array(ts::reference("RadrootsListingBin"))), - ts::optional_field( - "resource_area", - ts::union(vec![ts::reference("RadrootsResourceAreaRef"), ts::null()]), - ), - ts::optional_field( - "plot", - ts::union(vec![ts::reference("RadrootsPlotRef"), ts::null()]), - ), - ts::optional_field( - "discounts", - ts::union(vec![ - ts::array(ts::reference("RadrootsCoreDiscount")), - ts::null(), - ]), - ), - ts::optional_field( - "inventory_available", - ts::union(vec![ts::reference("RadrootsCoreDecimal"), ts::null()]), - ), - ts::optional_field( - "availability", - ts::union(vec![ - ts::reference("RadrootsListingAvailability"), - ts::null(), - ]), - ), - ts::optional_field( - "delivery_method", - ts::union(vec![ - ts::reference("RadrootsListingDeliveryMethod"), - ts::null(), - ]), - ), - ts::optional_field( - "location", - ts::union(vec![ts::reference("RadrootsListingLocation"), ts::null()]), - ), - ts::optional_field( - "images", - ts::union(vec![ - ts::array(ts::reference("RadrootsListingImage")), - ts::null(), - ]), - ), - ]), - ), - ts::type_alias( - "RadrootsListingAvailability", - ts::union(vec![ - ts::object(vec![ - ts::field("kind", ts::string_literal("window")), - ts::field( - "amount", - ts::object(vec![ - ts::optional_field("start", ts::union(vec![ts::number(), ts::null()])), - ts::optional_field("end", ts::union(vec![ts::number(), ts::null()])), - ]), - ), - ]), - ts::object(vec![ - ts::field("kind", ts::string_literal("status")), - ts::field( - "amount", - ts::object(vec![ts::field( - "status", - ts::reference("RadrootsListingStatus"), - )]), - ), - ]), - ]), - ), - ts::type_alias( - "RadrootsListingBin", - ts::object(vec![ - ts::field("bin_id", ts::string()), - ts::field("quantity", ts::reference("RadrootsCoreQuantity")), - ts::field( - "price_per_canonical_unit", - ts::reference("RadrootsCoreQuantityPrice"), - ), - ts::optional_field( - "display_amount", - ts::union(vec![ts::reference("RadrootsCoreDecimal"), ts::null()]), - ), - ts::optional_field( - "display_unit", - ts::union(vec![ts::reference("RadrootsCoreUnit"), ts::null()]), - ), - ts::optional_field("display_label", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field( - "display_price", - ts::union(vec![ts::reference("RadrootsCoreMoney"), ts::null()]), - ), - ts::optional_field( - "display_price_unit", - ts::union(vec![ts::reference("RadrootsCoreUnit"), ts::null()]), - ), - ]), - ), - ts::type_alias( - "RadrootsListingDeliveryMethod", - ts::union(vec![ - ts::object(vec![ts::field("kind", ts::string_literal("pickup"))]), - ts::object(vec![ts::field( - "kind", - ts::string_literal("local_delivery"), - )]), - ts::object(vec![ts::field("kind", ts::string_literal("shipping"))]), - ts::object(vec![ - ts::field("kind", ts::string_literal("other")), - ts::field( - "amount", - ts::object(vec![ts::field("method", ts::string())]), - ), - ]), - ]), - ), - ts::type_alias( - "RadrootsListingLocation", - ts::object(vec![ - ts::field("primary", ts::string()), - ts::optional_field("city", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("region", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("country", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("lat", ts::union(vec![ts::number(), ts::null()])), - ts::optional_field("lng", ts::union(vec![ts::number(), ts::null()])), - ts::optional_field("geohash", ts::union(vec![ts::string(), ts::null()])), - ]), - ), - ts::type_alias( - "RadrootsListingProduct", - ts::object(vec![ - ts::field("key", ts::string()), - ts::field("title", ts::string()), - ts::field("category", ts::string()), - ts::optional_field("summary", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("process", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("lot", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("location", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("profile", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("year", ts::union(vec![ts::string(), ts::null()])), - ]), - ), - ts::type_alias( - "RadrootsListingStatus", - ts::union(vec![ - ts::object(vec![ts::field("kind", ts::string_literal("active"))]), - ts::object(vec![ts::field("kind", ts::string_literal("sold"))]), - ts::object(vec![ - ts::field("kind", ts::string_literal("other")), - ts::field("amount", ts::object(vec![ts::field("value", ts::string())])), - ]), - ]), - ), - ts::type_alias( - "RadrootsTradeFacetCount", - ts::object(vec![ - ts::field("key", ts::string()), - ts::field("count", ts::number()), - ]), - ), - ts::type_alias( - "RadrootsTradeListing", - ts::object(vec![ - ts::field("listing_id", ts::string()), - ts::field("listing_addr", ts::string()), - ts::field("seller_pubkey", ts::string()), - ts::field("title", ts::string()), - ts::field("description", ts::string()), - ts::field("product_type", ts::string()), - ts::field("primary_bin_id", ts::string()), - ts::field("bin_quantity", ts::reference("RadrootsCoreQuantity")), - ts::field("unit", ts::reference("RadrootsCoreUnit")), - ts::field("unit_price", ts::reference("RadrootsCoreMoney")), - ts::field("inventory_available", ts::reference("RadrootsCoreDecimal")), - ts::field("availability", ts::reference("RadrootsListingAvailability")), - ts::field("location", ts::reference("RadrootsListingLocation")), - ts::field( - "delivery_method", - ts::reference("RadrootsListingDeliveryMethod"), - ), - ts::field("listing", ts::reference("RadrootsListing")), - ]), - ), - ts::type_alias( - "RadrootsTradeListingBackofficeOverlay", - ts::object(vec![ - ts::field("listing_addr", ts::string()), - ts::optional_field( - "review_queue", - ts::union(vec![ - ts::reference("RadrootsTradeReviewQueueEntry"), - ts::null(), - ]), - ), - ts::field( - "moderation_flags", - ts::array(ts::reference("RadrootsTradeModerationFlag")), - ), - ]), - ), - ts::type_alias( - "RadrootsTradeListingBackofficeQuery", - ts::object(vec![ - ts::field("listing", ts::reference("RadrootsTradeListingQuery")), - ts::optional_field( - "requires_review", - ts::union(vec![ts::boolean(), ts::null()]), - ), - ts::optional_field( - "has_open_moderation_flags", - ts::union(vec![ts::boolean(), ts::null()]), - ), - ]), - ), - ts::type_alias( - "RadrootsTradeListingBackofficeView", - ts::object(vec![ - ts::field("listing", ts::reference("RadrootsTradeListingProjection")), - ts::optional_field( - "marketplace", - ts::union(vec![ - ts::reference("RadrootsTradeMarketplaceListingSummary"), - ts::null(), - ]), - ), - ts::optional_field( - "overlay", - ts::union(vec![ - ts::reference("RadrootsTradeListingBackofficeOverlay"), - ts::null(), - ]), - ), - ts::field("requires_review", ts::boolean()), - ts::field("open_moderation_flag_count", ts::number()), - ]), - ), - ts::type_alias( - "RadrootsTradeListingBinProjection", - ts::object(vec![ - ts::field("bin", ts::reference("RadrootsListingBin")), - ts::field("one_bin_total", ts::reference("RadrootsTradeListingTotal")), - ]), - ), - ts::type_alias( - "RadrootsTradeListingFacets", - ts::object(vec![ - ts::field( - "seller_pubkeys", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ts::field( - "farm_pubkeys", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ts::field( - "farm_ids", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ts::field( - "product_keys", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ts::field( - "product_categories", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ts::field( - "listing_statuses", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ]), - ), - ts::type_alias( - "RadrootsTradeListingMarketStatus", - ts::union(vec![ - ts::string_literal("unknown"), - ts::string_literal("window"), - ts::string_literal("active"), - ts::string_literal("sold"), - ts::object(vec![ts::field( - "other", - ts::object(vec![ts::field("value", ts::string())]), - )]), - ]), - ), - ts::type_alias( - "RadrootsTradeListingProjection", - ts::object(vec![ - ts::field("listing_addr", ts::string()), - ts::field("seller_pubkey", ts::string()), - ts::field("listing_id", ts::string()), - ts::field("farm", ts::reference("RadrootsFarmRef")), - ts::field("product", ts::reference("RadrootsListingProduct")), - ts::field("primary_bin_id", ts::string()), - ts::field( - "bins", - ts::array(ts::reference("RadrootsTradeListingBinProjection")), - ), - ts::optional_field( - "resource_area", - ts::union(vec![ts::reference("RadrootsResourceAreaRef"), ts::null()]), - ), - ts::optional_field( - "plot", - ts::union(vec![ts::reference("RadrootsPlotRef"), ts::null()]), - ), - ts::optional_field( - "discounts", - ts::union(vec![ - ts::array(ts::reference("RadrootsCoreDiscount")), - ts::null(), - ]), - ), - ts::optional_field( - "inventory_available", - ts::union(vec![ts::reference("RadrootsCoreDecimal"), ts::null()]), - ), - ts::optional_field( - "availability", - ts::union(vec![ - ts::reference("RadrootsListingAvailability"), - ts::null(), - ]), - ), - ts::optional_field( - "delivery_method", - ts::union(vec![ - ts::reference("RadrootsListingDeliveryMethod"), - ts::null(), - ]), - ), - ts::optional_field( - "location", - ts::union(vec![ts::reference("RadrootsListingLocation"), ts::null()]), - ), - ts::optional_field( - "images", - ts::union(vec![ - ts::array(ts::reference("RadrootsListingImage")), - ts::null(), - ]), - ), - ts::field("order_count", ts::number()), - ts::field("open_order_count", ts::number()), - ts::field("terminal_order_count", ts::number()), - ]), - ), - ts::type_alias( - "RadrootsTradeListingQuery", - ts::object(vec![ - ts::optional_field("seller_pubkey", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("farm_pubkey", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("farm_id", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("product_key", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field( - "product_category", - ts::union(vec![ts::string(), ts::null()]), - ), - ts::optional_field( - "listing_status", - ts::union(vec![ - ts::reference("RadrootsTradeListingMarketStatus"), - ts::null(), - ]), - ), - ]), - ), - ts::type_alias( - "RadrootsTradeListingSort", - ts::object(vec![ - ts::field("field", ts::reference("RadrootsTradeListingSortField")), - ts::field("direction", ts::reference("RadrootsTradeSortDirection")), - ]), - ), - ts::type_alias( - "RadrootsTradeListingSortField", - ts::union(vec![ - ts::string_literal("listing_addr"), - ts::string_literal("product_title"), - ts::string_literal("product_category"), - ts::string_literal("seller_pubkey"), - ts::string_literal("inventory_available"), - ts::string_literal("open_order_count"), - ts::string_literal("total_order_count"), - ]), - ), - ts::type_alias( - "RadrootsTradeListingSubtotal", - ts::object(vec![ - ts::field("price_amount", ts::reference("RadrootsCoreMoney")), - ts::field("price_currency", ts::reference("RadrootsCoreCurrency")), - ts::field("quantity_amount", ts::reference("RadrootsCoreDecimal")), - ts::field("quantity_unit", ts::reference("RadrootsCoreUnit")), - ]), - ), - ts::type_alias( - "RadrootsTradeListingTotal", - ts::object(vec![ - ts::field("price_amount", ts::reference("RadrootsCoreMoney")), - ts::field("price_currency", ts::reference("RadrootsCoreCurrency")), - ts::field("quantity_amount", ts::reference("RadrootsCoreDecimal")), - ts::field("quantity_unit", ts::reference("RadrootsCoreUnit")), - ]), - ), - ts::type_alias( - "RadrootsTradeMarketplaceListingSummary", - ts::object(vec![ - ts::field("listing_addr", ts::string()), - ts::field("seller_pubkey", ts::string()), - ts::field("farm_pubkey", ts::string()), - ts::field("farm_id", ts::string()), - ts::field("product_key", ts::string()), - ts::field("product_title", ts::string()), - ts::field("product_category", ts::string()), - ts::optional_field("product_summary", ts::union(vec![ts::string(), ts::null()])), - ts::field( - "listing_status", - ts::reference("RadrootsTradeListingMarketStatus"), - ), - ts::optional_field( - "location_primary", - ts::union(vec![ts::string(), ts::null()]), - ), - ts::optional_field( - "inventory_available", - ts::union(vec![ts::reference("RadrootsCoreDecimal"), ts::null()]), - ), - ts::field("primary_bin_id", ts::string()), - ts::optional_field( - "primary_bin_label", - ts::union(vec![ts::string(), ts::null()]), - ), - ts::field( - "primary_bin_total", - ts::reference("RadrootsTradeListingTotal"), - ), - ts::field("order_count", ts::number()), - ts::field("open_order_count", ts::number()), - ts::field("terminal_order_count", ts::number()), - ]), - ), - ts::type_alias( - "RadrootsTradeMarketplaceOrderSummary", - ts::object(vec![ - ts::field("order_id", ts::string()), - ts::field("listing_addr", ts::string()), - ts::field("buyer_pubkey", ts::string()), - ts::field("seller_pubkey", ts::string()), - ts::field("status", ts::reference("RadrootsTradeOrderStatus")), - ts::field( - "last_message_type", - ts::reference("RadrootsTradeMessageType"), - ), - ts::field("item_count", ts::number()), - ts::field("total_bin_count", ts::number()), - ts::field("has_requested_discounts", ts::boolean()), - ts::optional_field("last_reason", ts::union(vec![ts::string(), ts::null()])), - ]), - ), - ts::type_alias( - "RadrootsTradeMessageType", - ts::union(vec![ - ts::string_literal("listing_validate_request"), - ts::string_literal("listing_validate_result"), - ts::string_literal("order_request"), - ts::string_literal("order_response"), - ts::string_literal("order_revision"), - ts::string_literal("order_revision_accept"), - ts::string_literal("order_revision_decline"), - ts::string_literal("question"), - ts::string_literal("answer"), - ts::string_literal("discount_request"), - ts::string_literal("discount_offer"), - ts::string_literal("discount_accept"), - ts::string_literal("discount_decline"), - ts::string_literal("cancel"), - ]), - ), - ts::type_alias( - "RadrootsTradeModerationFlag", - ts::object(vec![ - ts::field("code", ts::string()), - ts::field("severity", ts::reference("RadrootsTradeModerationSeverity")), - ts::field("status", ts::reference("RadrootsTradeModerationStatus")), - ts::optional_field("source", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("reason", ts::union(vec![ts::string(), ts::null()])), - ]), - ), - ts::type_alias( - "RadrootsTradeModerationSeverity", - ts::union(vec![ - ts::string_literal("notice"), - ts::string_literal("warning"), - ts::string_literal("block"), - ]), - ), - ts::type_alias( - "RadrootsTradeModerationStatus", - ts::union(vec![ - ts::string_literal("open"), - ts::string_literal("snoozed"), - ts::string_literal("resolved"), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderBackofficeOverlay", - ts::object(vec![ - ts::field("order_id", ts::string()), - ts::optional_field( - "review_queue", - ts::union(vec![ - ts::reference("RadrootsTradeReviewQueueEntry"), - ts::null(), - ]), - ), - ts::field( - "moderation_flags", - ts::array(ts::reference("RadrootsTradeModerationFlag")), - ), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderBackofficeQuery", - ts::object(vec![ - ts::field("order", ts::reference("RadrootsTradeOrderQuery")), - ts::optional_field( - "requires_review", - ts::union(vec![ts::boolean(), ts::null()]), - ), - ts::optional_field( - "has_open_moderation_flags", - ts::union(vec![ts::boolean(), ts::null()]), - ), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderBackofficeView", - ts::object(vec![ - ts::field( - "order", - ts::reference("RadrootsTradeOrderWorkflowProjection"), - ), - ts::field( - "marketplace", - ts::reference("RadrootsTradeMarketplaceOrderSummary"), - ), - ts::optional_field( - "overlay", - ts::union(vec![ - ts::reference("RadrootsTradeOrderBackofficeOverlay"), - ts::null(), - ]), - ), - ts::field("requires_review", ts::boolean()), - ts::field("open_moderation_flag_count", ts::number()), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderFacets", - ts::object(vec![ - ts::field( - "buyer_pubkeys", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ts::field( - "seller_pubkeys", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ts::field( - "listing_addrs", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ts::field( - "statuses", - ts::array(ts::reference("RadrootsTradeFacetCount")), - ), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderQuery", - ts::object(vec![ - ts::optional_field("listing_addr", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("buyer_pubkey", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("seller_pubkey", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field( - "status", - ts::union(vec![ts::reference("RadrootsTradeOrderStatus"), ts::null()]), - ), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderSort", - ts::object(vec![ - ts::field("field", ts::reference("RadrootsTradeOrderSortField")), - ts::field("direction", ts::reference("RadrootsTradeSortDirection")), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderSortField", - ts::union(vec![ - ts::string_literal("order_id"), - ts::string_literal("listing_addr"), - ts::string_literal("buyer_pubkey"), - ts::string_literal("seller_pubkey"), - ts::string_literal("status"), - ts::string_literal("last_message_type"), - ts::string_literal("total_bin_count"), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderStatus", - ts::union(vec![ - ts::string_literal("draft"), - ts::string_literal("validated"), - ts::string_literal("requested"), - ts::string_literal("questioned"), - ts::string_literal("revised"), - ts::string_literal("accepted"), - ts::string_literal("declined"), - ts::string_literal("cancelled"), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderWorkflowMessage", - ts::object(vec![ - ts::field("event_id", ts::string()), - ts::field("actor_pubkey", ts::string()), - ts::field("counterparty_pubkey", ts::string()), - ts::field("listing_addr", ts::string()), - ts::optional_field("order_id", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field( - "listing_event", - ts::union(vec![ts::reference("RadrootsNostrEventPtr"), ts::null()]), - ), - ts::optional_field("root_event_id", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field("prev_event_id", ts::union(vec![ts::string(), ts::null()])), - ts::field("payload", ts::reference("RadrootsTradeMessagePayload")), - ]), - ), - ts::type_alias( - "RadrootsTradeOrderWorkflowProjection", - ts::object(vec![ - ts::field("order_id", ts::string()), - ts::field("listing_addr", ts::string()), - ts::field("buyer_pubkey", ts::string()), - ts::field("seller_pubkey", ts::string()), - ts::field("items", ts::array(ts::reference("RadrootsTradeOrderItem"))), - ts::optional_field( - "requested_discounts", - ts::union(vec![ - ts::array(ts::reference("RadrootsTradeOrderEconomicLine")), - ts::null(), - ]), - ), - ts::field("status", ts::reference("RadrootsTradeOrderStatus")), - ts::optional_field( - "listing_snapshot", - ts::union(vec![ts::reference("RadrootsNostrEventPtr"), ts::null()]), - ), - ts::field("root_event_id", ts::string()), - ts::field("last_event_id", ts::string()), - ts::optional_field( - "last_discount_request", - ts::union(vec![ts::reference("RadrootsCoreDiscountValue"), ts::null()]), - ), - ts::optional_field( - "last_discount_offer", - ts::union(vec![ts::reference("RadrootsCoreDiscountValue"), ts::null()]), - ), - ts::optional_field( - "accepted_discount", - ts::union(vec![ts::reference("RadrootsCoreDiscountValue"), ts::null()]), - ), - ts::optional_field("last_reason", ts::union(vec![ts::string(), ts::null()])), - ts::optional_field( - "last_discount_decline_reason", - ts::union(vec![ts::string(), ts::null()]), - ), - ts::field("question_count", ts::number()), - ts::field("answer_count", ts::number()), - ts::field("revision_count", ts::number()), - ts::field("discount_request_count", ts::number()), - ts::field("discount_offer_count", ts::number()), - ts::field("discount_accept_count", ts::number()), - ts::field("discount_decline_count", ts::number()), - ts::field("cancellation_count", ts::number()), - ts::field( - "last_message_type", - ts::reference("RadrootsTradeMessageType"), - ), - ts::field("last_actor_pubkey", ts::string()), - ]), - ), - ts::type_alias( - "RadrootsTradeReviewPriority", - ts::union(vec![ - ts::string_literal("low"), - ts::string_literal("normal"), - ts::string_literal("high"), - ts::string_literal("critical"), - ]), - ), - ts::type_alias( - "RadrootsTradeReviewQueueEntry", - ts::object(vec![ - ts::field("queue", ts::string()), - ts::field("priority", ts::reference("RadrootsTradeReviewPriority")), - ts::field("status", ts::reference("RadrootsTradeReviewStatus")), - ts::optional_field( - "assigned_operator", - ts::union(vec![ts::string(), ts::null()]), - ), - ts::optional_field("reason", ts::union(vec![ts::string(), ts::null()])), - ]), - ), - ts::type_alias( - "RadrootsTradeReviewStatus", - ts::union(vec![ - ts::string_literal("queued"), - ts::string_literal("in_progress"), - ts::string_literal("blocked"), - ts::string_literal("resolved"), - ]), - ), - ts::type_alias( - "RadrootsTradeSortDirection", - ts::union(vec![ts::string_literal("asc"), ts::string_literal("desc")]), - ), - ]) -} diff --git a/packages/trade-bindings/src/generated/types.ts b/packages/trade-bindings/src/generated/types.ts @@ -7,35 +7,27 @@ import type { RadrootsCoreDiscountValue, RadrootsCoreMoney, RadrootsCoreQuantity, - RadrootsCoreQuantityPrice, RadrootsCoreUnit, } from "@radroots/core-bindings"; import type { + RadrootsFarmRef, + RadrootsListing, + RadrootsListingAvailability, + RadrootsListingBin, + RadrootsListingDeliveryMethod, RadrootsListingImage, + RadrootsListingLocation, + RadrootsListingProduct, RadrootsNostrEventPtr, RadrootsPlotRef, RadrootsResourceAreaRef, RadrootsTradeMessagePayload, + RadrootsTradeMessageType, RadrootsTradeOrderEconomicLine, RadrootsTradeOrderItem, + RadrootsTradeOrderStatus, } from "@radroots/events-bindings"; -export type RadrootsFarmRef = { pubkey: string, d_tag: string, }; - -export type RadrootsListing = { d_tag: string, farm: RadrootsFarmRef, product: RadrootsListingProduct, primary_bin_id: string, bins: Array<RadrootsListingBin>, resource_area?: RadrootsResourceAreaRef | null, plot?: RadrootsPlotRef | null, discounts?: Array<RadrootsCoreDiscount> | null, inventory_available?: RadrootsCoreDecimal | null, availability?: RadrootsListingAvailability | null, delivery_method?: RadrootsListingDeliveryMethod | null, location?: RadrootsListingLocation | null, images?: Array<RadrootsListingImage> | null, }; - -export type RadrootsListingAvailability = { kind: "window", amount: { start?: number | null, end?: number | null, }, } | { kind: "status", amount: { status: RadrootsListingStatus, }, }; - -export type RadrootsListingBin = { bin_id: string, quantity: RadrootsCoreQuantity, price_per_canonical_unit: RadrootsCoreQuantityPrice, display_amount?: RadrootsCoreDecimal | null, display_unit?: RadrootsCoreUnit | null, display_label?: string | null, display_price?: RadrootsCoreMoney | null, display_price_unit?: RadrootsCoreUnit | null, }; - -export type RadrootsListingDeliveryMethod = { kind: "pickup", } | { kind: "local_delivery", } | { kind: "shipping", } | { kind: "other", amount: { method: string, }, }; - -export type RadrootsListingLocation = { primary: string, city?: string | null, region?: string | null, country?: string | null, lat?: number | null, lng?: number | null, geohash?: string | null, }; - -export type RadrootsListingProduct = { key: string, title: string, category: string, summary?: string | null, process?: string | null, lot?: string | null, location?: string | null, profile?: string | null, year?: string | null, }; - -export type RadrootsListingStatus = { kind: "active", } | { kind: "sold", } | { kind: "other", amount: { value: string, }, }; - export type RadrootsTradeFacetCount = { key: string, count: number, }; export type RadrootsTradeListing = { listing_id: string, listing_addr: string, seller_pubkey: string, title: string, description: string, product_type: string, primary_bin_id: string, bin_quantity: RadrootsCoreQuantity, unit: RadrootsCoreUnit, unit_price: RadrootsCoreMoney, inventory_available: RadrootsCoreDecimal, availability: RadrootsListingAvailability, location: RadrootsListingLocation, delivery_method: RadrootsListingDeliveryMethod, listing: RadrootsListing, }; @@ -68,8 +60,6 @@ export type RadrootsTradeMarketplaceListingSummary = { listing_addr: string, sel export type RadrootsTradeMarketplaceOrderSummary = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, status: RadrootsTradeOrderStatus, last_message_type: RadrootsTradeMessageType, item_count: number, total_bin_count: number, has_requested_discounts: boolean, last_reason?: string | null, }; -export type RadrootsTradeMessageType = "listing_validate_request" | "listing_validate_result" | "order_request" | "order_response" | "order_revision" | "order_revision_accept" | "order_revision_decline" | "question" | "answer" | "discount_request" | "discount_offer" | "discount_accept" | "discount_decline" | "cancel"; - export type RadrootsTradeModerationFlag = { code: string, severity: RadrootsTradeModerationSeverity, status: RadrootsTradeModerationStatus, source?: string | null, reason?: string | null, }; export type RadrootsTradeModerationSeverity = "notice" | "warning" | "block"; @@ -90,8 +80,6 @@ export type RadrootsTradeOrderSort = { field: RadrootsTradeOrderSortField, direc export type RadrootsTradeOrderSortField = "order_id" | "listing_addr" | "buyer_pubkey" | "seller_pubkey" | "status" | "last_message_type" | "total_bin_count"; -export type RadrootsTradeOrderStatus = "draft" | "validated" | "requested" | "questioned" | "revised" | "accepted" | "declined" | "cancelled"; - export type RadrootsTradeOrderWorkflowMessage = { event_id: string, actor_pubkey: string, counterparty_pubkey: string, listing_addr: string, order_id?: string | null, listing_event?: RadrootsNostrEventPtr | null, root_event_id?: string | null, prev_event_id?: string | null, payload: RadrootsTradeMessagePayload, }; export type RadrootsTradeOrderWorkflowProjection = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, items: Array<RadrootsTradeOrderItem>, requested_discounts?: Array<RadrootsTradeOrderEconomicLine> | null, status: RadrootsTradeOrderStatus, listing_snapshot?: RadrootsNostrEventPtr | null, root_event_id: string, last_event_id: string, last_discount_request?: RadrootsCoreDiscountValue | null, last_discount_offer?: RadrootsCoreDiscountValue | null, accepted_discount?: RadrootsCoreDiscountValue | null, last_reason?: string | null, last_discount_decline_reason?: string | null, question_count: number, answer_count: number, revision_count: number, discount_request_count: number, discount_offer_count: number, discount_accept_count: number, discount_decline_count: number, cancellation_count: number, last_message_type: RadrootsTradeMessageType, last_actor_pubkey: string, }; diff --git a/tools/xtask/src/dto_render.rs b/tools/xtask/src/dto_render.rs @@ -47,6 +47,7 @@ impl DtoTypeImport { pub struct DtoRegistryRenderOptions { config: Config, external_imports: BTreeMap<TypeId, DtoTypeImport>, + external_overrides: BTreeMap<String, DtoTypeImport>, } impl DtoRegistryRenderOptions { @@ -54,6 +55,7 @@ impl DtoRegistryRenderOptions { Self { config, external_imports: BTreeMap::new(), + external_overrides: BTreeMap::new(), } } @@ -67,6 +69,17 @@ impl DtoRegistryRenderOptions { .insert(type_id, DtoTypeImport::new(import_name, from)); self } + + pub fn with_external_override( + mut self, + target_type: impl Into<String>, + import_name: impl Into<String>, + from: impl Into<String>, + ) -> Self { + self.external_overrides + .insert(target_type.into(), DtoTypeImport::new(import_name, from)); + self + } } impl Default for DtoRegistryRenderOptions { @@ -387,6 +400,13 @@ fn render_type_ref( TypeRef::Named(type_id) => render_named_type(*type_id, registry, options, imports), TypeRef::GenericParam(name) => Ok(name.clone()), TypeRef::Override(target) if target.backend == BackendId::TypeScript => { + if let Some(import) = options.external_overrides.get(&target.target_type) { + imports + .entry(import.from.clone()) + .or_default() + .insert(import.import_name.clone()); + return Ok(import.import_name.clone()); + } Ok(target.target_type.clone()) } TypeRef::Override(_) => Err("target override is for a different backend".to_owned()), @@ -675,6 +695,40 @@ mod tests { } #[test] + fn imports_typescript_overrides_when_configured() { + let mut registry = Registry::new(); + registry.register_type( + RustTypeId::new("sdk", "SyntheticThing"), + TypeDef::Struct( + StructDef::new("SyntheticThing", "SyntheticThing", span()).with_field(field( + "external", + "external", + TypeRef::Override(TargetOverride::new(BackendId::TypeScript, "ExternalAlias")), + )), + ), + ); + + let rendered = render_registry_types( + &registry, + &DtoRegistryRenderOptions::default().with_external_override( + "ExternalAlias", + "ExternalAlias", + "@radroots/external-bindings", + ), + ) + .expect("registry renders"); + + assert_eq!( + rendered.imports_ts(), + Some("import type { ExternalAlias } from \"@radroots/external-bindings\";\n\n") + ); + assert_eq!( + rendered.body_ts(), + "export type SyntheticThing = { external: ExternalAlias, };" + ); + } + + #[test] fn requires_explicit_large_integer_policy() { let mut registry = Registry::new(); registry.register_type( diff --git a/tools/xtask/src/dto_roots.rs b/tools/xtask/src/dto_roots.rs @@ -45,6 +45,10 @@ pub const DTO_PACKAGE_ROOTS: &[DtoPackageRootSet] = &[ package_key: "events_indexed", roots: events_indexed_roots, }, + DtoPackageRootSet { + package_key: "trade", + roots: trade_roots, + }, ]; pub const MANUAL_DESCRIPTOR_FAMILIES: &[ManualDescriptorFamily] = &[ @@ -69,6 +73,11 @@ pub const MANUAL_DESCRIPTOR_FAMILIES: &[ManualDescriptorFamily] = &[ reason: "custom deserialization and large integers require manual descriptor policy", }, ManualDescriptorFamily { + package_key: "trade", + source_family: "trade listing roots and package projection count fields", + reason: "core aliases, source-owned event imports, and count-family numeric policy require explicit descriptors", + }, + ManualDescriptorFamily { package_key: "replica_db_schema", source_family: "untagged query wrappers and serde_json value fields", reason: "schema query shapes are generated and not all source fields map to derive-supported DTOs", @@ -101,6 +110,11 @@ pub const SDK_LOCAL_WRAPPER_ALLOWANCES: &[SdkLocalWrapperAllowance] = &[ shape_family: "RadrootsEventsIndexedShardId package alias", reason: "source descriptors correctly describe the shard id newtype as a string, while package roots still need a stable named TypeScript alias", }, + SdkLocalWrapperAllowance { + package_key: "trade", + shape_family: "marketplace, query, projection, sort, review, and backoffice DTO shapes", + reason: "these are SDK package contract shapes layered over source-owned trade, events, and core DTOs", + }, ]; pub fn package_root_set(package_key: &str) -> Option<&'static DtoPackageRootSet> { @@ -147,6 +161,15 @@ pub fn events_indexed_types_module() -> Result<DtoTypesModule, String> { )) } +pub fn trade_types_module() -> Result<DtoTypesModule, String> { + let root_set = package_root_set("trade").ok_or_else(|| "missing trade DTO roots".to_owned())?; + let registry = root_set.registry(); + render_registry_types( + &registry, + &trade_import_options(DtoRegistryRenderOptions::default()), + ) +} + fn core_roots() -> Vec<RootDescriptor> { radroots_core::dto::dto_roots().into_iter().collect() } @@ -161,6 +184,10 @@ fn events_indexed_roots() -> Vec<RootDescriptor> { .collect() } +fn trade_roots() -> Vec<RootDescriptor> { + radroots_trade_bindings::dto_roots() +} + fn core_import_options( registry: &Registry, mut options: DtoRegistryRenderOptions, @@ -193,6 +220,47 @@ fn core_type_id(registry: &Registry, rust_ident: &str) -> Option<TypeId> { .copied() } +fn trade_import_options(mut options: DtoRegistryRenderOptions) -> DtoRegistryRenderOptions { + for export_name in [ + "RadrootsCoreCurrency", + "RadrootsCoreDecimal", + "RadrootsCoreDiscount", + "RadrootsCoreDiscountValue", + "RadrootsCoreMoney", + "RadrootsCoreQuantity", + "RadrootsCoreQuantityPrice", + "RadrootsCoreUnit", + ] { + options = + options.with_external_override(export_name, export_name, "@radroots/core-bindings"); + } + + for export_name in [ + "RadrootsFarmRef", + "RadrootsListing", + "RadrootsListingAvailability", + "RadrootsListingBin", + "RadrootsListingDeliveryMethod", + "RadrootsListingImage", + "RadrootsListingLocation", + "RadrootsListingProduct", + "RadrootsListingStatus", + "RadrootsNostrEventPtr", + "RadrootsPlotRef", + "RadrootsResourceAreaRef", + "RadrootsTradeMessagePayload", + "RadrootsTradeMessageType", + "RadrootsTradeOrderEconomicLine", + "RadrootsTradeOrderItem", + "RadrootsTradeOrderStatus", + ] { + options = + options.with_external_override(export_name, export_name, "@radroots/events-bindings"); + } + + options +} + fn with_events_sdk_wrappers(body: &str) -> String { let mut declarations = body .split("\n\n") @@ -249,6 +317,8 @@ mod tests { include_str!("../../../packages/events-bindings/src/generated/types.ts"); const EVENTS_INDEXED_BINDINGS_TYPES_TS: &str = include_str!("../../../packages/events-indexed-bindings/src/generated/types.ts"); + const TRADE_BINDINGS_TYPES_TS: &str = + include_str!("../../../packages/trade-bindings/src/generated/types.ts"); const EVENTS_TYPE_INVENTORY: &[&str] = &[ "JobFeedbackStatus", "JobInputType", @@ -359,6 +429,40 @@ mod tests { "RadrootsEventsIndexedShardCheckpoint", "RadrootsEventsIndexedIndexCheckpoint", ]; + const TRADE_TYPE_INVENTORY: &[&str] = &[ + "RadrootsTradeFacetCount", + "RadrootsTradeListing", + "RadrootsTradeListingBackofficeOverlay", + "RadrootsTradeListingBackofficeQuery", + "RadrootsTradeListingBackofficeView", + "RadrootsTradeListingBinProjection", + "RadrootsTradeListingFacets", + "RadrootsTradeListingMarketStatus", + "RadrootsTradeListingProjection", + "RadrootsTradeListingQuery", + "RadrootsTradeListingSort", + "RadrootsTradeListingSortField", + "RadrootsTradeListingSubtotal", + "RadrootsTradeListingTotal", + "RadrootsTradeMarketplaceListingSummary", + "RadrootsTradeMarketplaceOrderSummary", + "RadrootsTradeModerationFlag", + "RadrootsTradeModerationSeverity", + "RadrootsTradeModerationStatus", + "RadrootsTradeOrderBackofficeOverlay", + "RadrootsTradeOrderBackofficeQuery", + "RadrootsTradeOrderBackofficeView", + "RadrootsTradeOrderFacets", + "RadrootsTradeOrderQuery", + "RadrootsTradeOrderSort", + "RadrootsTradeOrderSortField", + "RadrootsTradeOrderWorkflowMessage", + "RadrootsTradeOrderWorkflowProjection", + "RadrootsTradeReviewPriority", + "RadrootsTradeReviewQueueEntry", + "RadrootsTradeReviewStatus", + "RadrootsTradeSortDirection", + ]; #[test] fn approved_source_roots_build_registries() { @@ -379,7 +483,7 @@ mod tests { assert!(package_root_set("core").is_some()); assert!(package_root_set("events").is_some()); assert!(package_root_set("events_indexed").is_some()); - assert!(package_root_set("trade").is_none()); + assert!(package_root_set("trade").is_some()); } #[test] @@ -409,6 +513,11 @@ mod tests { .shape_family .contains("RadrootsEventsIndexedShardId") })); + assert!(SDK_LOCAL_WRAPPER_ALLOWANCES.iter().any(|allowance| { + allowance + .shape_family + .contains("marketplace, query, projection") + })); } #[test] @@ -425,6 +534,28 @@ mod tests { assert_eq!(actual, EVENTS_INDEXED_TYPE_INVENTORY); } + #[test] + fn trade_type_inventory_matches_current_package_surface() { + let actual = type_inventory(TRADE_BINDINGS_TYPES_TS); + + assert_eq!(actual, TRADE_TYPE_INVENTORY); + } + + #[test] + fn trade_package_imports_source_owned_support_types() { + assert!(TRADE_BINDINGS_TYPES_TS.contains("from \"@radroots/core-bindings\"")); + assert!(TRADE_BINDINGS_TYPES_TS.contains("from \"@radroots/events-bindings\"")); + + for duplicate in [ + "export type RadrootsListing = ", + "export type RadrootsFarmRef = ", + "export type RadrootsTradeMessageType = ", + "export type RadrootsTradeOrderStatus = ", + ] { + assert!(!TRADE_BINDINGS_TYPES_TS.contains(duplicate)); + } + } + fn type_inventory(types_ts: &str) -> Vec<&str> { types_ts .lines() diff --git a/tools/xtask/src/output.rs b/tools/xtask/src/output.rs @@ -123,8 +123,8 @@ pub fn package_outputs() -> Result<Vec<PackageOutput>, String> { }, PackageOutput { spec: spec_by_key("trade"), - types_ts: Some(TsSource::Module(radroots_trade_bindings::types_module())), - types_imports_ts: Some(TRADE_TYPES_IMPORTS_TS), + types_ts: Some(TsSource::DtoRegistry(dto_roots::trade_types_module()?)), + types_imports_ts: None, constants_ts: None, kinds_ts: None, }, @@ -173,28 +173,6 @@ const REPLICA_DB_SCHEMA_TYPES_IMPORTS_TS: &str = r#"import type { "#; -const TRADE_TYPES_IMPORTS_TS: &str = r#"import type { - RadrootsCoreCurrency, - RadrootsCoreDecimal, - RadrootsCoreDiscount, - RadrootsCoreDiscountValue, - RadrootsCoreMoney, - RadrootsCoreQuantity, - RadrootsCoreQuantityPrice, - RadrootsCoreUnit, -} from "@radroots/core-bindings"; -import type { - RadrootsListingImage, - RadrootsNostrEventPtr, - RadrootsPlotRef, - RadrootsResourceAreaRef, - RadrootsTradeMessagePayload, - RadrootsTradeOrderEconomicLine, - RadrootsTradeOrderItem, -} from "@radroots/events-bindings"; - -"#; - fn render_manifest(spec: PackageSpec) -> String { let mut value = package_manifest(spec); value["generated"] = serde_json::Value::Bool(true); @@ -227,6 +205,9 @@ mod tests { use crate::{dto_render::DtoTypesModule, package_matrix::package_specs}; use radroots_sdk_binding_model::{module, string, type_alias}; + const TRADE_BINDINGS_TYPES_TS: &str = + include_str!("../../../packages/trade-bindings/src/generated/types.ts"); + #[test] fn renders_sdk_header() { let output = render_ts( @@ -310,4 +291,24 @@ mod tests { assert!(manifest.contents.contains("\"generated\": true")); assert_eq!(index.contents, "export * from \"./generated/types.js\";\n"); } + + #[test] + fn trade_output_uses_dto_registry_and_matches_checked_in_types() { + let output = package_outputs() + .expect("package outputs") + .into_iter() + .find(|output| output.spec.key == "trade") + .expect("trade output"); + + assert!(matches!(output.types_ts, Some(TsSource::DtoRegistry(_)))); + assert!(output.types_imports_ts.is_none()); + + let types = output + .files() + .into_iter() + .find(|file| file.relative_path == "src/generated/types.ts") + .expect("types file"); + + assert_eq!(types.contents, TRADE_BINDINGS_TYPES_TS); + } }