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:
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(
+ ®istry,
+ &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(
+ ®istry,
+ &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);
+ }
}