commit a1f46d6bd6a632971de82903f6395da93688836e
parent 78aca54a2b55b31408f6a9108de5a26c908057fe
Author: triesap <tyson@radroots.org>
Date: Fri, 12 Jun 2026 21:36:57 -0700
events: add two-layer contract registry
Diffstat:
1 file changed, 2649 insertions(+), 475 deletions(-)
diff --git a/crates/events/src/contract.rs b/crates/events/src/contract.rs
@@ -1,13 +1,9 @@
#![forbid(unsafe_code)]
-use crate::kinds::{
- KIND_LISTING, KIND_LISTING_DRAFT, KIND_ORDER_CANCELLATION, KIND_ORDER_DECISION,
- KIND_ORDER_FULFILLMENT_UPDATE, KIND_ORDER_PAYMENT_RECORD, KIND_ORDER_RECEIPT,
- KIND_ORDER_REQUEST, KIND_ORDER_REVISION_DECISION, KIND_ORDER_REVISION_PROPOSAL,
- KIND_ORDER_SETTLEMENT_DECISION, KIND_TRADE_LISTING_VALIDATION_REQUEST,
- KIND_TRADE_LISTING_VALIDATION_RESULT, KIND_TRADE_TRANSITION_PROOF_REQUEST,
- KIND_TRADE_TRANSITION_PROOF_RESULT, KIND_TRADE_VALIDATION_RECEIPT,
-};
+#[cfg(not(feature = "std"))]
+use alloc::{string::String, vec::Vec};
+
+use crate::kinds::*;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RadrootsEventClass {
@@ -18,6 +14,30 @@ pub enum RadrootsEventClass {
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum RadrootsNostrStandard {
+ Nip01,
+ Nip09,
+ Nip17,
+ Nip18,
+ Nip22,
+ Nip23,
+ Nip25,
+ Nip28,
+ Nip29,
+ Nip42,
+ Nip51,
+ Nip52,
+ Nip53,
+ Nip56,
+ Nip57,
+ Nip78,
+ Nip90,
+ Nip94,
+ Nip98,
+ Radroots,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RadrootsEventPrivacy {
Public,
Encrypted,
@@ -29,28 +49,47 @@ pub enum RadrootsEventPrivacy {
pub enum RadrootsEventStability {
Stable,
Experimental,
- Deprecated,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RadrootsActorRole {
Any,
+ Application,
+ Buyer,
Farmer,
+ Member,
+ Moderator,
+ Relay,
Seller,
- Buyer,
Service,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RadrootsReducer {
+ CalendarProjection,
+ FarmOpsProjection,
+ GroupProjection,
+ ListingInventoryAccounting,
ListingProjection,
MarketProjection,
OrderProjection,
- ListingInventoryAccounting,
+ ProfileProjection,
+ RelayPolicyProjection,
+ SocialProjection,
TradeValidation,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum RadrootsContentSchema {
+ Empty,
+ JsonObject,
+ PlainText,
+ Markdown,
+ Encrypted,
+ BinaryReference,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RadrootsTagCardinality {
RequiredOne,
OptionalOne,
@@ -60,22 +99,41 @@ pub enum RadrootsTagCardinality {
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RadrootsTagSemantic {
- Identifier,
+ AddressableCoordinate,
+ Category,
Counterparty,
+ EventPointer,
+ GroupId,
+ Identifier,
+ Image,
+ Kind,
ListingAddress,
- RootEvent,
- PreviousEvent,
ListingSnapshot,
- Title,
- Summary,
- PublishedAt,
Location,
+ PreviousEvent,
Price,
- Status,
- Category,
- Image,
+ PublishedAt,
+ Relay,
+ RootEvent,
ServiceInput,
ServiceOutput,
+ Status,
+ Summary,
+ Title,
+ Url,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum RadrootsTagValueType {
+ AddressableCoordinate,
+ DTag,
+ EventId,
+ Kind,
+ PublicKey,
+ RelayUrl,
+ Text,
+ UnixTimestamp,
+ Url,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -83,10 +141,46 @@ pub struct RadrootsTagContract {
pub name: &'static str,
pub cardinality: RadrootsTagCardinality,
pub semantic: RadrootsTagSemantic,
+ pub value_type: RadrootsTagValueType,
pub relay_indexed: bool,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum RadrootsEventDiscriminator {
+ KindOnly,
+ DTagExact(&'static str),
+ DTagPrefix(&'static str),
+ DTagSuffix(&'static str),
+ TagEquals {
+ name: &'static str,
+ value: &'static str,
+ },
+ ContentJsonFieldEquals {
+ field: &'static str,
+ value: &'static str,
+ },
+ EnvelopeType(&'static str),
+ Composite(&'static [RadrootsEventDiscriminator]),
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum RadrootsContractMatchError {
+ UnsupportedKind(u32),
+ UnsupportedShape(u32),
+ AmbiguousShape(u32),
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct RadrootsKindContract {
+ pub kind: u32,
+ pub canonical_constant: &'static str,
+ pub name: &'static str,
+ pub class: RadrootsEventClass,
+ pub standard: RadrootsNostrStandard,
+ pub accepted_event_contracts: &'static [&'static str],
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RadrootsEventContract {
pub id: &'static str,
pub kind: u32,
@@ -96,525 +190,2605 @@ pub struct RadrootsEventContract {
pub stability: RadrootsEventStability,
pub privacy: RadrootsEventPrivacy,
pub author_role: RadrootsActorRole,
+ pub content_schema: RadrootsContentSchema,
+ pub discriminator: RadrootsEventDiscriminator,
pub tags: &'static [RadrootsTagContract],
pub reducers: &'static [RadrootsReducer],
}
-const LISTING_REDUCERS: &[RadrootsReducer] = &[
- RadrootsReducer::ListingProjection,
- RadrootsReducer::MarketProjection,
- RadrootsReducer::ListingInventoryAccounting,
-];
-const ORDER_REDUCERS: &[RadrootsReducer] = &[
- RadrootsReducer::OrderProjection,
- RadrootsReducer::ListingInventoryAccounting,
-];
-const TRADE_VALIDATION_REDUCERS: &[RadrootsReducer] = &[RadrootsReducer::TradeValidation];
-
-const LISTING_TAGS: &[RadrootsTagContract] = &[
- RadrootsTagContract {
- name: "d",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::Identifier,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "title",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::Title,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "summary",
- cardinality: RadrootsTagCardinality::OptionalOne,
- semantic: RadrootsTagSemantic::Summary,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "published_at",
- cardinality: RadrootsTagCardinality::OptionalOne,
- semantic: RadrootsTagSemantic::PublishedAt,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "location",
- cardinality: RadrootsTagCardinality::OptionalMany,
- semantic: RadrootsTagSemantic::Location,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "price",
- cardinality: RadrootsTagCardinality::OptionalMany,
- semantic: RadrootsTagSemantic::Price,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "status",
- cardinality: RadrootsTagCardinality::OptionalOne,
- semantic: RadrootsTagSemantic::Status,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "category",
- cardinality: RadrootsTagCardinality::OptionalMany,
- semantic: RadrootsTagSemantic::Category,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "image",
- cardinality: RadrootsTagCardinality::OptionalMany,
- semantic: RadrootsTagSemantic::Image,
- relay_indexed: true,
- },
-];
-
-const ORDER_REQUEST_TAGS: &[RadrootsTagContract] = &[
- RadrootsTagContract {
- name: "d",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::Identifier,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "p",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::Counterparty,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "a",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::ListingAddress,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "listing_event",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::ListingSnapshot,
- relay_indexed: false,
- },
-];
-
-const CHAINED_ORDER_TAGS: &[RadrootsTagContract] = &[
- RadrootsTagContract {
- name: "d",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::Identifier,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "p",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::Counterparty,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "a",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::ListingAddress,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "e",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::RootEvent,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "e",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::PreviousEvent,
- relay_indexed: true,
- },
-];
-
-const TRADE_VALIDATION_REQUEST_TAGS: &[RadrootsTagContract] = &[
- RadrootsTagContract {
- name: "i",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::ServiceInput,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "a",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::ListingAddress,
- relay_indexed: true,
- },
-];
-
-const TRADE_VALIDATION_RESULT_TAGS: &[RadrootsTagContract] = &[
- RadrootsTagContract {
- name: "request",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::ServiceInput,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "output",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::ServiceOutput,
- relay_indexed: false,
- },
-];
-
-const TRADE_VALIDATION_RECEIPT_TAGS: &[RadrootsTagContract] = &[
- RadrootsTagContract {
- name: "e",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::RootEvent,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "a",
- cardinality: RadrootsTagCardinality::OptionalOne,
- semantic: RadrootsTagSemantic::ListingAddress,
- relay_indexed: true,
- },
- RadrootsTagContract {
- name: "output",
- cardinality: RadrootsTagCardinality::RequiredOne,
- semantic: RadrootsTagSemantic::ServiceOutput,
- relay_indexed: false,
- },
-];
-
-const fn contract(
- id: &'static str,
- kind: u32,
+const fn tag(
name: &'static str,
- payload_type: &'static str,
- class: RadrootsEventClass,
- author_role: RadrootsActorRole,
- tags: &'static [RadrootsTagContract],
- reducers: &'static [RadrootsReducer],
-) -> RadrootsEventContract {
- RadrootsEventContract {
- id,
- kind,
+ cardinality: RadrootsTagCardinality,
+ semantic: RadrootsTagSemantic,
+ value_type: RadrootsTagValueType,
+ relay_indexed: bool,
+) -> RadrootsTagContract {
+ RadrootsTagContract {
name,
- payload_type,
- class,
- stability: RadrootsEventStability::Stable,
- privacy: RadrootsEventPrivacy::Public,
- author_role,
- tags,
- reducers,
+ cardinality,
+ semantic,
+ value_type,
+ relay_indexed,
}
}
-const LISTING_CONTRACT: RadrootsEventContract = contract(
- "listing",
- KIND_LISTING,
- "Listing",
- "RadrootsListing",
- RadrootsEventClass::Addressable,
- RadrootsActorRole::Seller,
- LISTING_TAGS,
- LISTING_REDUCERS,
+const TAG_D: RadrootsTagContract = tag(
+ "d",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::Identifier,
+ RadrootsTagValueType::DTag,
+ true,
+);
+const TAG_P_REQUIRED: RadrootsTagContract = tag(
+ "p",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::Counterparty,
+ RadrootsTagValueType::PublicKey,
+ true,
+);
+const TAG_P_MANY: RadrootsTagContract = tag(
+ "p",
+ RadrootsTagCardinality::OptionalMany,
+ RadrootsTagSemantic::Counterparty,
+ RadrootsTagValueType::PublicKey,
+ true,
+);
+const TAG_A_REQUIRED: RadrootsTagContract = tag(
+ "a",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::ListingAddress,
+ RadrootsTagValueType::AddressableCoordinate,
+ true,
);
-const LISTING_DRAFT_CONTRACT: RadrootsEventContract = contract(
- "listing_draft",
- KIND_LISTING_DRAFT,
- "Listing Draft",
- "RadrootsListing",
- RadrootsEventClass::Addressable,
- RadrootsActorRole::Seller,
- LISTING_TAGS,
- LISTING_REDUCERS,
+const TAG_A_OPTIONAL: RadrootsTagContract = tag(
+ "a",
+ RadrootsTagCardinality::OptionalOne,
+ RadrootsTagSemantic::AddressableCoordinate,
+ RadrootsTagValueType::AddressableCoordinate,
+ true,
);
-const ORDER_REQUEST_CONTRACT: RadrootsEventContract = contract(
- "order_request",
- KIND_ORDER_REQUEST,
- "Order Request",
- "RadrootsOrderRequest",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Buyer,
- ORDER_REQUEST_TAGS,
- ORDER_REDUCERS,
+const TAG_E_ROOT: RadrootsTagContract = tag(
+ "e",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::RootEvent,
+ RadrootsTagValueType::EventId,
+ true,
);
-const ORDER_DECISION_CONTRACT: RadrootsEventContract = contract(
- "order_decision",
- KIND_ORDER_DECISION,
- "Order Decision",
- "RadrootsOrderDecision",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Seller,
- CHAINED_ORDER_TAGS,
- ORDER_REDUCERS,
+const TAG_E_PREVIOUS: RadrootsTagContract = tag(
+ "e",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::PreviousEvent,
+ RadrootsTagValueType::EventId,
+ true,
);
-const ORDER_REVISION_PROPOSAL_CONTRACT: RadrootsEventContract = contract(
- "order_revision_proposal",
- KIND_ORDER_REVISION_PROPOSAL,
- "Order Revision Proposal",
- "RadrootsOrderRevisionProposal",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Buyer,
- CHAINED_ORDER_TAGS,
- ORDER_REDUCERS,
+const TAG_E_MANY: RadrootsTagContract = tag(
+ "e",
+ RadrootsTagCardinality::OptionalMany,
+ RadrootsTagSemantic::EventPointer,
+ RadrootsTagValueType::EventId,
+ true,
);
-const ORDER_REVISION_DECISION_CONTRACT: RadrootsEventContract = contract(
- "order_revision_decision",
- KIND_ORDER_REVISION_DECISION,
- "Order Revision Decision",
- "RadrootsOrderRevisionDecision",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Seller,
- CHAINED_ORDER_TAGS,
- ORDER_REDUCERS,
+const TAG_KIND: RadrootsTagContract = tag(
+ "k",
+ RadrootsTagCardinality::OptionalOne,
+ RadrootsTagSemantic::Kind,
+ RadrootsTagValueType::Kind,
+ true,
);
-const ORDER_CANCELLATION_CONTRACT: RadrootsEventContract = contract(
- "order_cancellation",
- KIND_ORDER_CANCELLATION,
- "Order Cancellation",
- "RadrootsOrderCancellation",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Buyer,
- CHAINED_ORDER_TAGS,
- ORDER_REDUCERS,
+const TAG_RELAY: RadrootsTagContract = tag(
+ "relay",
+ RadrootsTagCardinality::OptionalMany,
+ RadrootsTagSemantic::Relay,
+ RadrootsTagValueType::RelayUrl,
+ false,
);
-const ORDER_FULFILLMENT_UPDATE_CONTRACT: RadrootsEventContract = contract(
- "order_fulfillment_update",
- KIND_ORDER_FULFILLMENT_UPDATE,
- "Order Fulfillment Update",
- "RadrootsOrderFulfillmentUpdate",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Seller,
- CHAINED_ORDER_TAGS,
- ORDER_REDUCERS,
+const TAG_GROUP: RadrootsTagContract = tag(
+ "h",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::GroupId,
+ RadrootsTagValueType::DTag,
+ true,
);
-const ORDER_RECEIPT_CONTRACT: RadrootsEventContract = contract(
- "order_receipt",
- KIND_ORDER_RECEIPT,
- "Order Receipt",
- "RadrootsOrderReceipt",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Buyer,
- CHAINED_ORDER_TAGS,
- ORDER_REDUCERS,
+const TAG_TITLE: RadrootsTagContract = tag(
+ "title",
+ RadrootsTagCardinality::OptionalOne,
+ RadrootsTagSemantic::Title,
+ RadrootsTagValueType::Text,
+ false,
);
-const ORDER_PAYMENT_RECORD_CONTRACT: RadrootsEventContract = contract(
- "order_payment_record",
- KIND_ORDER_PAYMENT_RECORD,
- "Order Payment Record",
- "RadrootsOrderPaymentRecord",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Buyer,
- CHAINED_ORDER_TAGS,
- ORDER_REDUCERS,
+const TAG_SUMMARY: RadrootsTagContract = tag(
+ "summary",
+ RadrootsTagCardinality::OptionalOne,
+ RadrootsTagSemantic::Summary,
+ RadrootsTagValueType::Text,
+ false,
);
-const ORDER_SETTLEMENT_DECISION_CONTRACT: RadrootsEventContract = contract(
- "order_settlement_decision",
- KIND_ORDER_SETTLEMENT_DECISION,
- "Order Settlement Decision",
- "RadrootsOrderSettlementDecision",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Seller,
- CHAINED_ORDER_TAGS,
- ORDER_REDUCERS,
+const TAG_PUBLISHED_AT: RadrootsTagContract = tag(
+ "published_at",
+ RadrootsTagCardinality::OptionalOne,
+ RadrootsTagSemantic::PublishedAt,
+ RadrootsTagValueType::UnixTimestamp,
+ false,
);
-const TRADE_LISTING_VALIDATION_REQUEST_CONTRACT: RadrootsEventContract = contract(
- "trade_listing_validation_request",
- KIND_TRADE_LISTING_VALIDATION_REQUEST,
- "Trade Listing Validation Request",
- "RadrootsTradeValidationListingRequest",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Service,
- TRADE_VALIDATION_REQUEST_TAGS,
- TRADE_VALIDATION_REDUCERS,
+const TAG_LOCATION: RadrootsTagContract = tag(
+ "location",
+ RadrootsTagCardinality::OptionalMany,
+ RadrootsTagSemantic::Location,
+ RadrootsTagValueType::Text,
+ false,
);
-const TRADE_LISTING_VALIDATION_RESULT_CONTRACT: RadrootsEventContract = contract(
- "trade_listing_validation_result",
- KIND_TRADE_LISTING_VALIDATION_RESULT,
- "Trade Listing Validation Result",
- "RadrootsTradeValidationListingResult",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Service,
- TRADE_VALIDATION_RESULT_TAGS,
- TRADE_VALIDATION_REDUCERS,
+const TAG_PRICE: RadrootsTagContract = tag(
+ "price",
+ RadrootsTagCardinality::OptionalMany,
+ RadrootsTagSemantic::Price,
+ RadrootsTagValueType::Text,
+ false,
);
-const TRADE_TRANSITION_PROOF_REQUEST_CONTRACT: RadrootsEventContract = contract(
- "trade_transition_proof_request",
- KIND_TRADE_TRANSITION_PROOF_REQUEST,
- "Trade Transition Proof Request",
- "RadrootsTradeTransitionProofRequest",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Service,
- TRADE_VALIDATION_REQUEST_TAGS,
- TRADE_VALIDATION_REDUCERS,
+const TAG_STATUS: RadrootsTagContract = tag(
+ "status",
+ RadrootsTagCardinality::OptionalOne,
+ RadrootsTagSemantic::Status,
+ RadrootsTagValueType::Text,
+ false,
);
-const TRADE_TRANSITION_PROOF_RESULT_CONTRACT: RadrootsEventContract = contract(
- "trade_transition_proof_result",
- KIND_TRADE_TRANSITION_PROOF_RESULT,
- "Trade Transition Proof Result",
- "RadrootsTradeTransitionProofResult",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Service,
- TRADE_VALIDATION_RESULT_TAGS,
- TRADE_VALIDATION_REDUCERS,
+const TAG_CATEGORY: RadrootsTagContract = tag(
+ "category",
+ RadrootsTagCardinality::OptionalMany,
+ RadrootsTagSemantic::Category,
+ RadrootsTagValueType::Text,
+ false,
);
-const TRADE_VALIDATION_RECEIPT_CONTRACT: RadrootsEventContract = contract(
- "trade_validation_receipt",
- KIND_TRADE_VALIDATION_RECEIPT,
- "Trade Validation Receipt",
- "RadrootsTradeValidationReceipt",
- RadrootsEventClass::Regular,
- RadrootsActorRole::Service,
- TRADE_VALIDATION_RECEIPT_TAGS,
- TRADE_VALIDATION_REDUCERS,
+const TAG_IMAGE: RadrootsTagContract = tag(
+ "image",
+ RadrootsTagCardinality::OptionalMany,
+ RadrootsTagSemantic::Image,
+ RadrootsTagValueType::Url,
+ false,
);
+const TAG_LISTING_EVENT: RadrootsTagContract = tag(
+ "listing_event",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::ListingSnapshot,
+ RadrootsTagValueType::EventId,
+ false,
+);
+const TAG_SERVICE_INPUT: RadrootsTagContract = tag(
+ "i",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::ServiceInput,
+ RadrootsTagValueType::Text,
+ true,
+);
+const TAG_SERVICE_REQUEST: RadrootsTagContract = tag(
+ "request",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::ServiceInput,
+ RadrootsTagValueType::EventId,
+ false,
+);
+const TAG_SERVICE_OUTPUT: RadrootsTagContract = tag(
+ "output",
+ RadrootsTagCardinality::RequiredOne,
+ RadrootsTagSemantic::ServiceOutput,
+ RadrootsTagValueType::Text,
+ false,
+);
+const TAG_URL: RadrootsTagContract = tag(
+ "url",
+ RadrootsTagCardinality::OptionalOne,
+ RadrootsTagSemantic::Url,
+ RadrootsTagValueType::Url,
+ false,
+);
+
+const NO_TAGS: &[RadrootsTagContract] = &[];
+const D_TAGS: &[RadrootsTagContract] = &[TAG_D];
+const P_TAGS: &[RadrootsTagContract] = &[TAG_P_MANY];
+const EVENT_POINTER_TAGS: &[RadrootsTagContract] = &[TAG_E_MANY, TAG_P_MANY, TAG_KIND];
+const LIST_TAGS: &[RadrootsTagContract] = &[TAG_E_MANY, TAG_A_OPTIONAL, TAG_P_MANY, TAG_RELAY];
+const LIST_SET_TAGS: &[RadrootsTagContract] = &[TAG_D, TAG_E_MANY, TAG_A_OPTIONAL, TAG_P_MANY];
+const PROFILE_TAGS: &[RadrootsTagContract] = &[TAG_P_MANY];
+const GROUP_ACTION_TAGS: &[RadrootsTagContract] = &[TAG_GROUP, TAG_P_MANY, TAG_E_MANY];
+const GROUP_STATE_TAGS: &[RadrootsTagContract] = &[TAG_D, TAG_P_MANY, TAG_E_MANY];
+const FILE_METADATA_TAGS: &[RadrootsTagContract] = &[TAG_URL, TAG_IMAGE];
+const ARTICLE_TAGS: &[RadrootsTagContract] = &[TAG_D, TAG_TITLE, TAG_SUMMARY, TAG_PUBLISHED_AT];
+const CALENDAR_EVENT_TAGS: &[RadrootsTagContract] =
+ &[TAG_D, TAG_TITLE, TAG_LOCATION, TAG_PUBLISHED_AT];
+const FARM_TAGS: &[RadrootsTagContract] = &[TAG_D, TAG_TITLE, TAG_LOCATION, TAG_IMAGE];
+const LISTING_TAGS: &[RadrootsTagContract] = &[
+ TAG_D,
+ TAG_TITLE,
+ TAG_SUMMARY,
+ TAG_PUBLISHED_AT,
+ TAG_LOCATION,
+ TAG_PRICE,
+ TAG_STATUS,
+ TAG_CATEGORY,
+ TAG_IMAGE,
+];
+const ORDER_REQUEST_TAGS: &[RadrootsTagContract] =
+ &[TAG_D, TAG_P_REQUIRED, TAG_A_REQUIRED, TAG_LISTING_EVENT];
+const CHAINED_ORDER_TAGS: &[RadrootsTagContract] = &[
+ TAG_D,
+ TAG_P_REQUIRED,
+ TAG_A_REQUIRED,
+ TAG_E_ROOT,
+ TAG_E_PREVIOUS,
+];
+const TRADE_VALIDATION_REQUEST_TAGS: &[RadrootsTagContract] = &[TAG_SERVICE_INPUT, TAG_A_REQUIRED];
+const TRADE_VALIDATION_RESULT_TAGS: &[RadrootsTagContract] =
+ &[TAG_SERVICE_REQUEST, TAG_SERVICE_OUTPUT];
+const TRADE_VALIDATION_RECEIPT_TAGS: &[RadrootsTagContract] =
+ &[TAG_E_ROOT, TAG_A_OPTIONAL, TAG_SERVICE_OUTPUT];
+
+const SOCIAL_REDUCERS: &[RadrootsReducer] = &[RadrootsReducer::SocialProjection];
+const PROFILE_REDUCERS: &[RadrootsReducer] = &[RadrootsReducer::ProfileProjection];
+const FARM_OPS_REDUCERS: &[RadrootsReducer] = &[RadrootsReducer::FarmOpsProjection];
+const GROUP_REDUCERS: &[RadrootsReducer] = &[RadrootsReducer::GroupProjection];
+const CALENDAR_REDUCERS: &[RadrootsReducer] = &[RadrootsReducer::CalendarProjection];
+const LISTING_REDUCERS: &[RadrootsReducer] = &[
+ RadrootsReducer::ListingProjection,
+ RadrootsReducer::MarketProjection,
+ RadrootsReducer::ListingInventoryAccounting,
+];
+const ORDER_REDUCERS: &[RadrootsReducer] = &[
+ RadrootsReducer::OrderProjection,
+ RadrootsReducer::ListingInventoryAccounting,
+];
+const TRADE_VALIDATION_REDUCERS: &[RadrootsReducer] = &[RadrootsReducer::TradeValidation];
+const RELAY_REDUCERS: &[RadrootsReducer] = &[RadrootsReducer::RelayPolicyProjection];
+
+const FARM_MEMBERS_LIST_DISCRIMINATOR: &[RadrootsEventDiscriminator] = &[
+ RadrootsEventDiscriminator::DTagPrefix("farm:"),
+ RadrootsEventDiscriminator::DTagSuffix(":members"),
+];
+const FARM_OWNERS_LIST_DISCRIMINATOR: &[RadrootsEventDiscriminator] = &[
+ RadrootsEventDiscriminator::DTagPrefix("farm:"),
+ RadrootsEventDiscriminator::DTagSuffix(":members.owners"),
+];
+const FARM_WORKERS_LIST_DISCRIMINATOR: &[RadrootsEventDiscriminator] = &[
+ RadrootsEventDiscriminator::DTagPrefix("farm:"),
+ RadrootsEventDiscriminator::DTagSuffix(":members.workers"),
+];
+const FARM_PLOTS_LIST_DISCRIMINATOR: &[RadrootsEventDiscriminator] = &[
+ RadrootsEventDiscriminator::DTagPrefix("farm:"),
+ RadrootsEventDiscriminator::DTagSuffix(":plots"),
+];
+const FARM_LISTINGS_LIST_DISCRIMINATOR: &[RadrootsEventDiscriminator] = &[
+ RadrootsEventDiscriminator::DTagPrefix("farm:"),
+ RadrootsEventDiscriminator::DTagSuffix(":listings"),
+];
+
+macro_rules! kind_contract {
+ ($kind:expr, $constant:literal, $name:literal, $class:expr, $standard:expr, [$($contract:literal),+ $(,)?]) => {
+ RadrootsKindContract {
+ kind: $kind,
+ canonical_constant: $constant,
+ name: $name,
+ class: $class,
+ standard: $standard,
+ accepted_event_contracts: &[$($contract),+],
+ }
+ };
+}
-static LISTING_EVENT_CONTRACTS: [RadrootsEventContract; 2] =
- [LISTING_CONTRACT, LISTING_DRAFT_CONTRACT];
-static ORDER_EVENT_CONTRACTS: [RadrootsEventContract; 9] = [
- ORDER_REQUEST_CONTRACT,
- ORDER_DECISION_CONTRACT,
- ORDER_REVISION_PROPOSAL_CONTRACT,
- ORDER_REVISION_DECISION_CONTRACT,
- ORDER_CANCELLATION_CONTRACT,
- ORDER_FULFILLMENT_UPDATE_CONTRACT,
- ORDER_RECEIPT_CONTRACT,
- ORDER_PAYMENT_RECORD_CONTRACT,
- ORDER_SETTLEMENT_DECISION_CONTRACT,
+macro_rules! event_contract {
+ (
+ $id:literal,
+ $kind:expr,
+ $name:literal,
+ $payload_type:literal,
+ $class:expr,
+ $standard_privacy:expr,
+ $author_role:expr,
+ $content_schema:expr,
+ $discriminator:expr,
+ $tags:expr,
+ $reducers:expr $(,)?
+ ) => {
+ RadrootsEventContract {
+ id: $id,
+ kind: $kind,
+ name: $name,
+ payload_type: $payload_type,
+ class: $class,
+ stability: RadrootsEventStability::Stable,
+ privacy: $standard_privacy,
+ author_role: $author_role,
+ content_schema: $content_schema,
+ discriminator: $discriminator,
+ tags: $tags,
+ reducers: $reducers,
+ }
+ };
+}
+
+static LIST_SET_GENERIC_EVENT_CONTRACTS: &[RadrootsEventContract] = &[
+ event_contract!(
+ "radroots.list_set.farm.members.v1",
+ KIND_LIST_SET_GENERIC,
+ "Farm Members List Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::Composite(FARM_MEMBERS_LIST_DISCRIMINATOR),
+ LIST_SET_TAGS,
+ FARM_OPS_REDUCERS,
+ ),
+ event_contract!(
+ "radroots.list_set.farm.members.owners.v1",
+ KIND_LIST_SET_GENERIC,
+ "Farm Owners List Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::Composite(FARM_OWNERS_LIST_DISCRIMINATOR),
+ LIST_SET_TAGS,
+ FARM_OPS_REDUCERS,
+ ),
+ event_contract!(
+ "radroots.list_set.farm.members.workers.v1",
+ KIND_LIST_SET_GENERIC,
+ "Farm Workers List Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::Composite(FARM_WORKERS_LIST_DISCRIMINATOR),
+ LIST_SET_TAGS,
+ FARM_OPS_REDUCERS,
+ ),
+ event_contract!(
+ "radroots.list_set.farm.plots.v1",
+ KIND_LIST_SET_GENERIC,
+ "Farm Plots List Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::Composite(FARM_PLOTS_LIST_DISCRIMINATOR),
+ LIST_SET_TAGS,
+ FARM_OPS_REDUCERS,
+ ),
+ event_contract!(
+ "radroots.list_set.farm.listings.v1",
+ KIND_LIST_SET_GENERIC,
+ "Farm Listings List Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::Composite(FARM_LISTINGS_LIST_DISCRIMINATOR),
+ LIST_SET_TAGS,
+ FARM_OPS_REDUCERS,
+ ),
+ event_contract!(
+ "radroots.list_set.member_of.farms.v1",
+ KIND_LIST_SET_GENERIC,
+ "Member Of Farms List Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Member,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::DTagExact("member_of.farms"),
+ LIST_SET_TAGS,
+ FARM_OPS_REDUCERS,
+ ),
];
-static TRADE_VALIDATION_CONTRACTS: [RadrootsEventContract; 5] = [
- TRADE_LISTING_VALIDATION_REQUEST_CONTRACT,
- TRADE_LISTING_VALIDATION_RESULT_CONTRACT,
- TRADE_TRANSITION_PROOF_REQUEST_CONTRACT,
- TRADE_TRANSITION_PROOF_RESULT_CONTRACT,
- TRADE_VALIDATION_RECEIPT_CONTRACT,
+
+static ALL_KIND_CONTRACTS: &[RadrootsKindContract] = &[
+ kind_contract!(
+ KIND_PROFILE,
+ "KIND_PROFILE",
+ "Profile Metadata",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip01,
+ ["radroots.profile.metadata.v1"]
+ ),
+ kind_contract!(
+ KIND_POST,
+ "KIND_POST",
+ "Short Text Note",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip01,
+ ["radroots.social.post.v1"]
+ ),
+ kind_contract!(
+ KIND_FOLLOW,
+ "KIND_FOLLOW",
+ "Contact List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip01,
+ ["radroots.social.follow_list.v1"]
+ ),
+ kind_contract!(
+ KIND_REPOST,
+ "KIND_REPOST",
+ "Repost",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip18,
+ ["radroots.social.repost.v1"]
+ ),
+ kind_contract!(
+ KIND_REACTION,
+ "KIND_REACTION",
+ "Reaction",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip25,
+ ["radroots.social.reaction.v1"]
+ ),
+ kind_contract!(
+ KIND_SEAL,
+ "KIND_SEAL",
+ "Seal",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip17,
+ ["radroots.message.seal.v1"]
+ ),
+ kind_contract!(
+ KIND_MESSAGE,
+ "KIND_MESSAGE",
+ "Direct Message",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip17,
+ ["radroots.message.private.v1"]
+ ),
+ kind_contract!(
+ KIND_MESSAGE_FILE,
+ "KIND_MESSAGE_FILE",
+ "Direct Message File",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip17,
+ ["radroots.message.file.v1"]
+ ),
+ kind_contract!(
+ KIND_GENERIC_REPOST,
+ "KIND_GENERIC_REPOST",
+ "Generic Repost",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip18,
+ ["radroots.social.generic_repost.v1"]
+ ),
+ kind_contract!(
+ KIND_FARM_CRDT_CHANGE,
+ "KIND_FARM_CRDT_CHANGE",
+ "Farm CRDT Change",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.farm.crdt_change.v1"]
+ ),
+ kind_contract!(
+ KIND_GIFT_WRAP,
+ "KIND_GIFT_WRAP",
+ "Gift Wrap",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip17,
+ ["radroots.message.gift_wrap.v1"]
+ ),
+ kind_contract!(
+ KIND_FILE_METADATA,
+ "KIND_FILE_METADATA",
+ "File Metadata",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip94,
+ ["radroots.file.metadata.v1"]
+ ),
+ kind_contract!(
+ KIND_COMMENT,
+ "KIND_COMMENT",
+ "Comment",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip22,
+ ["radroots.social.comment.v1"]
+ ),
+ kind_contract!(
+ KIND_REPORT,
+ "KIND_REPORT",
+ "Report",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip56,
+ ["radroots.social.report.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_PUT_USER,
+ "KIND_GROUP_PUT_USER",
+ "Group Put User",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.put_user.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_REMOVE_USER,
+ "KIND_GROUP_REMOVE_USER",
+ "Group Remove User",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.remove_user.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_EDIT_METADATA,
+ "KIND_GROUP_EDIT_METADATA",
+ "Group Edit Metadata",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.edit_metadata.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_DELETE_EVENT,
+ "KIND_GROUP_DELETE_EVENT",
+ "Group Delete Event",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.delete_event.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_CREATE_GROUP,
+ "KIND_GROUP_CREATE_GROUP",
+ "Group Create Group",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.create_group.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_DELETE_GROUP,
+ "KIND_GROUP_DELETE_GROUP",
+ "Group Delete Group",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.delete_group.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_CREATE_INVITE,
+ "KIND_GROUP_CREATE_INVITE",
+ "Group Create Invite",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.create_invite.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_JOIN_REQUEST,
+ "KIND_GROUP_JOIN_REQUEST",
+ "Group Join Request",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.join_request.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_LEAVE_REQUEST,
+ "KIND_GROUP_LEAVE_REQUEST",
+ "Group Leave Request",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.leave_request.v1"]
+ ),
+ kind_contract!(
+ KIND_GEOCHAT,
+ "KIND_GEOCHAT",
+ "Geochat",
+ RadrootsEventClass::Ephemeral,
+ RadrootsNostrStandard::Nip28,
+ ["radroots.social.geochat.v1"]
+ ),
+ kind_contract!(
+ KIND_RELAY_AUTH,
+ "KIND_RELAY_AUTH",
+ "Relay Auth",
+ RadrootsEventClass::Ephemeral,
+ RadrootsNostrStandard::Nip42,
+ ["radroots.relay.auth.v1"]
+ ),
+ kind_contract!(
+ KIND_HTTP_AUTH,
+ "KIND_HTTP_AUTH",
+ "HTTP Auth",
+ RadrootsEventClass::Ephemeral,
+ RadrootsNostrStandard::Nip98,
+ ["radroots.http.auth.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_MUTE,
+ "KIND_LIST_MUTE",
+ "Mute List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.mute.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_PINNED_NOTES,
+ "KIND_LIST_PINNED_NOTES",
+ "Pinned Notes List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.pinned_notes.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_READ_WRITE_RELAYS,
+ "KIND_LIST_READ_WRITE_RELAYS",
+ "Read Write Relays List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.read_write_relays.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_BOOKMARKS,
+ "KIND_LIST_BOOKMARKS",
+ "Bookmarks List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.bookmarks.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_COMMUNITIES,
+ "KIND_LIST_COMMUNITIES",
+ "Communities List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.communities.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_PUBLIC_CHATS,
+ "KIND_LIST_PUBLIC_CHATS",
+ "Public Chats List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.public_chats.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_BLOCKED_RELAYS,
+ "KIND_LIST_BLOCKED_RELAYS",
+ "Blocked Relays List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.blocked_relays.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SEARCH_RELAYS,
+ "KIND_LIST_SEARCH_RELAYS",
+ "Search Relays List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.search_relays.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SIMPLE_GROUPS,
+ "KIND_LIST_SIMPLE_GROUPS",
+ "Simple Groups List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.simple_groups.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_RELAY_FEEDS,
+ "KIND_LIST_RELAY_FEEDS",
+ "Relay Feeds List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.relay_feeds.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_INTERESTS,
+ "KIND_LIST_INTERESTS",
+ "Interests List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.interests.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_MEDIA_FOLLOWS,
+ "KIND_LIST_MEDIA_FOLLOWS",
+ "Media Follows List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.media_follows.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_EMOJIS,
+ "KIND_LIST_EMOJIS",
+ "Emojis List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.emojis.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_DM_RELAYS,
+ "KIND_LIST_DM_RELAYS",
+ "DM Relays List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.dm_relays.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_GOOD_WIKI_AUTHORS,
+ "KIND_LIST_GOOD_WIKI_AUTHORS",
+ "Good Wiki Authors List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.good_wiki_authors.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_GOOD_WIKI_RELAYS,
+ "KIND_LIST_GOOD_WIKI_RELAYS",
+ "Good Wiki Relays List",
+ RadrootsEventClass::Replaceable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list.good_wiki_relays.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_FOLLOW,
+ "KIND_LIST_SET_FOLLOW",
+ "Follow Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.follow.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_GENERIC,
+ "KIND_LIST_SET_GENERIC",
+ "Generic List Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ [
+ "radroots.list_set.farm.members.v1",
+ "radroots.list_set.farm.members.owners.v1",
+ "radroots.list_set.farm.members.workers.v1",
+ "radroots.list_set.farm.plots.v1",
+ "radroots.list_set.farm.listings.v1",
+ "radroots.list_set.member_of.farms.v1"
+ ]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_RELAY,
+ "KIND_LIST_SET_RELAY",
+ "Relay Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.relay.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_BOOKMARK,
+ "KIND_LIST_SET_BOOKMARK",
+ "Bookmark Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.bookmark.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_CURATION,
+ "KIND_LIST_SET_CURATION",
+ "Curation Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.curation.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_VIDEO,
+ "KIND_LIST_SET_VIDEO",
+ "Video Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.video.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_PICTURE,
+ "KIND_LIST_SET_PICTURE",
+ "Picture Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.picture.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_KIND_MUTE,
+ "KIND_LIST_SET_KIND_MUTE",
+ "Kind Mute Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.kind_mute.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_INTEREST,
+ "KIND_LIST_SET_INTEREST",
+ "Interest Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.interest.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_EMOJI,
+ "KIND_LIST_SET_EMOJI",
+ "Emoji Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.emoji.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_RELEASE_ARTIFACT,
+ "KIND_LIST_SET_RELEASE_ARTIFACT",
+ "Release Artifact Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.release_artifact.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_APP_CURATION,
+ "KIND_LIST_SET_APP_CURATION",
+ "App Curation Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.app_curation.v1"]
+ ),
+ kind_contract!(
+ KIND_ARTICLE,
+ "KIND_ARTICLE",
+ "Long Form Article",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip23,
+ ["radroots.social.article.v1"]
+ ),
+ kind_contract!(
+ KIND_CALENDAR_DATE_EVENT,
+ "KIND_CALENDAR_DATE_EVENT",
+ "Calendar Date Event",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip52,
+ ["radroots.calendar.date_event.v1"]
+ ),
+ kind_contract!(
+ KIND_CALENDAR_TIME_EVENT,
+ "KIND_CALENDAR_TIME_EVENT",
+ "Calendar Time Event",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip52,
+ ["radroots.calendar.time_event.v1"]
+ ),
+ kind_contract!(
+ KIND_CALENDAR,
+ "KIND_CALENDAR",
+ "Calendar Collection",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip52,
+ ["radroots.calendar.collection.v1"]
+ ),
+ kind_contract!(
+ KIND_CALENDAR_EVENT_RSVP,
+ "KIND_CALENDAR_EVENT_RSVP",
+ "Calendar RSVP",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip52,
+ ["radroots.calendar.rsvp.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_STARTER_PACK,
+ "KIND_LIST_SET_STARTER_PACK",
+ "Starter Pack Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.starter_pack.v1"]
+ ),
+ kind_contract!(
+ KIND_LIST_SET_MEDIA_STARTER_PACK,
+ "KIND_LIST_SET_MEDIA_STARTER_PACK",
+ "Media Starter Pack Set",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip51,
+ ["radroots.list_set.media_starter_pack.v1"]
+ ),
+ kind_contract!(
+ KIND_FARM,
+ "KIND_FARM",
+ "Farm",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.farm.profile.v1"]
+ ),
+ kind_contract!(
+ KIND_PLOT,
+ "KIND_PLOT",
+ "Plot",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.farm.plot.v1"]
+ ),
+ kind_contract!(
+ KIND_COOP,
+ "KIND_COOP",
+ "Coop",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.farm.coop.v1"]
+ ),
+ kind_contract!(
+ KIND_DOCUMENT,
+ "KIND_DOCUMENT",
+ "Document",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.farm.document.v1"]
+ ),
+ kind_contract!(
+ KIND_RESOURCE_AREA,
+ "KIND_RESOURCE_AREA",
+ "Resource Area",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.farm.resource_area.v1"]
+ ),
+ kind_contract!(
+ KIND_RESOURCE_HARVEST_CAP,
+ "KIND_RESOURCE_HARVEST_CAP",
+ "Resource Harvest Capacity",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.farm.resource_harvest_cap.v1"]
+ ),
+ kind_contract!(
+ KIND_ACCOUNT_CLAIM,
+ "KIND_ACCOUNT_CLAIM",
+ "Account Claim",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.account.claim.v1"]
+ ),
+ kind_contract!(
+ KIND_FARM_WORKSPACE_MANIFEST,
+ "KIND_FARM_WORKSPACE_MANIFEST",
+ "Farm Workspace Manifest",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip78,
+ ["radroots.farm.workspace_manifest.v1"]
+ ),
+ kind_contract!(
+ KIND_LISTING,
+ "KIND_LISTING",
+ "Listing",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.listing.published.v1"]
+ ),
+ kind_contract!(
+ KIND_LISTING_DRAFT,
+ "KIND_LISTING_DRAFT",
+ "Listing Draft",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.listing.draft.v1"]
+ ),
+ kind_contract!(
+ KIND_APPLICATION_HANDLER,
+ "KIND_APPLICATION_HANDLER",
+ "Application Handler",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.application.handler.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_METADATA,
+ "KIND_GROUP_METADATA",
+ "Group Metadata",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.metadata.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_ADMINS,
+ "KIND_GROUP_ADMINS",
+ "Group Admins",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.admins.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_MEMBERS,
+ "KIND_GROUP_MEMBERS",
+ "Group Members",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.members.v1"]
+ ),
+ kind_contract!(
+ KIND_GROUP_ROLES,
+ "KIND_GROUP_ROLES",
+ "Group Roles",
+ RadrootsEventClass::Addressable,
+ RadrootsNostrStandard::Nip29,
+ ["radroots.group.roles.v1"]
+ ),
+ kind_contract!(
+ KIND_TRADE_LISTING_VALIDATION_REQUEST,
+ "KIND_TRADE_LISTING_VALIDATION_REQUEST",
+ "Trade Listing Validation Request",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip90,
+ ["radroots.trade.listing_validation.request.v1"]
+ ),
+ kind_contract!(
+ KIND_TRADE_LISTING_VALIDATION_RESULT,
+ "KIND_TRADE_LISTING_VALIDATION_RESULT",
+ "Trade Listing Validation Result",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip90,
+ ["radroots.trade.listing_validation.result.v1"]
+ ),
+ kind_contract!(
+ KIND_TRADE_TRANSITION_PROOF_REQUEST,
+ "KIND_TRADE_TRANSITION_PROOF_REQUEST",
+ "Trade Transition Proof Request",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip90,
+ ["radroots.trade.transition_proof.request.v1"]
+ ),
+ kind_contract!(
+ KIND_TRADE_TRANSITION_PROOF_RESULT,
+ "KIND_TRADE_TRANSITION_PROOF_RESULT",
+ "Trade Transition Proof Result",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Nip90,
+ ["radroots.trade.transition_proof.result.v1"]
+ ),
+ kind_contract!(
+ KIND_ORDER_REQUEST,
+ "KIND_ORDER_REQUEST",
+ "Order Request",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.order.request.v1"]
+ ),
+ kind_contract!(
+ KIND_ORDER_DECISION,
+ "KIND_ORDER_DECISION",
+ "Order Decision",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.order.decision.v1"]
+ ),
+ kind_contract!(
+ KIND_ORDER_REVISION_PROPOSAL,
+ "KIND_ORDER_REVISION_PROPOSAL",
+ "Order Revision Proposal",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.order.revision_proposal.v1"]
+ ),
+ kind_contract!(
+ KIND_ORDER_REVISION_DECISION,
+ "KIND_ORDER_REVISION_DECISION",
+ "Order Revision Decision",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.order.revision_decision.v1"]
+ ),
+ kind_contract!(
+ KIND_ORDER_CANCELLATION,
+ "KIND_ORDER_CANCELLATION",
+ "Order Cancellation",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.order.cancellation.v1"]
+ ),
+ kind_contract!(
+ KIND_ORDER_FULFILLMENT_UPDATE,
+ "KIND_ORDER_FULFILLMENT_UPDATE",
+ "Order Fulfillment Update",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.order.fulfillment_update.v1"]
+ ),
+ kind_contract!(
+ KIND_ORDER_RECEIPT,
+ "KIND_ORDER_RECEIPT",
+ "Order Receipt",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.order.receipt.v1"]
+ ),
+ kind_contract!(
+ KIND_ORDER_PAYMENT_RECORD,
+ "KIND_ORDER_PAYMENT_RECORD",
+ "Order Payment Record",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.order.payment_record.v1"]
+ ),
+ kind_contract!(
+ KIND_ORDER_SETTLEMENT_DECISION,
+ "KIND_ORDER_SETTLEMENT_DECISION",
+ "Order Settlement Decision",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.order.settlement_decision.v1"]
+ ),
+ kind_contract!(
+ KIND_TRADE_VALIDATION_RECEIPT,
+ "KIND_TRADE_VALIDATION_RECEIPT",
+ "Trade Validation Receipt",
+ RadrootsEventClass::Regular,
+ RadrootsNostrStandard::Radroots,
+ ["radroots.trade.validation_receipt.v1"]
+ ),
];
-static ALL_EVENT_CONTRACTS: [RadrootsEventContract; 16] = [
- LISTING_CONTRACT,
- LISTING_DRAFT_CONTRACT,
- ORDER_REQUEST_CONTRACT,
- ORDER_DECISION_CONTRACT,
- ORDER_REVISION_PROPOSAL_CONTRACT,
- ORDER_REVISION_DECISION_CONTRACT,
- ORDER_CANCELLATION_CONTRACT,
- ORDER_FULFILLMENT_UPDATE_CONTRACT,
- ORDER_RECEIPT_CONTRACT,
- ORDER_PAYMENT_RECORD_CONTRACT,
- ORDER_SETTLEMENT_DECISION_CONTRACT,
- TRADE_LISTING_VALIDATION_REQUEST_CONTRACT,
- TRADE_LISTING_VALIDATION_RESULT_CONTRACT,
- TRADE_TRANSITION_PROOF_REQUEST_CONTRACT,
- TRADE_TRANSITION_PROOF_RESULT_CONTRACT,
- TRADE_VALIDATION_RECEIPT_CONTRACT,
+
+static ALL_EVENT_CONTRACTS: &[RadrootsEventContract] = &[
+ event_contract!(
+ "radroots.profile.metadata.v1",
+ KIND_PROFILE,
+ "Profile Metadata",
+ "RadrootsProfile",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ PROFILE_TAGS,
+ PROFILE_REDUCERS
+ ),
+ event_contract!(
+ "radroots.social.post.v1",
+ KIND_POST,
+ "Short Text Note",
+ "RadrootsPost",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::PlainText,
+ RadrootsEventDiscriminator::KindOnly,
+ NO_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.social.follow_list.v1",
+ KIND_FOLLOW,
+ "Contact List",
+ "RadrootsFollowList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ P_TAGS,
+ PROFILE_REDUCERS
+ ),
+ event_contract!(
+ "radroots.social.repost.v1",
+ KIND_REPOST,
+ "Repost",
+ "RadrootsRepost",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ EVENT_POINTER_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.social.reaction.v1",
+ KIND_REACTION,
+ "Reaction",
+ "RadrootsReaction",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::PlainText,
+ RadrootsEventDiscriminator::KindOnly,
+ EVENT_POINTER_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.message.seal.v1",
+ KIND_SEAL,
+ "Seal",
+ "RadrootsSeal",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Encrypted,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::Encrypted,
+ RadrootsEventDiscriminator::KindOnly,
+ NO_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.message.private.v1",
+ KIND_MESSAGE,
+ "Direct Message",
+ "RadrootsMessage",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Encrypted,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::Encrypted,
+ RadrootsEventDiscriminator::KindOnly,
+ P_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.message.file.v1",
+ KIND_MESSAGE_FILE,
+ "Direct Message File",
+ "RadrootsMessageFile",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Encrypted,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::Encrypted,
+ RadrootsEventDiscriminator::KindOnly,
+ P_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.social.generic_repost.v1",
+ KIND_GENERIC_REPOST,
+ "Generic Repost",
+ "RadrootsGenericRepost",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ EVENT_POINTER_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.farm.crdt_change.v1",
+ KIND_FARM_CRDT_CHANGE,
+ "Farm CRDT Change",
+ "RadrootsFarmCrdtChange",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Encrypted,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ NO_TAGS,
+ FARM_OPS_REDUCERS
+ ),
+ event_contract!(
+ "radroots.message.gift_wrap.v1",
+ KIND_GIFT_WRAP,
+ "Gift Wrap",
+ "RadrootsGiftWrap",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Encrypted,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::Encrypted,
+ RadrootsEventDiscriminator::KindOnly,
+ P_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.file.metadata.v1",
+ KIND_FILE_METADATA,
+ "File Metadata",
+ "RadrootsFileMetadata",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ FILE_METADATA_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.social.comment.v1",
+ KIND_COMMENT,
+ "Comment",
+ "RadrootsComment",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::PlainText,
+ RadrootsEventDiscriminator::KindOnly,
+ EVENT_POINTER_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.social.report.v1",
+ KIND_REPORT,
+ "Report",
+ "RadrootsReport",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::PlainText,
+ RadrootsEventDiscriminator::KindOnly,
+ EVENT_POINTER_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.put_user.v1",
+ KIND_GROUP_PUT_USER,
+ "Group Put User",
+ "RadrootsGroupPutUser",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_ACTION_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.remove_user.v1",
+ KIND_GROUP_REMOVE_USER,
+ "Group Remove User",
+ "RadrootsGroupRemoveUser",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_ACTION_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.edit_metadata.v1",
+ KIND_GROUP_EDIT_METADATA,
+ "Group Edit Metadata",
+ "RadrootsGroupEditMetadata",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_ACTION_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.delete_event.v1",
+ KIND_GROUP_DELETE_EVENT,
+ "Group Delete Event",
+ "RadrootsGroupDeleteEvent",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_ACTION_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.create_group.v1",
+ KIND_GROUP_CREATE_GROUP,
+ "Group Create Group",
+ "RadrootsGroupCreateGroup",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_ACTION_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.delete_group.v1",
+ KIND_GROUP_DELETE_GROUP,
+ "Group Delete Group",
+ "RadrootsGroupDeleteGroup",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_ACTION_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.create_invite.v1",
+ KIND_GROUP_CREATE_INVITE,
+ "Group Create Invite",
+ "RadrootsGroupCreateInvite",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_ACTION_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.join_request.v1",
+ KIND_GROUP_JOIN_REQUEST,
+ "Group Join Request",
+ "RadrootsGroupJoinRequest",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Member,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_ACTION_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.leave_request.v1",
+ KIND_GROUP_LEAVE_REQUEST,
+ "Group Leave Request",
+ "RadrootsGroupLeaveRequest",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Member,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_ACTION_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.social.geochat.v1",
+ KIND_GEOCHAT,
+ "Geochat",
+ "RadrootsGeochat",
+ RadrootsEventClass::Ephemeral,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::PlainText,
+ RadrootsEventDiscriminator::KindOnly,
+ NO_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.relay.auth.v1",
+ KIND_RELAY_AUTH,
+ "Relay Auth",
+ "RadrootsRelayAuth",
+ RadrootsEventClass::Ephemeral,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Relay,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ NO_TAGS,
+ RELAY_REDUCERS
+ ),
+ event_contract!(
+ "radroots.http.auth.v1",
+ KIND_HTTP_AUTH,
+ "HTTP Auth",
+ "RadrootsHttpAuth",
+ RadrootsEventClass::Ephemeral,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Application,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ NO_TAGS,
+ RELAY_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.mute.v1",
+ KIND_LIST_MUTE,
+ "Mute List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.pinned_notes.v1",
+ KIND_LIST_PINNED_NOTES,
+ "Pinned Notes List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.read_write_relays.v1",
+ KIND_LIST_READ_WRITE_RELAYS,
+ "Read Write Relays List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.bookmarks.v1",
+ KIND_LIST_BOOKMARKS,
+ "Bookmarks List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.communities.v1",
+ KIND_LIST_COMMUNITIES,
+ "Communities List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.public_chats.v1",
+ KIND_LIST_PUBLIC_CHATS,
+ "Public Chats List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.blocked_relays.v1",
+ KIND_LIST_BLOCKED_RELAYS,
+ "Blocked Relays List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.search_relays.v1",
+ KIND_LIST_SEARCH_RELAYS,
+ "Search Relays List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.simple_groups.v1",
+ KIND_LIST_SIMPLE_GROUPS,
+ "Simple Groups List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.relay_feeds.v1",
+ KIND_LIST_RELAY_FEEDS,
+ "Relay Feeds List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.interests.v1",
+ KIND_LIST_INTERESTS,
+ "Interests List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.media_follows.v1",
+ KIND_LIST_MEDIA_FOLLOWS,
+ "Media Follows List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.emojis.v1",
+ KIND_LIST_EMOJIS,
+ "Emojis List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.dm_relays.v1",
+ KIND_LIST_DM_RELAYS,
+ "DM Relays List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.good_wiki_authors.v1",
+ KIND_LIST_GOOD_WIKI_AUTHORS,
+ "Good Wiki Authors List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list.good_wiki_relays.v1",
+ KIND_LIST_GOOD_WIKI_RELAYS,
+ "Good Wiki Relays List",
+ "RadrootsList",
+ RadrootsEventClass::Replaceable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.follow.v1",
+ KIND_LIST_SET_FOLLOW,
+ "Follow Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.relay.v1",
+ KIND_LIST_SET_RELAY,
+ "Relay Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ RELAY_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.bookmark.v1",
+ KIND_LIST_SET_BOOKMARK,
+ "Bookmark Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.curation.v1",
+ KIND_LIST_SET_CURATION,
+ "Curation Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.video.v1",
+ KIND_LIST_SET_VIDEO,
+ "Video Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.picture.v1",
+ KIND_LIST_SET_PICTURE,
+ "Picture Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.kind_mute.v1",
+ KIND_LIST_SET_KIND_MUTE,
+ "Kind Mute Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.interest.v1",
+ KIND_LIST_SET_INTEREST,
+ "Interest Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.emoji.v1",
+ KIND_LIST_SET_EMOJI,
+ "Emoji Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.release_artifact.v1",
+ KIND_LIST_SET_RELEASE_ARTIFACT,
+ "Release Artifact Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.app_curation.v1",
+ KIND_LIST_SET_APP_CURATION,
+ "App Curation Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.social.article.v1",
+ KIND_ARTICLE,
+ "Long Form Article",
+ "RadrootsArticle",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::Markdown,
+ RadrootsEventDiscriminator::KindOnly,
+ ARTICLE_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.calendar.date_event.v1",
+ KIND_CALENDAR_DATE_EVENT,
+ "Calendar Date Event",
+ "RadrootsCalendarDateEvent",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CALENDAR_EVENT_TAGS,
+ CALENDAR_REDUCERS
+ ),
+ event_contract!(
+ "radroots.calendar.time_event.v1",
+ KIND_CALENDAR_TIME_EVENT,
+ "Calendar Time Event",
+ "RadrootsCalendarTimeEvent",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CALENDAR_EVENT_TAGS,
+ CALENDAR_REDUCERS
+ ),
+ event_contract!(
+ "radroots.calendar.collection.v1",
+ KIND_CALENDAR,
+ "Calendar Collection",
+ "RadrootsCalendar",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ CALENDAR_REDUCERS
+ ),
+ event_contract!(
+ "radroots.calendar.rsvp.v1",
+ KIND_CALENDAR_EVENT_RSVP,
+ "Calendar RSVP",
+ "RadrootsCalendarRsvp",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CALENDAR_EVENT_TAGS,
+ CALENDAR_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.starter_pack.v1",
+ KIND_LIST_SET_STARTER_PACK,
+ "Starter Pack Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.list_set.media_starter_pack.v1",
+ KIND_LIST_SET_MEDIA_STARTER_PACK,
+ "Media Starter Pack Set",
+ "RadrootsListSet",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LIST_SET_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.farm.profile.v1",
+ KIND_FARM,
+ "Farm",
+ "RadrootsFarm",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ FARM_TAGS,
+ FARM_OPS_REDUCERS
+ ),
+ event_contract!(
+ "radroots.farm.plot.v1",
+ KIND_PLOT,
+ "Plot",
+ "RadrootsPlot",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ FARM_TAGS,
+ FARM_OPS_REDUCERS
+ ),
+ event_contract!(
+ "radroots.farm.coop.v1",
+ KIND_COOP,
+ "Coop",
+ "RadrootsCoop",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ FARM_TAGS,
+ FARM_OPS_REDUCERS
+ ),
+ event_contract!(
+ "radroots.farm.document.v1",
+ KIND_DOCUMENT,
+ "Document",
+ "RadrootsDocument",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ D_TAGS,
+ FARM_OPS_REDUCERS
+ ),
+ event_contract!(
+ "radroots.farm.resource_area.v1",
+ KIND_RESOURCE_AREA,
+ "Resource Area",
+ "RadrootsResourceArea",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ FARM_TAGS,
+ FARM_OPS_REDUCERS
+ ),
+ event_contract!(
+ "radroots.farm.resource_harvest_cap.v1",
+ KIND_RESOURCE_HARVEST_CAP,
+ "Resource Harvest Capacity",
+ "RadrootsResourceHarvestCap",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ FARM_TAGS,
+ FARM_OPS_REDUCERS
+ ),
+ event_contract!(
+ "radroots.account.claim.v1",
+ KIND_ACCOUNT_CLAIM,
+ "Account Claim",
+ "RadrootsAccountClaim",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ D_TAGS,
+ PROFILE_REDUCERS
+ ),
+ event_contract!(
+ "radroots.farm.workspace_manifest.v1",
+ KIND_FARM_WORKSPACE_MANIFEST,
+ "Farm Workspace Manifest",
+ "RadrootsFarmWorkspaceManifest",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Encrypted,
+ RadrootsActorRole::Farmer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ D_TAGS,
+ FARM_OPS_REDUCERS
+ ),
+ event_contract!(
+ "radroots.listing.published.v1",
+ KIND_LISTING,
+ "Listing",
+ "RadrootsListing",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Seller,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LISTING_TAGS,
+ LISTING_REDUCERS
+ ),
+ event_contract!(
+ "radroots.listing.draft.v1",
+ KIND_LISTING_DRAFT,
+ "Listing Draft",
+ "RadrootsListing",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Secret,
+ RadrootsActorRole::Seller,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ LISTING_TAGS,
+ LISTING_REDUCERS
+ ),
+ event_contract!(
+ "radroots.application.handler.v1",
+ KIND_APPLICATION_HANDLER,
+ "Application Handler",
+ "RadrootsApplicationHandler",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Application,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ D_TAGS,
+ SOCIAL_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.metadata.v1",
+ KIND_GROUP_METADATA,
+ "Group Metadata",
+ "RadrootsGroupMetadata",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_STATE_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.admins.v1",
+ KIND_GROUP_ADMINS,
+ "Group Admins",
+ "RadrootsGroupAdmins",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_STATE_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.members.v1",
+ KIND_GROUP_MEMBERS,
+ "Group Members",
+ "RadrootsGroupMembers",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_STATE_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.group.roles.v1",
+ KIND_GROUP_ROLES,
+ "Group Roles",
+ "RadrootsGroupRoles",
+ RadrootsEventClass::Addressable,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Moderator,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ GROUP_STATE_TAGS,
+ GROUP_REDUCERS
+ ),
+ event_contract!(
+ "radroots.trade.listing_validation.request.v1",
+ KIND_TRADE_LISTING_VALIDATION_REQUEST,
+ "Trade Listing Validation Request",
+ "RadrootsTradeValidationListingRequest",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Service,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ TRADE_VALIDATION_REQUEST_TAGS,
+ TRADE_VALIDATION_REDUCERS
+ ),
+ event_contract!(
+ "radroots.trade.listing_validation.result.v1",
+ KIND_TRADE_LISTING_VALIDATION_RESULT,
+ "Trade Listing Validation Result",
+ "RadrootsTradeValidationListingResult",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Service,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ TRADE_VALIDATION_RESULT_TAGS,
+ TRADE_VALIDATION_REDUCERS
+ ),
+ event_contract!(
+ "radroots.trade.transition_proof.request.v1",
+ KIND_TRADE_TRANSITION_PROOF_REQUEST,
+ "Trade Transition Proof Request",
+ "RadrootsTradeTransitionProofRequest",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Service,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ TRADE_VALIDATION_REQUEST_TAGS,
+ TRADE_VALIDATION_REDUCERS
+ ),
+ event_contract!(
+ "radroots.trade.transition_proof.result.v1",
+ KIND_TRADE_TRANSITION_PROOF_RESULT,
+ "Trade Transition Proof Result",
+ "RadrootsTradeTransitionProofResult",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Service,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ TRADE_VALIDATION_RESULT_TAGS,
+ TRADE_VALIDATION_REDUCERS
+ ),
+ event_contract!(
+ "radroots.order.request.v1",
+ KIND_ORDER_REQUEST,
+ "Order Request",
+ "RadrootsOrderRequest",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Buyer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ ORDER_REQUEST_TAGS,
+ ORDER_REDUCERS
+ ),
+ event_contract!(
+ "radroots.order.decision.v1",
+ KIND_ORDER_DECISION,
+ "Order Decision",
+ "RadrootsOrderDecision",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Seller,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CHAINED_ORDER_TAGS,
+ ORDER_REDUCERS
+ ),
+ event_contract!(
+ "radroots.order.revision_proposal.v1",
+ KIND_ORDER_REVISION_PROPOSAL,
+ "Order Revision Proposal",
+ "RadrootsOrderRevisionProposal",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Buyer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CHAINED_ORDER_TAGS,
+ ORDER_REDUCERS
+ ),
+ event_contract!(
+ "radroots.order.revision_decision.v1",
+ KIND_ORDER_REVISION_DECISION,
+ "Order Revision Decision",
+ "RadrootsOrderRevisionDecision",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Seller,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CHAINED_ORDER_TAGS,
+ ORDER_REDUCERS
+ ),
+ event_contract!(
+ "radroots.order.cancellation.v1",
+ KIND_ORDER_CANCELLATION,
+ "Order Cancellation",
+ "RadrootsOrderCancellation",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Buyer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CHAINED_ORDER_TAGS,
+ ORDER_REDUCERS
+ ),
+ event_contract!(
+ "radroots.order.fulfillment_update.v1",
+ KIND_ORDER_FULFILLMENT_UPDATE,
+ "Order Fulfillment Update",
+ "RadrootsOrderFulfillmentUpdate",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Seller,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CHAINED_ORDER_TAGS,
+ ORDER_REDUCERS
+ ),
+ event_contract!(
+ "radroots.order.receipt.v1",
+ KIND_ORDER_RECEIPT,
+ "Order Receipt",
+ "RadrootsOrderReceipt",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Buyer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CHAINED_ORDER_TAGS,
+ ORDER_REDUCERS
+ ),
+ event_contract!(
+ "radroots.order.payment_record.v1",
+ KIND_ORDER_PAYMENT_RECORD,
+ "Order Payment Record",
+ "RadrootsOrderPaymentRecord",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Buyer,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CHAINED_ORDER_TAGS,
+ ORDER_REDUCERS
+ ),
+ event_contract!(
+ "radroots.order.settlement_decision.v1",
+ KIND_ORDER_SETTLEMENT_DECISION,
+ "Order Settlement Decision",
+ "RadrootsOrderSettlementDecision",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Seller,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ CHAINED_ORDER_TAGS,
+ ORDER_REDUCERS
+ ),
+ event_contract!(
+ "radroots.trade.validation_receipt.v1",
+ KIND_TRADE_VALIDATION_RECEIPT,
+ "Trade Validation Receipt",
+ "RadrootsTradeValidationReceipt",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Service,
+ RadrootsContentSchema::JsonObject,
+ RadrootsEventDiscriminator::KindOnly,
+ TRADE_VALIDATION_RECEIPT_TAGS,
+ TRADE_VALIDATION_REDUCERS
+ ),
];
-pub fn contract_for_kind(kind: u32) -> Option<&'static RadrootsEventContract> {
+pub fn all_kind_contracts() -> &'static [RadrootsKindContract] {
+ ALL_KIND_CONTRACTS
+}
+
+pub fn all_event_contracts() -> &'static [RadrootsEventContract] {
ALL_EVENT_CONTRACTS
+}
+
+pub fn kind_contract(kind: u32) -> Option<&'static RadrootsKindContract> {
+ ALL_KIND_CONTRACTS
.iter()
.find(|contract| contract.kind == kind)
}
-pub fn all_contracts() -> &'static [RadrootsEventContract] {
- &ALL_EVENT_CONTRACTS
+pub fn event_contract(id: &str) -> Option<&'static RadrootsEventContract> {
+ ALL_EVENT_CONTRACTS
+ .iter()
+ .find(|contract| contract.id == id)
+ .or_else(|| {
+ LIST_SET_GENERIC_EVENT_CONTRACTS
+ .iter()
+ .find(|contract| contract.id == id)
+ })
}
-pub fn order_event_contracts() -> &'static [RadrootsEventContract] {
- &ORDER_EVENT_CONTRACTS
+pub fn event_contracts_for_kind(kind: u32) -> &'static [RadrootsEventContract] {
+ if kind == KIND_LIST_SET_GENERIC {
+ return LIST_SET_GENERIC_EVENT_CONTRACTS;
+ }
+
+ match ALL_EVENT_CONTRACTS
+ .iter()
+ .find(|contract| contract.kind == kind)
+ {
+ Some(contract) => core::slice::from_ref(contract),
+ None => &[],
+ }
}
-pub fn listing_event_contracts() -> &'static [RadrootsEventContract] {
- &LISTING_EVENT_CONTRACTS
+pub fn identify_event_contract(
+ kind: u32,
+ tags: &[Vec<String>],
+ content: &str,
+) -> Result<&'static RadrootsEventContract, RadrootsContractMatchError> {
+ if kind_contract(kind).is_none() {
+ return Err(RadrootsContractMatchError::UnsupportedKind(kind));
+ }
+
+ identify_from_contracts(event_contracts_for_kind(kind), kind, tags, content)
}
-pub fn trade_validation_contracts() -> &'static [RadrootsEventContract] {
- &TRADE_VALIDATION_CONTRACTS
+fn identify_from_contracts(
+ contracts: &'static [RadrootsEventContract],
+ kind: u32,
+ tags: &[Vec<String>],
+ content: &str,
+) -> Result<&'static RadrootsEventContract, RadrootsContractMatchError> {
+ let mut matched = None;
+ let mut matched_count = 0;
+
+ for contract in contracts {
+ if discriminator_matches(&contract.discriminator, tags, content) {
+ matched = Some(contract);
+ matched_count += 1;
+ }
+ }
+
+ match (matched, matched_count) {
+ (Some(contract), 1) => Ok(contract),
+ (None, _) => Err(RadrootsContractMatchError::UnsupportedShape(kind)),
+ (Some(_), _) => Err(RadrootsContractMatchError::AmbiguousShape(kind)),
+ }
+}
+
+fn discriminator_matches(
+ discriminator: &RadrootsEventDiscriminator,
+ tags: &[Vec<String>],
+ content: &str,
+) -> bool {
+ match discriminator {
+ RadrootsEventDiscriminator::KindOnly => true,
+ RadrootsEventDiscriminator::DTagExact(expected) => tag_value(tags, "d") == Some(*expected),
+ RadrootsEventDiscriminator::DTagPrefix(prefix) => tag_value(tags, "d")
+ .map(|value| value.starts_with(prefix))
+ .unwrap_or(false),
+ RadrootsEventDiscriminator::DTagSuffix(suffix) => tag_value(tags, "d")
+ .map(|value| value.ends_with(suffix))
+ .unwrap_or(false),
+ RadrootsEventDiscriminator::TagEquals { name, value } => {
+ tag_value(tags, name) == Some(*value)
+ }
+ RadrootsEventDiscriminator::ContentJsonFieldEquals { field, value } => {
+ content_json_string_field_equals(content, field, value)
+ }
+ RadrootsEventDiscriminator::EnvelopeType(expected) => {
+ content_json_string_field_equals(content, "type", expected)
+ }
+ RadrootsEventDiscriminator::Composite(parts) => parts
+ .iter()
+ .all(|part| discriminator_matches(part, tags, content)),
+ }
+}
+
+fn tag_value<'a>(tags: &'a [Vec<String>], name: &str) -> Option<&'a str> {
+ tags.iter().find_map(|tag| {
+ if tag.first().map(|value| value.as_str()) == Some(name) {
+ tag.get(1).map(|value| value.as_str())
+ } else {
+ None
+ }
+ })
+}
+
+fn content_json_string_field_equals(content: &str, field: &str, value: &str) -> bool {
+ let mut quoted = content.split('"');
+ while let Some(token) = quoted.next() {
+ if token == field {
+ if let Some(separator) = quoted.next() {
+ if separator.trim_start().starts_with(':') {
+ return quoted.next() == Some(value);
+ }
+ }
+ }
+ }
+ false
}
#[cfg(test)]
mod tests {
use super::*;
- use crate::kinds::{COMMERCIAL_EVENT_KINDS, ORDER_EVENT_KINDS, TRADE_VALIDATION_EVENT_KINDS};
+ use std::collections::BTreeSet;
+
+ static AMBIGUOUS_TEST_CONTRACTS: &[RadrootsEventContract] = &[
+ event_contract!(
+ "radroots.test.one.v1",
+ KIND_POST,
+ "Test One",
+ "Test",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::PlainText,
+ RadrootsEventDiscriminator::KindOnly,
+ NO_TAGS,
+ SOCIAL_REDUCERS,
+ ),
+ event_contract!(
+ "radroots.test.two.v1",
+ KIND_POST,
+ "Test Two",
+ "Test",
+ RadrootsEventClass::Regular,
+ RadrootsEventPrivacy::Public,
+ RadrootsActorRole::Any,
+ RadrootsContentSchema::PlainText,
+ RadrootsEventDiscriminator::KindOnly,
+ NO_TAGS,
+ SOCIAL_REDUCERS,
+ ),
+ ];
#[test]
- fn exposes_scoped_contract_sets() {
- assert_eq!(all_contracts().len(), COMMERCIAL_EVENT_KINDS.len());
- assert_eq!(listing_event_contracts().len(), 2);
- assert_eq!(order_event_contracts().len(), ORDER_EVENT_KINDS.len());
- assert_eq!(
- trade_validation_contracts().len(),
- TRADE_VALIDATION_EVENT_KINDS.len()
- );
+ fn exposes_one_kind_contract_per_supported_kind() {
+ let mut kinds = BTreeSet::new();
+ for contract in all_kind_contracts() {
+ assert!(
+ kinds.insert(contract.kind),
+ "duplicate kind {}",
+ contract.kind
+ );
+ assert!(!contract.accepted_event_contracts.is_empty());
+ }
}
#[test]
- fn every_commercial_kind_has_one_contract() {
- for kind in COMMERCIAL_EVENT_KINDS {
- let matches = all_contracts()
- .iter()
- .filter(|contract| contract.kind == kind)
- .count();
- assert_eq!(matches, 1, "kind {kind}");
- assert_eq!(
- contract_for_kind(kind).map(|contract| contract.kind),
- Some(kind)
+ fn exposes_unique_event_contract_ids() {
+ let mut ids = BTreeSet::new();
+ for contract in all_event_contracts()
+ .iter()
+ .chain(LIST_SET_GENERIC_EVENT_CONTRACTS.iter())
+ {
+ assert!(
+ ids.insert(contract.id),
+ "duplicate event contract {}",
+ contract.id
);
+ assert!(kind_contract(contract.kind).is_some());
}
}
#[test]
- fn order_request_contract_requires_listing_snapshot_without_relay_indexing() {
- let contract = contract_for_kind(KIND_ORDER_REQUEST).expect("order request contract");
- assert_eq!(contract.class, RadrootsEventClass::Regular);
- assert_eq!(contract.author_role, RadrootsActorRole::Buyer);
- assert!(contract.tags.iter().any(|tag| {
- tag.name == "p"
- && tag.cardinality == RadrootsTagCardinality::RequiredOne
- && tag.semantic == RadrootsTagSemantic::Counterparty
- }));
- assert!(contract.tags.iter().any(|tag| {
- tag.name == "a"
- && tag.cardinality == RadrootsTagCardinality::RequiredOne
- && tag.semantic == RadrootsTagSemantic::ListingAddress
- }));
- assert!(contract.tags.iter().any(|tag| {
- tag.name == "d"
- && tag.cardinality == RadrootsTagCardinality::RequiredOne
- && tag.semantic == RadrootsTagSemantic::Identifier
- }));
- assert!(contract.tags.iter().any(|tag| {
- tag.name == "listing_event"
- && tag.cardinality == RadrootsTagCardinality::RequiredOne
- && tag.semantic == RadrootsTagSemantic::ListingSnapshot
- && !tag.relay_indexed
- }));
+ fn every_kind_references_known_matching_event_contracts() {
+ for kind in all_kind_contracts() {
+ for id in kind.accepted_event_contracts {
+ let event = event_contract(id).expect("accepted event contract");
+ assert_eq!(event.kind, kind.kind, "{}", id);
+ }
+ }
}
#[test]
- fn chained_order_contract_requires_root_and_previous_event_tags() {
- let contract = contract_for_kind(KIND_ORDER_DECISION).expect("order decision contract");
- assert_eq!(contract.class, RadrootsEventClass::Regular);
- assert!(contract.tags.iter().any(|tag| {
- tag.name == "e"
- && tag.cardinality == RadrootsTagCardinality::RequiredOne
- && tag.semantic == RadrootsTagSemantic::RootEvent
- }));
- assert!(contract.tags.iter().any(|tag| {
- tag.name == "e"
- && tag.cardinality == RadrootsTagCardinality::RequiredOne
- && tag.semantic == RadrootsTagSemantic::PreviousEvent
- }));
+ fn covers_public_kind_arrays() {
+ for kind in COMMERCIAL_EVENT_KINDS
+ .iter()
+ .chain(PUBLIC_SOCIAL_KINDS.iter())
+ .chain(PRIVATE_FARM_OPS_KINDS.iter())
+ .chain(NIP29_GROUP_KINDS.iter())
+ {
+ assert!(kind_contract(*kind).is_some(), "missing kind {kind}");
+ }
}
#[test]
- fn validation_receipt_is_trade_validation_contract() {
- let contract =
- contract_for_kind(KIND_TRADE_VALIDATION_RECEIPT).expect("validation receipt contract");
- assert_eq!(contract.id, "trade_validation_receipt");
- assert_eq!(contract.author_role, RadrootsActorRole::Service);
- assert!(
- contract
- .reducers
- .contains(&RadrootsReducer::TradeValidation)
- );
+ fn event_contract_lookup_supports_many_contracts_per_kind() {
+ let contracts = event_contracts_for_kind(KIND_LIST_SET_GENERIC);
+ assert_eq!(contracts.len(), 6);
assert!(
- trade_validation_contracts()
+ contracts
.iter()
- .any(|contract| contract.kind == KIND_TRADE_VALIDATION_RECEIPT)
+ .any(|contract| contract.id == "radroots.list_set.farm.members.v1")
);
+ assert_eq!(
+ event_contract("radroots.list_set.member_of.farms.v1").map(|contract| contract.kind),
+ Some(KIND_LIST_SET_GENERIC)
+ );
+ }
+
+ #[test]
+ fn identifies_exact_list_set_shape() {
+ let tags = vec![vec!["d".to_owned(), "member_of.farms".to_owned()]];
+ let contract = identify_event_contract(KIND_LIST_SET_GENERIC, &tags, "{}")
+ .expect("member_of farms contract");
+ assert_eq!(contract.id, "radroots.list_set.member_of.farms.v1");
+ }
+
+ #[test]
+ fn identifies_composite_list_set_shape() {
+ let tags = vec![vec![
+ "d".to_owned(),
+ "farm:farm_01:members.workers".to_owned(),
+ ]];
+ let contract = identify_event_contract(KIND_LIST_SET_GENERIC, &tags, "{}")
+ .expect("farm workers contract");
+ assert_eq!(contract.id, "radroots.list_set.farm.members.workers.v1");
+ }
+
+ #[test]
+ fn rejects_unknown_or_unsupported_shapes() {
+ assert_eq!(
+ identify_event_contract(999_999, &[], "{}"),
+ Err(RadrootsContractMatchError::UnsupportedKind(999_999))
+ );
+
+ let tags = vec![vec!["d".to_owned(), "unknown".to_owned()]];
+ assert_eq!(
+ identify_event_contract(KIND_LIST_SET_GENERIC, &tags, "{}"),
+ Err(RadrootsContractMatchError::UnsupportedShape(
+ KIND_LIST_SET_GENERIC
+ ))
+ );
+ }
+
+ #[test]
+ fn rejects_ambiguous_shapes() {
+ assert_eq!(
+ identify_from_contracts(AMBIGUOUS_TEST_CONTRACTS, KIND_POST, &[], ""),
+ Err(RadrootsContractMatchError::AmbiguousShape(KIND_POST))
+ );
+ }
+
+ #[test]
+ fn supports_content_field_discriminators_without_json_dependency() {
+ assert!(discriminator_matches(
+ &RadrootsEventDiscriminator::EnvelopeType("order_request"),
+ &[],
+ r#"{"domain":"radroots.order","type":"order_request"}"#
+ ));
+ assert!(discriminator_matches(
+ &RadrootsEventDiscriminator::ContentJsonFieldEquals {
+ field: "domain",
+ value: "radroots.order"
+ },
+ &[],
+ r#"{"domain": "radroots.order", "type": "order_request"}"#
+ ));
+ }
+
+ #[test]
+ fn relay_indexed_tags_are_single_letter() {
+ for contract in all_event_contracts()
+ .iter()
+ .chain(LIST_SET_GENERIC_EVENT_CONTRACTS.iter())
+ {
+ for tag in contract.tags {
+ if tag.relay_indexed {
+ assert_eq!(tag.name.len(), 1, "{}:{}", contract.id, tag.name);
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn addressable_event_contracts_require_d_tags() {
+ for contract in all_event_contracts()
+ .iter()
+ .chain(LIST_SET_GENERIC_EVENT_CONTRACTS.iter())
+ {
+ if contract.class == RadrootsEventClass::Addressable {
+ assert!(
+ contract.tags.iter().any(|tag| tag.name == "d"
+ && tag.cardinality == RadrootsTagCardinality::RequiredOne),
+ "{}",
+ contract.id
+ );
+ }
+ }
}
}