sdk

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

commit ebd6fc76629f8cb7688a04c8012bd1103008e94e
parent 87cf4ff726d7eee0f11a5eef5a8206f4960b6956
Author: triesap <tyson@radroots.org>
Date:   Sat, 27 Jun 2026 21:45:13 +0000

trade: source order workflow projection bindings

- Remove the SDK-local trade order workflow projection descriptor.
- Generate the projection from the rr-rs source trade DTO root.
- Import event-owned order support types from generated event bindings.
- Drop stale discount fields and required event evidence from trade types.

Diffstat:
Mcrates/trade_bindings/src/dto.rs | 32++------------------------------
Mcrates/trade_bindings/src/lib.rs | 39++++++++++++++++++++++++++-------------
Mpackages/trade-bindings/src/generated/types.ts | 12++++++------
Mtools/xtask/src/dto_roots.rs | 46+++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 77 insertions(+), 52 deletions(-)

diff --git a/crates/trade_bindings/src/dto.rs b/crates/trade_bindings/src/dto.rs @@ -4,7 +4,8 @@ use dto_bindgen_core::{ VariantShape, WireFieldNames, }; use radroots_trade::{ - listing::model::RadrootsTradeListingTotal, workflow::RadrootsTradeWorkflowState, + listing::model::RadrootsTradeListingTotal, order::RadrootsTradeOrderWorkflowProjection, + workflow::RadrootsTradeWorkflowState, }; pub fn dto_roots() -> Vec<RootDescriptor> { @@ -35,7 +36,6 @@ pub fn dto_roots() -> Vec<RootDescriptor> { RootDescriptor::new::<RadrootsTradeOrderQuery>(), RootDescriptor::new::<RadrootsTradeOrderSort>(), RootDescriptor::new::<RadrootsTradeOrderSortField>(), - RootDescriptor::new::<RadrootsTradeOrderWorkflowProjection>(), RootDescriptor::new::<RadrootsTradeReviewPriority>(), RootDescriptor::new::<RadrootsTradeReviewQueueEntry>(), RootDescriptor::new::<RadrootsTradeReviewStatus>(), @@ -58,7 +58,6 @@ macro_rules! imported_ts_type { 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"); @@ -80,12 +79,9 @@ imported_ts_type!( "RadrootsListingPublicLocation" ); imported_ts_type!(RadrootsListingProductImport, "RadrootsListingProduct"); -imported_ts_type!(RadrootsNostrEventPtrImport, "RadrootsNostrEventPtr"); imported_ts_type!(RadrootsPlotRefImport, "RadrootsPlotRef"); imported_ts_type!(RadrootsResourceAreaRefImport, "RadrootsResourceAreaRef"); -imported_ts_type!(RadrootsOrderEconomicLineImport, "RadrootsOrderEconomicLine"); imported_ts_type!(RadrootsOrderEventTypeImport, "RadrootsOrderEventType"); -imported_ts_type!(RadrootsOrderItemImport, "RadrootsOrderItem"); #[derive(dto_bindgen::Dto)] pub struct RadrootsTradeFacetCount { @@ -275,7 +271,6 @@ pub struct RadrootsTradeMarketplaceOrderSummary { pub last_message_type: RadrootsOrderEventTypeImport, pub item_count: u32, pub total_bin_count: u32, - pub has_requested_discounts: bool, pub last_reason: Option<String>, } @@ -372,29 +367,6 @@ pub enum RadrootsTradeOrderSortField { } #[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<RadrootsOrderItemImport>, - pub requested_discounts: Option<Vec<RadrootsOrderEconomicLineImport>>, - pub status: RadrootsTradeWorkflowState, - 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 revision_count: u32, - pub cancellation_count: u32, - pub last_message_type: RadrootsOrderEventTypeImport, - pub last_actor_pubkey: String, -} - -#[derive(dto_bindgen::Dto)] pub enum RadrootsTradeReviewPriority { #[serde(rename = "low")] Low, diff --git a/crates/trade_bindings/src/lib.rs b/crates/trade_bindings/src/lib.rs @@ -7,6 +7,7 @@ pub use dto::dto_roots; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum TradeTypeDisposition { SourceTradeRoot, + SourceTradeSupport, EventsBindingImport, SdkLocalPackageShape, } @@ -38,7 +39,10 @@ pub const TRADE_TYPE_INVENTORY: &[TradeTypeInventoryEntry] = &[ event_import("RadrootsListingProduct"), event_import("RadrootsListingPublicLocation"), event_import("RadrootsListingStatus"), + event_import("RadrootsOrderEconomics"), event_import("RadrootsOrderEventType"), + event_import("RadrootsOrderInventoryCommitment"), + source_support("RadrootsOrderIssue"), local_shape("RadrootsTradeFacetCount"), source_root("RadrootsTradeListing"), local_shape("RadrootsTradeListingBackofficeOverlay"), @@ -65,7 +69,7 @@ pub const TRADE_TYPE_INVENTORY: &[TradeTypeInventoryEntry] = &[ local_shape("RadrootsTradeOrderQuery"), local_shape("RadrootsTradeOrderSort"), local_shape("RadrootsTradeOrderSortField"), - local_shape("RadrootsTradeOrderWorkflowProjection"), + source_root("RadrootsTradeOrderWorkflowProjection"), local_shape("RadrootsTradeReviewPriority"), local_shape("RadrootsTradeReviewQueueEntry"), local_shape("RadrootsTradeReviewStatus"), @@ -94,8 +98,6 @@ pub const TRADE_LARGE_INTEGER_POLICIES: &[TradeLargeIntegerPolicyEntry] = &[ "RadrootsTradeOrderBackofficeView", "open_moderation_flag_count", ), - json_number_safe_count("RadrootsTradeOrderWorkflowProjection", "revision_count"), - json_number_safe_count("RadrootsTradeOrderWorkflowProjection", "cancellation_count"), ]; const fn source_root(export_name: &'static str) -> TradeTypeInventoryEntry { @@ -105,6 +107,13 @@ const fn source_root(export_name: &'static str) -> TradeTypeInventoryEntry { } } +const fn source_support(export_name: &'static str) -> TradeTypeInventoryEntry { + TradeTypeInventoryEntry { + export_name, + disposition: TradeTypeDisposition::SourceTradeSupport, + } +} + const fn event_import(export_name: &'static str) -> TradeTypeInventoryEntry { TradeTypeInventoryEntry { export_name, @@ -165,7 +174,10 @@ mod tests { "RadrootsListingProduct", "RadrootsListingPublicLocation", "RadrootsListingStatus", + "RadrootsOrderEconomics", "RadrootsOrderEventType", + "RadrootsOrderInventoryCommitment", + "RadrootsOrderIssue", "RadrootsTradeFacetCount", "RadrootsTradeListing", "RadrootsTradeListingBackofficeOverlay", @@ -213,7 +225,9 @@ mod tests { "RadrootsListingProduct", "RadrootsListingPublicLocation", "RadrootsListingStatus", + "RadrootsOrderEconomics", "RadrootsOrderEventType", + "RadrootsOrderInventoryCommitment", ] { assert_eq!( disposition(export_name), @@ -236,12 +250,21 @@ mod tests { "RadrootsTradeListing", "RadrootsTradeListingSubtotal", "RadrootsTradeListingTotal", + "RadrootsTradeOrderWorkflowProjection", "RadrootsTradeWorkflowState" ] ); } #[test] + fn trade_source_support_types_are_marked_for_source_registry() { + assert_eq!( + disposition("RadrootsOrderIssue"), + TradeTypeDisposition::SourceTradeSupport + ); + } + + #[test] fn trade_large_integer_policy_covers_current_count_fields() { let actual = TRADE_LARGE_INTEGER_POLICIES .iter() @@ -306,16 +329,6 @@ mod tests { "open_moderation_flag_count", super::TradeLargeIntegerPolicy::JsonNumberSafeCount ), - ( - "RadrootsTradeOrderWorkflowProjection", - "revision_count", - super::TradeLargeIntegerPolicy::JsonNumberSafeCount - ), - ( - "RadrootsTradeOrderWorkflowProjection", - "cancellation_count", - super::TradeLargeIntegerPolicy::JsonNumberSafeCount - ), ] ); } diff --git a/packages/trade-bindings/src/generated/types.ts b/packages/trade-bindings/src/generated/types.ts @@ -4,7 +4,6 @@ import type { RadrootsCoreCurrency, RadrootsCoreDecimal, RadrootsCoreDiscount, - RadrootsCoreDiscountValue, RadrootsCoreMoney, RadrootsCoreQuantity, RadrootsCoreUnit, @@ -18,14 +17,15 @@ import type { RadrootsListingImage, RadrootsListingProduct, RadrootsListingPublicLocation, - RadrootsNostrEventPtr, - RadrootsOrderEconomicLine, + RadrootsOrderEconomics, RadrootsOrderEventType, - RadrootsOrderItem, + RadrootsOrderInventoryCommitment, RadrootsPlotRef, RadrootsResourceAreaRef, } from "@radroots/events-bindings"; +export type RadrootsOrderIssue = "missing_request" | { multiple_requests: { event_ids: Array<string>, }, } | { request_payload_invalid: { event_id: string, }, } | { request_order_id_mismatch: { event_id: string, }, } | { request_author_mismatch: { event_id: string, }, } | { request_listing_address_invalid: { event_id: string, }, } | { request_seller_listing_mismatch: { event_id: string, }, } | { decision_payload_invalid: { event_id: string, }, } | { decision_order_id_mismatch: { event_id: string, }, } | { decision_author_mismatch: { event_id: string, }, } | { decision_counterparty_mismatch: { event_id: string, }, } | { decision_buyer_mismatch: { event_id: string, }, } | { decision_seller_mismatch: { event_id: string, }, } | { decision_listing_address_invalid: { event_id: string, }, } | { decision_listing_mismatch: { event_id: string, }, } | { decision_root_mismatch: { event_id: string, }, } | { decision_previous_mismatch: { event_id: string, }, } | { decision_missing_inventory_commitments: { event_id: string, }, } | { decision_inventory_commitment_mismatch: { event_id: string, }, } | { decision_missing_reason: { event_id: string, }, } | { conflicting_decisions: { event_ids: Array<string>, }, } | { revision_proposal_payload_invalid: { event_id: string, }, } | { revision_proposal_order_id_mismatch: { event_id: string, }, } | { revision_proposal_author_mismatch: { event_id: string, }, } | { revision_proposal_counterparty_mismatch: { event_id: string, }, } | { revision_proposal_buyer_mismatch: { event_id: string, }, } | { revision_proposal_seller_mismatch: { event_id: string, }, } | { revision_proposal_listing_address_invalid: { event_id: string, }, } | { revision_proposal_listing_mismatch: { event_id: string, }, } | { revision_proposal_root_mismatch: { event_id: string, }, } | { revision_proposal_previous_mismatch: { event_id: string, }, } | { revision_decision_without_proposal: { event_id: string, }, } | { revision_decision_payload_invalid: { event_id: string, }, } | { revision_decision_order_id_mismatch: { event_id: string, }, } | { revision_decision_author_mismatch: { event_id: string, }, } | { revision_decision_counterparty_mismatch: { event_id: string, }, } | { revision_decision_buyer_mismatch: { event_id: string, }, } | { revision_decision_seller_mismatch: { event_id: string, }, } | { revision_decision_listing_address_invalid: { event_id: string, }, } | { revision_decision_listing_mismatch: { event_id: string, }, } | { revision_decision_root_mismatch: { event_id: string, }, } | { revision_decision_previous_mismatch: { event_id: string, }, } | { revision_decision_revision_id_mismatch: { event_id: string, }, } | { cancellation_without_cancellable_order: { event_id: string, }, } | { cancellation_payload_invalid: { event_id: string, }, } | { cancellation_order_id_mismatch: { event_id: string, }, } | { cancellation_author_mismatch: { event_id: string, }, } | { cancellation_counterparty_mismatch: { event_id: string, }, } | { cancellation_buyer_mismatch: { event_id: string, }, } | { cancellation_seller_mismatch: { event_id: string, }, } | { cancellation_listing_address_invalid: { event_id: string, }, } | { cancellation_listing_mismatch: { event_id: string, }, } | { cancellation_root_mismatch: { event_id: string, }, } | { cancellation_previous_mismatch: { event_id: string, }, } | { forked_lifecycle: { event_ids: Array<string>, }, } | { validation_receipt_without_pending_agreement: { event_id: string, }, } | { validation_receipt_order_id_mismatch: { event_id: string, }, } | { validation_receipt_type_mismatch: { event_id: string, }, } | { validation_receipt_root_mismatch: { event_id: string, }, } | { validation_receipt_target_mismatch: { event_id: string, }, } | { validation_receipt_listing_mismatch: { event_id: string, }, } | { conflicting_validation_receipts: { event_ids: Array<string>, }, } | { deterministic_validation_failure: { event_id: string, reason: string, }, } | { stale_listing_event: { expected_event_id: string, current_event_id: 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: RadrootsListingPublicLocation, delivery_method: RadrootsListingDeliveryMethod, listing: RadrootsListing, }; @@ -56,7 +56,7 @@ export type RadrootsTradeListingTotal = { price_amount: RadrootsCoreMoney, price export type RadrootsTradeMarketplaceListingSummary = { listing_addr: string, seller_pubkey: string, farm_pubkey: string, farm_id: string, product_key: string, product_title: string, product_category: string, product_summary?: string | null, listing_status: RadrootsTradeListingMarketStatus, location_primary?: string | null, inventory_available?: RadrootsCoreDecimal | null, primary_bin_id: string, primary_bin_label?: string | null, primary_bin_total: RadrootsTradeListingTotal, order_count: number, open_order_count: number, terminal_order_count: number, }; -export type RadrootsTradeMarketplaceOrderSummary = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, status: RadrootsTradeWorkflowState, last_message_type: RadrootsOrderEventType, item_count: number, total_bin_count: number, has_requested_discounts: boolean, last_reason?: string | null, }; +export type RadrootsTradeMarketplaceOrderSummary = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, status: RadrootsTradeWorkflowState, last_message_type: RadrootsOrderEventType, item_count: number, total_bin_count: number, last_reason?: string | null, }; export type RadrootsTradeModerationFlag = { code: string, severity: RadrootsTradeModerationSeverity, status: RadrootsTradeModerationStatus, source?: string | null, reason?: string | null, }; @@ -78,7 +78,7 @@ 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 RadrootsTradeOrderWorkflowProjection = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, items: Array<RadrootsOrderItem>, requested_discounts?: Array<RadrootsOrderEconomicLine> | null, status: RadrootsTradeWorkflowState, 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, revision_count: number, cancellation_count: number, last_message_type: RadrootsOrderEventType, last_actor_pubkey: string, }; +export type RadrootsTradeOrderWorkflowProjection = { order_id: string, status: RadrootsTradeWorkflowState, request_event_id?: string | null, decision_event_id?: string | null, cancellation_event_id?: string | null, validation_receipt_event_id?: string | null, lifecycle_terminal: boolean, economics?: RadrootsOrderEconomics | null, agreement_event_id?: string | null, pending_revision_event_id?: string | null, pending_inventory_reservations: Array<RadrootsOrderInventoryCommitment>, committed_inventory_reservations: Array<RadrootsOrderInventoryCommitment>, listing_addr?: string | null, buyer_pubkey?: string | null, seller_pubkey?: string | null, last_event_id?: string | null, issues: Array<RadrootsOrderIssue>, }; export type RadrootsTradeReviewPriority = "low" | "normal" | "high" | "critical"; diff --git a/tools/xtask/src/dto_roots.rs b/tools/xtask/src/dto_roots.rs @@ -157,9 +157,16 @@ const TRADE_EXTERNAL_OVERRIDES: &[DtoExternalOverride] = &[ events_override("RadrootsNostrEventPtr"), events_override("RadrootsPlotRef"), events_override("RadrootsResourceAreaRef"), + events_override("RadrootsOrderEconomicActor"), + events_override("RadrootsOrderEconomicEffect"), + events_override("RadrootsOrderEconomicItem"), events_override("RadrootsOrderEconomicLine"), + events_override("RadrootsOrderEconomicLineKind"), + events_override("RadrootsOrderEconomics"), events_override("RadrootsOrderEventType"), + events_override("RadrootsOrderInventoryCommitment"), events_override("RadrootsOrderItem"), + events_override("RadrootsOrderPricingBasis"), ]; const TRADE_REQUIRED_EXTERNAL_PACKAGE_IMPORTS: &[&str] = @@ -217,7 +224,7 @@ pub fn replica_db_schema_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(); - let options = trade_import_options(DtoRegistryRenderOptions::default())?; + let options = trade_import_options(&registry, DtoRegistryRenderOptions::default())?; let rendered = render_registry_types(&registry, &options)?; validate_external_override_usage(&rendered, TRADE_EXTERNAL_OVERRIDES)?; Ok(rendered) @@ -286,11 +293,19 @@ fn with_checked_external_type( } fn trade_import_options( + registry: &Registry, mut options: DtoRegistryRenderOptions, ) -> Result<DtoRegistryRenderOptions, String> { let package_exports = generated_external_package_exports()?; for override_target in TRADE_EXTERNAL_OVERRIDES { validate_external_override_target(*override_target, &package_exports)?; + if let Ok(type_id) = registry.type_id_by_export_name(override_target.target_type) { + options = options.with_external_type( + type_id, + override_target.import_name, + override_target.from, + ); + } options = options.with_external_override( override_target.target_type, override_target.import_name, @@ -624,6 +639,7 @@ mod tests { "RadrootsEventsIndexedIndexCheckpoint", ]; const TRADE_TYPE_INVENTORY: &[&str] = &[ + "RadrootsOrderIssue", "RadrootsTradeFacetCount", "RadrootsTradeListing", "RadrootsTradeListingBackofficeOverlay", @@ -760,7 +776,9 @@ mod tests { #[test] fn trade_external_override_targets_resolve_to_generated_exports() { - trade_import_options(DtoRegistryRenderOptions::default()) + let registry = package_root_set("trade").expect("trade roots").registry(); + + trade_import_options(&registry, DtoRegistryRenderOptions::default()) .expect("trade external overrides validate"); } @@ -918,10 +936,22 @@ mod tests { .get("@radroots/events-bindings") .is_some_and(|names| names.contains("RadrootsOrderEventType")) ); + assert!( + imports + .get("@radroots/events-bindings") + .is_some_and(|names| names.contains("RadrootsOrderEconomics")) + ); + assert!( + imports + .get("@radroots/events-bindings") + .is_some_and(|names| names.contains("RadrootsOrderInventoryCommitment")) + ); for duplicate in [ "export type RadrootsListing = ", "export type RadrootsFarmRef = ", + "export type RadrootsOrderEconomics = ", + "export type RadrootsOrderInventoryCommitment = ", "export type RadrootsCommercialMessagePayload = ", "export type RadrootsCommercialMessageType = ", "export type RadrootsOrderStatus = ", @@ -936,6 +966,7 @@ mod tests { ); assert!(marketplace_order_summary.contains("status: RadrootsTradeWorkflowState")); assert!(marketplace_order_summary.contains("last_message_type: RadrootsOrderEventType")); + assert!(!marketplace_order_summary.contains("has_requested_discounts")); let order_query = type_declaration(TRADE_BINDINGS_TYPES_TS, "RadrootsTradeOrderQuery"); assert!(order_query.contains("status?: RadrootsTradeWorkflowState | null")); @@ -945,8 +976,17 @@ mod tests { "RadrootsTradeOrderWorkflowProjection", ); assert!(workflow_projection.contains("status: RadrootsTradeWorkflowState")); - assert!(workflow_projection.contains("last_message_type: RadrootsOrderEventType")); + assert!(workflow_projection.contains("request_event_id?: string | null")); + assert!(workflow_projection.contains("last_event_id?: string | null")); + assert!(workflow_projection.contains("listing_addr?: string | null")); for stale_counter in [ + "root_event_id", + "last_message_type", + "last_discount_request", + "last_discount_offer", + "accepted_discount", + "last_discount_decline_reason", + "has_requested_discounts", "question_count", "answer_count", "discount_request_count",