commit eec2badb91364f5d4735d0b375aa0ce51c5f23d0
parent 319c978911b90655c3e363b4ac0cd333dfca5cc5
Author: triesap <tyson@radroots.org>
Date: Sun, 29 Mar 2026 17:08:25 +0000
trade: reduce public crate boundary to workflow ownership
- point trade workflow code at canonical radroots-events and radroots-events-codec trade models
- make the legacy listing codec and contract modules internal to radroots-trade
- replace duplicated trade validation error ownership with canonical trade error types
- wire the required serde_json and std feature plumbing for the shared codec path
Diffstat:
12 files changed, 160 insertions(+), 174 deletions(-)
diff --git a/crates/events-codec/src/trade/decode.rs b/crates/events-codec/src/trade/decode.rs
@@ -1,5 +1,5 @@
-#[cfg(not(feature = "std"))]
-use alloc::{format, string::String};
+#[cfg(all(not(feature = "std"), feature = "serde_json"))]
+use alloc::{borrow::ToOwned, format, string::String, vec::Vec};
#[cfg(feature = "serde_json")]
use radroots_events::{
@@ -188,8 +188,7 @@ pub fn trade_envelope_from_event<T: DeserializeOwned>(
#[cfg(all(test, feature = "serde_json"))]
mod tests {
use super::{
- RadrootsTradeEnvelopeParseError, RadrootsTradeListingAddress,
- trade_envelope_from_event,
+ RadrootsTradeEnvelopeParseError, RadrootsTradeListingAddress, trade_envelope_from_event,
};
use crate::trade::encode::trade_envelope_event_build;
use radroots_events::{
@@ -245,7 +244,10 @@ mod tests {
};
let envelope: RadrootsTradeEnvelope<RadrootsTradeMessagePayload> =
trade_envelope_from_event(&event).expect("parse trade envelope");
- assert_eq!(envelope.message_type, RadrootsTradeMessageType::OrderRequest);
+ assert_eq!(
+ envelope.message_type,
+ RadrootsTradeMessageType::OrderRequest
+ );
assert_eq!(envelope.order_id.as_deref(), Some("order-1"));
}
diff --git a/crates/events-codec/src/trade/encode.rs b/crates/events-codec/src/trade/encode.rs
@@ -1,3 +1,6 @@
+#[cfg(all(not(feature = "std"), feature = "serde_json"))]
+use alloc::string::String;
+
#[cfg(feature = "serde_json")]
use radroots_events::trade::{RadrootsTradeEnvelope, RadrootsTradeMessageType};
diff --git a/crates/events-codec/src/trade/mod.rs b/crates/events-codec/src/trade/mod.rs
@@ -4,8 +4,8 @@ pub mod tags;
#[cfg(feature = "serde_json")]
pub use decode::{
- RadrootsTradeEnvelopeParseError, RadrootsTradeListingAddress,
- RadrootsTradeListingAddressError, trade_envelope_from_event,
+ RadrootsTradeEnvelopeParseError, RadrootsTradeListingAddress, RadrootsTradeListingAddressError,
+ trade_envelope_from_event,
};
#[cfg(feature = "serde_json")]
pub use encode::trade_envelope_event_build;
diff --git a/crates/events-codec/src/trade/tags.rs b/crates/events-codec/src/trade/tags.rs
@@ -1,5 +1,5 @@
#[cfg(not(feature = "std"))]
-use alloc::{string::String, vec::Vec};
+use alloc::{borrow::ToOwned, string::String, vec::Vec};
use radroots_events::tags::{TAG_D, TAG_E_PREV, TAG_E_ROOT};
@@ -93,10 +93,11 @@ pub fn validate_trade_chain(tags: &[Vec<String>]) -> Result<(), JobParseError> {
#[cfg(test)]
mod tests {
- use super::{
- push_trade_chain_tags, trade_envelope_tags, validate_trade_chain,
+ use super::{push_trade_chain_tags, trade_envelope_tags, validate_trade_chain};
+ use radroots_events::{
+ kinds::KIND_LISTING,
+ tags::{TAG_D, TAG_E_PREV, TAG_E_ROOT},
};
- use radroots_events::{kinds::KIND_LISTING, tags::{TAG_D, TAG_E_PREV, TAG_E_ROOT}};
#[test]
fn trade_envelope_tags_build_expected_tags() {
diff --git a/crates/events/src/kinds.rs b/crates/events/src/kinds.rs
@@ -307,8 +307,14 @@ mod kinds_constants_tests {
("KIND_APP_DATA", KIND_APP_DATA),
("KIND_LISTING", KIND_LISTING),
("KIND_APPLICATION_HANDLER", KIND_APPLICATION_HANDLER),
- ("KIND_TRADE_LISTING_VALIDATE_REQ", KIND_TRADE_LISTING_VALIDATE_REQ),
- ("KIND_TRADE_LISTING_VALIDATE_RES", KIND_TRADE_LISTING_VALIDATE_RES),
+ (
+ "KIND_TRADE_LISTING_VALIDATE_REQ",
+ KIND_TRADE_LISTING_VALIDATE_REQ,
+ ),
+ (
+ "KIND_TRADE_LISTING_VALIDATE_RES",
+ KIND_TRADE_LISTING_VALIDATE_RES,
+ ),
("KIND_TRADE_LISTING_ORDER_REQ", KIND_TRADE_LISTING_ORDER_REQ),
("KIND_TRADE_LISTING_ORDER_RES", KIND_TRADE_LISTING_ORDER_RES),
(
@@ -319,9 +325,18 @@ mod kinds_constants_tests {
"KIND_TRADE_LISTING_ORDER_REVISION_RES",
KIND_TRADE_LISTING_ORDER_REVISION_RES,
),
- ("KIND_TRADE_LISTING_QUESTION_REQ", KIND_TRADE_LISTING_QUESTION_REQ),
- ("KIND_TRADE_LISTING_ANSWER_RES", KIND_TRADE_LISTING_ANSWER_RES),
- ("KIND_TRADE_LISTING_DISCOUNT_REQ", KIND_TRADE_LISTING_DISCOUNT_REQ),
+ (
+ "KIND_TRADE_LISTING_QUESTION_REQ",
+ KIND_TRADE_LISTING_QUESTION_REQ,
+ ),
+ (
+ "KIND_TRADE_LISTING_ANSWER_RES",
+ KIND_TRADE_LISTING_ANSWER_RES,
+ ),
+ (
+ "KIND_TRADE_LISTING_DISCOUNT_REQ",
+ KIND_TRADE_LISTING_DISCOUNT_REQ,
+ ),
(
"KIND_TRADE_LISTING_DISCOUNT_OFFER_RES",
KIND_TRADE_LISTING_DISCOUNT_OFFER_RES,
@@ -334,12 +349,18 @@ mod kinds_constants_tests {
"KIND_TRADE_LISTING_DISCOUNT_DECLINE_REQ",
KIND_TRADE_LISTING_DISCOUNT_DECLINE_REQ,
),
- ("KIND_TRADE_LISTING_CANCEL_REQ", KIND_TRADE_LISTING_CANCEL_REQ),
+ (
+ "KIND_TRADE_LISTING_CANCEL_REQ",
+ KIND_TRADE_LISTING_CANCEL_REQ,
+ ),
(
"KIND_TRADE_LISTING_FULFILLMENT_UPDATE_REQ",
KIND_TRADE_LISTING_FULFILLMENT_UPDATE_REQ,
),
- ("KIND_TRADE_LISTING_RECEIPT_REQ", KIND_TRADE_LISTING_RECEIPT_REQ),
+ (
+ "KIND_TRADE_LISTING_RECEIPT_REQ",
+ KIND_TRADE_LISTING_RECEIPT_REQ,
+ ),
("KIND_JOB_REQUEST_MIN", KIND_JOB_REQUEST_MIN),
("KIND_JOB_REQUEST_MAX", KIND_JOB_REQUEST_MAX),
("KIND_JOB_RESULT_MIN", KIND_JOB_RESULT_MIN),
diff --git a/crates/events/src/trade.rs b/crates/events/src/trade.rs
@@ -51,11 +51,19 @@ impl std::error::Error for RadrootsTradeListingParseError {}
)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RadrootsTradeListingValidationError {
- InvalidKind { kind: u32 },
+ InvalidKind {
+ kind: u32,
+ },
MissingListingId,
- ListingEventNotFound { listing_addr: String },
- ListingEventFetchFailed { listing_addr: String },
- ParseError { error: RadrootsTradeListingParseError },
+ ListingEventNotFound {
+ listing_addr: String,
+ },
+ ListingEventFetchFailed {
+ listing_addr: String,
+ },
+ ParseError {
+ error: RadrootsTradeListingParseError,
+ },
InvalidSeller,
MissingFarmProfile,
MissingFarmRecord,
@@ -309,10 +317,7 @@ pub struct RadrootsTradeListingValidateRequest {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RadrootsTradeListingValidateResult {
pub valid: bool,
- #[cfg_attr(
- feature = "ts-rs",
- ts(type = "RadrootsTradeListingValidationError[]")
- )]
+ #[cfg_attr(feature = "ts-rs", ts(type = "RadrootsTradeListingValidationError[]"))]
pub errors: Vec<RadrootsTradeListingValidationError>,
}
@@ -426,7 +431,10 @@ impl RadrootsTradeMessageType {
#[inline]
pub const fn requires_order_id(self) -> bool {
- !matches!(self, Self::ListingValidateRequest | Self::ListingValidateResult)
+ !matches!(
+ self,
+ Self::ListingValidateRequest | Self::ListingValidateResult
+ )
}
#[inline]
@@ -516,7 +524,10 @@ impl core::fmt::Display for RadrootsTradeEnvelopeError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::InvalidVersion { expected, got } => {
- write!(f, "invalid envelope version: expected {expected}, got {got}")
+ write!(
+ f,
+ "invalid envelope version: expected {expected}, got {got}"
+ )
}
Self::MissingOrderId => write!(f, "missing order_id for order-scoped message"),
Self::MissingListingAddr => write!(f, "missing listing_addr"),
diff --git a/crates/trade/Cargo.toml b/crates/trade/Cargo.toml
@@ -7,7 +7,7 @@ authors = [
]
rust-version.workspace = true
license.workspace = true
-description = "trade listing models and tag mappings for radroots nostr flows"
+description = "workflow validation projections and read models for radroots trade flows"
repository.workspace = true
homepage.workspace = true
documentation = "https://docs.rs/radroots-trade"
@@ -16,14 +16,18 @@ build = "build.rs"
[features]
default = ["std", "serde", "serde_json", "ts-rs"]
-std = []
+std = ["radroots-core/std", "radroots-events/std", "radroots-events-codec/std"]
serde = [
"dep:serde",
"radroots-core/serde",
"radroots-events/serde",
"radroots-events-codec/serde",
]
-serde_json = ["serde", "dep:serde_json"]
+serde_json = [
+ "serde",
+ "dep:serde_json",
+ "radroots-events-codec/serde_json",
+]
ts-rs = ["dep:ts-rs", "radroots-events/ts-rs", "radroots-events/std"]
[dependencies]
diff --git a/crates/trade/src/listing/codec.rs b/crates/trade/src/listing/codec.rs
@@ -17,11 +17,10 @@ use radroots_events::listing::{
use radroots_events::plot::RadrootsPlotRef;
use radroots_events::resource_area::RadrootsResourceAreaRef;
use radroots_events::tags::TAG_D;
+pub(crate) use radroots_events::trade::RadrootsTradeListingParseError as TradeListingParseError;
use radroots_events_codec::d_tag::is_d_tag_base64url;
use radroots_events_codec::error::EventEncodeError;
-use radroots_events_codec::listing::tags::{ListingTagOptions, listing_tags_with_options};
-#[cfg(feature = "ts-rs")]
-use ts_rs::TS;
+use radroots_events_codec::listing::tags::listing_tags_full;
const TAG_PRICE: &str = "price";
const TAG_RADROOTS_BIN: &str = "radroots:bin";
@@ -41,39 +40,6 @@ const TAG_EXPIRES_AT: &str = "expires_at";
const TAG_P: &str = "p";
const TAG_A: &str = "a";
-#[cfg_attr(feature = "ts-rs", derive(TS))]
-#[cfg_attr(feature = "ts-rs", ts(export, export_to = "types.ts"))]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum TradeListingParseError {
- MissingTag(String),
- InvalidTag(String),
- InvalidNumber(String),
- InvalidUnit,
- InvalidCurrency,
- InvalidJson(String),
- InvalidDiscount(String),
-}
-
-impl core::fmt::Display for TradeListingParseError {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- match self {
- TradeListingParseError::MissingTag(tag) => write!(f, "missing required tag: {tag}"),
- TradeListingParseError::InvalidTag(tag) => write!(f, "invalid tag: {tag}"),
- TradeListingParseError::InvalidNumber(field) => write!(f, "invalid number: {field}"),
- TradeListingParseError::InvalidUnit => write!(f, "invalid unit"),
- TradeListingParseError::InvalidCurrency => write!(f, "invalid currency"),
- TradeListingParseError::InvalidJson(field) => write!(f, "invalid json: {field}"),
- TradeListingParseError::InvalidDiscount(kind) => {
- write!(f, "invalid discount data for {kind}")
- }
- }
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for TradeListingParseError {}
-
fn parse_decimal(s: &str, field: &str) -> Result<RadrootsCoreDecimal, TradeListingParseError> {
s.parse::<RadrootsCoreDecimal>()
.map_err(|_| TradeListingParseError::InvalidNumber(field.to_string()))
@@ -171,13 +137,14 @@ pub fn listing_from_event_parts(
listing_from_tags(tags, d_tag, farm_ref, farm_pubkey, resource_area, plot)
}
+#[allow(dead_code)]
pub fn listing_tags_build(
listing: &RadrootsListing,
) -> Result<Vec<Vec<String>>, TradeListingParseError> {
- let options = ListingTagOptions::with_trade_fields();
- listing_tags_with_options(listing, options).map_err(map_listing_tags_error)
+ listing_tags_full(listing).map_err(map_listing_tags_error)
}
+#[allow(dead_code)]
fn map_listing_tags_error(err: EventEncodeError) -> TradeListingParseError {
match err {
EventEncodeError::EmptyRequiredField(field) => {
diff --git a/crates/trade/src/listing/contract.rs b/crates/trade/src/listing/contract.rs
@@ -0,0 +1,62 @@
+#![forbid(unsafe_code)]
+
+#[allow(unused_imports)]
+#[cfg(feature = "serde_json")]
+use radroots_events::RadrootsNostrEvent;
+#[allow(unused_imports)]
+pub(crate) use radroots_events::{
+ kinds::{
+ KIND_TRADE_LISTING_ANSWER_RES, KIND_TRADE_LISTING_CANCEL_REQ,
+ KIND_TRADE_LISTING_DISCOUNT_ACCEPT_REQ, KIND_TRADE_LISTING_DISCOUNT_DECLINE_REQ,
+ KIND_TRADE_LISTING_DISCOUNT_OFFER_RES, KIND_TRADE_LISTING_DISCOUNT_REQ,
+ KIND_TRADE_LISTING_FULFILLMENT_UPDATE_REQ, KIND_TRADE_LISTING_ORDER_REQ,
+ KIND_TRADE_LISTING_ORDER_RES, KIND_TRADE_LISTING_ORDER_REVISION_REQ,
+ KIND_TRADE_LISTING_ORDER_REVISION_RES, KIND_TRADE_LISTING_QUESTION_REQ,
+ KIND_TRADE_LISTING_RECEIPT_REQ, KIND_TRADE_LISTING_VALIDATE_REQ,
+ KIND_TRADE_LISTING_VALIDATE_RES, TRADE_LISTING_KINDS, is_trade_listing_kind,
+ },
+ trade::{
+ RADROOTS_TRADE_ENVELOPE_VERSION as TRADE_LISTING_ENVELOPE_VERSION,
+ RADROOTS_TRADE_LISTING_DOMAIN as TRADE_LISTING_DOMAIN, RadrootsTradeAnswer as TradeAnswer,
+ RadrootsTradeDiscountDecision as TradeDiscountDecision,
+ RadrootsTradeDiscountOffer as TradeDiscountOffer,
+ RadrootsTradeDiscountRequest as TradeDiscountRequest,
+ RadrootsTradeEnvelope as TradeListingEnvelope,
+ RadrootsTradeEnvelopeError as TradeListingEnvelopeError,
+ RadrootsTradeFulfillmentStatus as TradeFulfillmentStatus,
+ RadrootsTradeFulfillmentUpdate as TradeFulfillmentUpdate,
+ RadrootsTradeListingCancel as TradeListingCancel,
+ RadrootsTradeListingParseError as TradeListingParseError,
+ RadrootsTradeListingValidateRequest as TradeListingValidateRequest,
+ RadrootsTradeListingValidateResult as TradeListingValidateResult,
+ RadrootsTradeListingValidationError as TradeListingValidationError,
+ RadrootsTradeMessagePayload as TradeListingMessagePayload,
+ RadrootsTradeMessageType as TradeListingMessageType, RadrootsTradeOrder as TradeOrder,
+ RadrootsTradeOrderChange as TradeOrderChange, RadrootsTradeOrderItem as TradeOrderItem,
+ RadrootsTradeOrderResponse as TradeOrderResponse,
+ RadrootsTradeOrderRevision as TradeOrderRevision,
+ RadrootsTradeOrderRevisionResponse as TradeOrderRevisionResponse,
+ RadrootsTradeOrderStatus as TradeOrderStatus, RadrootsTradeQuestion as TradeQuestion,
+ RadrootsTradeReceipt as TradeReceipt,
+ },
+};
+#[allow(unused_imports)]
+#[cfg(feature = "serde_json")]
+pub(crate) use radroots_events_codec::trade::{
+ decode::{
+ RadrootsTradeEnvelopeParseError as TradeListingEnvelopeParseError,
+ RadrootsTradeListingAddress as TradeListingAddress,
+ RadrootsTradeListingAddressError as TradeListingAddressError, trade_envelope_from_event,
+ },
+ encode::trade_envelope_event_build as trade_listing_envelope_event_build,
+};
+
+#[cfg(feature = "serde_json")]
+use serde::de::DeserializeOwned;
+
+#[cfg(feature = "serde_json")]
+pub(crate) fn trade_listing_envelope_from_event<T: DeserializeOwned>(
+ event: &RadrootsNostrEvent,
+) -> Result<TradeListingEnvelope<T>, TradeListingEnvelopeParseError> {
+ trade_envelope_from_event(event)
+}
diff --git a/crates/trade/src/listing/mod.rs b/crates/trade/src/listing/mod.rs
@@ -1,10 +1,12 @@
-pub mod codec;
-pub mod dvm;
-pub mod kinds;
+mod codec;
+pub(crate) mod contract;
pub mod model;
-pub mod order;
pub mod overlay;
pub mod price_ext;
pub mod projection;
-pub mod tags;
pub mod validation;
+
+pub(crate) use self::contract as dvm;
+#[allow(unused_imports)]
+pub(crate) use self::contract as kinds;
+pub(crate) use self::contract as order;
diff --git a/crates/trade/src/listing/projection.rs b/crates/trade/src/listing/projection.rs
@@ -25,8 +25,8 @@ use ts_rs::TS;
use crate::listing::{
codec::{TradeListingParseError, listing_from_event_parts},
dvm::{
- TradeListingEnvelope, TradeListingEnvelopeParseError, TradeListingMessagePayload,
- TradeListingMessageType,
+ TradeListingEnvelopeParseError, TradeListingMessagePayload, TradeListingMessageType,
+ trade_listing_envelope_from_event,
},
model::RadrootsTradeListingTotal,
order::{
@@ -109,7 +109,7 @@ pub struct RadrootsTradeOrderWorkflowProjection {
pub listing_addr: String,
pub buyer_pubkey: String,
pub seller_pubkey: String,
- #[cfg_attr(feature = "ts-rs", ts(type = "TradeOrderItem[]"))]
+ #[cfg_attr(feature = "ts-rs", ts(type = "RadrootsTradeOrderItem[]"))]
pub items: Vec<TradeOrderItem>,
#[cfg_attr(
feature = "ts-rs",
@@ -136,7 +136,7 @@ pub struct RadrootsTradeOrderWorkflowProjection {
pub accepted_discount: Option<RadrootsCoreDiscountValue>,
#[cfg_attr(
feature = "ts-rs",
- ts(optional, type = "TradeFulfillmentStatus | null")
+ ts(optional, type = "RadrootsTradeFulfillmentStatus | null")
)]
pub last_fulfillment_status: Option<TradeFulfillmentStatus>,
#[cfg_attr(feature = "ts-rs", ts(optional, type = "bool | null"))]
@@ -170,7 +170,7 @@ pub struct RadrootsTradeOrderWorkflowMessage {
pub listing_addr: String,
#[cfg_attr(feature = "ts-rs", ts(optional, type = "string | null"))]
pub order_id: Option<String>,
- #[cfg_attr(feature = "ts-rs", ts(type = "TradeListingMessagePayload"))]
+ #[cfg_attr(feature = "ts-rs", ts(type = "RadrootsTradeMessagePayload"))]
pub payload: TradeListingMessagePayload,
}
@@ -263,7 +263,10 @@ pub struct RadrootsTradeOrderQuery {
pub buyer_pubkey: Option<String>,
#[cfg_attr(feature = "ts-rs", ts(optional, type = "string | null"))]
pub seller_pubkey: Option<String>,
- #[cfg_attr(feature = "ts-rs", ts(optional, type = "TradeOrderStatus | null"))]
+ #[cfg_attr(
+ feature = "ts-rs",
+ ts(optional, type = "RadrootsTradeOrderStatus | null")
+ )]
pub status: Option<TradeOrderStatus>,
}
@@ -662,7 +665,7 @@ impl RadrootsTradeOrderWorkflowProjection {
impl RadrootsTradeOrderWorkflowMessage {
#[cfg(feature = "serde_json")]
pub fn from_event(event: &RadrootsNostrEvent) -> Result<Self, TradeListingEnvelopeParseError> {
- let envelope = TradeListingEnvelope::<TradeListingMessagePayload>::from_event(event)?;
+ let envelope = trade_listing_envelope_from_event::<TradeListingMessagePayload>(event)?;
Ok(Self {
actor_pubkey: event.author.clone(),
listing_addr: envelope.listing_addr,
diff --git a/crates/trade/src/listing/validation.rs b/crates/trade/src/listing/validation.rs
@@ -13,11 +13,12 @@ use radroots_events::{
RadrootsListing, RadrootsListingAvailability, RadrootsListingDeliveryMethod,
RadrootsListingLocation,
},
+ trade::RadrootsTradeListingValidationError as TradeListingValidationError,
};
#[cfg(feature = "ts-rs")]
use ts_rs::TS;
-use crate::listing::codec::{TradeListingParseError, listing_from_event_parts};
+use crate::listing::codec::listing_from_event_parts;
use crate::listing::dvm::TradeListingAddress;
#[cfg_attr(feature = "ts-rs", derive(TS))]
@@ -46,97 +47,6 @@ pub struct RadrootsTradeListing {
pub listing: RadrootsListing,
}
-#[cfg_attr(feature = "ts-rs", derive(TS))]
-#[cfg_attr(feature = "ts-rs", ts(export, export_to = "types.ts"))]
-#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
-#[cfg_attr(
- feature = "serde",
- serde(rename_all = "snake_case", tag = "kind", content = "amount")
-)]
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum TradeListingValidationError {
- InvalidKind { kind: u32 },
- MissingListingId,
- ListingEventNotFound { listing_addr: String },
- ListingEventFetchFailed { listing_addr: String },
- ParseError { error: TradeListingParseError },
- InvalidSeller,
- MissingFarmProfile,
- MissingFarmRecord,
- MissingTitle,
- MissingDescription,
- MissingProductType,
- MissingBins,
- MissingPrimaryBin,
- InvalidBin,
- MissingPrice,
- InvalidPrice,
- MissingInventory,
- InvalidInventory,
- MissingAvailability,
- MissingLocation,
- MissingDeliveryMethod,
-}
-
-impl core::fmt::Display for TradeListingValidationError {
- fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
- match self {
- TradeListingValidationError::InvalidKind { kind } => {
- write!(f, "invalid listing kind: {kind}")
- }
- TradeListingValidationError::MissingListingId => write!(f, "missing listing id"),
- TradeListingValidationError::ListingEventNotFound { listing_addr } => {
- write!(f, "listing event not found: {listing_addr}")
- }
- TradeListingValidationError::ListingEventFetchFailed { listing_addr } => {
- write!(f, "listing event fetch failed: {listing_addr}")
- }
- TradeListingValidationError::ParseError { error } => {
- write!(f, "invalid listing data: {error}")
- }
- TradeListingValidationError::InvalidSeller => {
- write!(f, "listing author does not match farm pubkey")
- }
- TradeListingValidationError::MissingFarmProfile => {
- write!(f, "missing farm profile")
- }
- TradeListingValidationError::MissingFarmRecord => {
- write!(f, "missing farm record")
- }
- TradeListingValidationError::MissingTitle => write!(f, "missing listing title"),
- TradeListingValidationError::MissingDescription => {
- write!(f, "missing listing description")
- }
- TradeListingValidationError::MissingProductType => {
- write!(f, "missing listing product type")
- }
- TradeListingValidationError::MissingBins => write!(f, "missing listing bins"),
- TradeListingValidationError::MissingPrimaryBin => {
- write!(f, "missing primary listing bin")
- }
- TradeListingValidationError::InvalidBin => write!(f, "invalid listing bin"),
- TradeListingValidationError::MissingPrice => write!(f, "missing listing price"),
- TradeListingValidationError::InvalidPrice => write!(f, "invalid listing price"),
- TradeListingValidationError::MissingInventory => {
- write!(f, "missing listing inventory")
- }
- TradeListingValidationError::InvalidInventory => {
- write!(f, "invalid listing inventory")
- }
- TradeListingValidationError::MissingAvailability => {
- write!(f, "missing listing availability")
- }
- TradeListingValidationError::MissingLocation => write!(f, "missing listing location"),
- TradeListingValidationError::MissingDeliveryMethod => {
- write!(f, "missing listing delivery method")
- }
- }
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for TradeListingValidationError {}
-
pub fn validate_listing_event(
event: &RadrootsNostrEvent,
) -> Result<RadrootsTradeListing, TradeListingValidationError> {
@@ -153,7 +63,7 @@ pub fn validate_listing_event(
return Err(TradeListingValidationError::InvalidSeller);
}
let listing_addr = TradeListingAddress {
- kind: KIND_LISTING as u16,
+ kind: KIND_LISTING,
seller_pubkey: seller_pubkey.clone(),
listing_id: listing_id.clone(),
}