sdk

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

commit 7d4b0d701167691ee8ea04d436acb0d2565ae347
parent 0bcdc82efff93198de3fd8f53c9a2acd75a2148c
Author: triesap <tyson@radroots.org>
Date:   Fri, 26 Jun 2026 08:23:13 +0000

sdk: expose RadrootsClient trade facade

- Replace the public SDK facade with RadrootsClient and trades().
- Add thin product client handles for farms, listings, market, trades, sync, and DVM.
- Regenerate events bindings with target trade DTO export names.
- Validate with full SDK workspace all-feature tests and stale API scans.

Diffstat:
Mcrates/sdk/examples/runtime_local.rs | 6+++---
Mcrates/sdk/examples/sdk_v1_listing_prepare.rs | 4++--
Mcrates/sdk/examples/sdk_v1_local_enqueue_and_mock_sync.rs | 6+++---
Mcrates/sdk/examples/sdk_v1_myc_nip46_signer_setup.rs | 4++--
Mcrates/sdk/src/lib.rs | 8+++++---
Mcrates/sdk/src/orders_runtime.rs | 19++++++++++++++-----
Mcrates/sdk/src/product_clients.rs | 60+++++++++++++++++++++++++++++++++++++++++++-----------------
Mcrates/sdk/src/runtime.rs | 36++++++++++++++++++++++--------------
Mcrates/sdk/src/workflow_runtime.rs | 10+++++-----
Mcrates/sdk/tests/facade.rs | 6+++---
Mcrates/sdk/tests/farms_runtime.rs | 8++++----
Mcrates/sdk/tests/listings_runtime.rs | 8++++----
Mcrates/sdk/tests/orders_runtime.rs | 180+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mcrates/sdk/tests/runtime_foundation.rs | 44+++++++++++++++++++++++---------------------
Mcrates/sdk/tests/source_boundary.rs | 35+++++++++++++++++++++++++++--------
Mcrates/sdk/tests/sync_runtime.rs | 84++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mcrates/sdk/tests/unit/farms_runtime_tests.rs | 10+++++-----
Mcrates/sdk/tests/unit/listings_runtime_tests.rs | 10+++++-----
Mcrates/sdk/tests/unit/orders_runtime_tests.rs | 206+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Mcrates/sdk/tests/unit/runtime_tests.rs | 34+++++++++++++++++++---------------
Mcrates/sdk/tests/unit/signer_provider_tests.rs | 2+-
Mcrates/sdk/tests/unit/sync_runtime_tests.rs | 6+++---
Mcrates/sdk/tests/unit/workflow_runtime_tests.rs | 8++++----
Mpackages/events-bindings/src/generated/types.ts | 130++++++++++++++++++++++++++++++++++++++++----------------------------------------
24 files changed, 505 insertions(+), 419 deletions(-)

diff --git a/crates/sdk/examples/runtime_local.rs b/crates/sdk/examples/runtime_local.rs @@ -11,7 +11,7 @@ use radroots_sdk::protocol::listing::{ RadrootsListing, RadrootsListingBin, RadrootsListingProduct, }; use radroots_sdk::{ - ListingPreparePublishRequest, OrderStatusRequest, PushOutboxRequest, RadrootsSdk, + ListingPreparePublishRequest, OrderStatusRequest, PushOutboxRequest, RadrootsClient, RadrootsSdkError, RadrootsSdkLocalKeySigner, RadrootsSdkSignerProvider, RadrootsSdkTimestamp, SdkIdempotencyKey, SdkRelayTargetPolicy, SdkRelayUrlPolicy, }; @@ -23,7 +23,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { let keys = RadrootsNostrKeys::generate(); let seller = keys.public_key().to_hex(); let signer = RadrootsSdkLocalKeySigner::new(keys)?; - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)) .signer_provider(RadrootsSdkSignerProvider::LocalKey(signer)) .build() @@ -49,7 +49,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { .push_outbox(PushOutboxRequest::new().with_limit(1)) .await; let order_status = sdk - .orders() + .trades() .status(OrderStatusRequest::parse("example-order-1")?) .await?; diff --git a/crates/sdk/examples/sdk_v1_listing_prepare.rs b/crates/sdk/examples/sdk_v1_listing_prepare.rs @@ -9,13 +9,13 @@ use radroots_sdk::protocol::farm::RadrootsFarmRef; use radroots_sdk::protocol::listing::{ RadrootsListing, RadrootsListingBin, RadrootsListingProduct, }; -use radroots_sdk::{ListingPreparePublishRequest, RadrootsSdk, RadrootsSdkTimestamp}; +use radroots_sdk::{ListingPreparePublishRequest, RadrootsClient, RadrootsSdkTimestamp}; const SELLER: &str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)) .build() .await?; diff --git a/crates/sdk/examples/sdk_v1_local_enqueue_and_mock_sync.rs b/crates/sdk/examples/sdk_v1_local_enqueue_and_mock_sync.rs @@ -12,7 +12,7 @@ use radroots_sdk::protocol::listing::{ RadrootsListing, RadrootsListingBin, RadrootsListingProduct, }; use radroots_sdk::{ - ListingPreparePublishRequest, OrderStatusRequest, PushOutboxRequest, RadrootsSdk, + ListingPreparePublishRequest, OrderStatusRequest, PushOutboxRequest, RadrootsClient, RadrootsSdkLocalKeySigner, RadrootsSdkSignerProvider, RadrootsSdkTimestamp, SdkIdempotencyKey, SdkRelayTargetPolicy, SdkRelayTargetSet, SdkRelayUrlPolicy, }; @@ -24,7 +24,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { let keys = RadrootsNostrKeys::generate(); let seller = keys.public_key().to_hex(); let signer = RadrootsSdkLocalKeySigner::new(keys)?; - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)) .signer_provider(RadrootsSdkSignerProvider::LocalKey(signer)) .build() @@ -54,7 +54,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { .push_outbox_with_adapter(&adapter, PushOutboxRequest::new().with_limit(1)) .await?; let order_status = sdk - .orders() + .trades() .status(OrderStatusRequest::parse("example-order-1")?) .await?; diff --git a/crates/sdk/examples/sdk_v1_myc_nip46_signer_setup.rs b/crates/sdk/examples/sdk_v1_myc_nip46_signer_setup.rs @@ -3,7 +3,7 @@ use radroots_nostr_connect::prelude::{ RadrootsNostrConnectClientTarget, RadrootsNostrConnectError, }; use radroots_sdk::{ - RadrootsSdk, RadrootsSdkMycNip46Signer, RadrootsSdkNip46Transport, + RadrootsClient, RadrootsSdkMycNip46Signer, RadrootsSdkNip46Transport, RadrootsSdkNip46TransportFuture, RadrootsSdkSignerMode, RadrootsSdkSignerProvider, radroots_sdk_myc_nip46_product_permission_strings, }; @@ -41,7 +41,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { user_keys.public_key().to_hex(), Arc::new(ExampleNip46Transport), )?; - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .signer_provider(RadrootsSdkSignerProvider::MycNip46(signer)) .build() .await?; diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs @@ -99,15 +99,17 @@ pub use crate::orders_runtime::{ SdkOrderStatusIssueKind, SdkOrderStatusSource, }; #[cfg(feature = "runtime")] -pub use crate::product_clients::{FarmsClient, ListingsClient, OrdersClient, SyncClient}; +pub use crate::product_clients::{ + DvmClient, FarmsClient, ListingsClient, MarketClient, SyncClient, TradesClient, +}; #[cfg(feature = "runtime")] pub use crate::relay_targets::{ SDK_RELAY_TARGET_MAX_COUNT, SdkRelayTargetPolicy, SdkRelayTargetSet, SdkRelayUrlPolicy, }; #[cfg(feature = "runtime")] pub use crate::runtime::{ - BackupReceipt, BackupRequest, IntegrityReceipt, IntegrityRequest, RadrootsSdk, - RadrootsSdkBuilder, RadrootsSdkClock, RadrootsSdkStorageConfig, RadrootsSdkStoragePaths, + BackupReceipt, BackupRequest, IntegrityReceipt, IntegrityRequest, RadrootsClient, + RadrootsClientBuilder, RadrootsSdkClock, RadrootsSdkStorageConfig, RadrootsSdkStoragePaths, RadrootsSdkTimestamp, RestoreArchive, RestoreReceipt, RestoreRequest, SdkBackupManifest, SdkBackupManifestKind, SdkBackupState, SdkBackupVerification, SdkEventStoreStorageStatus, SdkOutboxStorageStatus, SdkPublishTransport, SdkRestoreState, SdkSqliteStoreStatus, diff --git a/crates/sdk/src/orders_runtime.rs b/crates/sdk/src/orders_runtime.rs @@ -2,8 +2,8 @@ use crate::workflow_runtime::enqueue_configured_signed_workflow; #[cfg(feature = "runtime")] use crate::{ - OrdersClient, RadrootsSdkError, RadrootsSdkRecoveryAction, RadrootsSdkTimestamp, - SdkIdempotencyKey, SdkMutationState, SdkRelayTargetPolicy, SdkRelayUrlPolicy, order, + RadrootsSdkError, RadrootsSdkRecoveryAction, RadrootsSdkTimestamp, SdkIdempotencyKey, + SdkMutationState, SdkRelayTargetPolicy, SdkRelayUrlPolicy, TradesClient, order, workflow_runtime::{SdkWorkflowEnqueueRequest, enqueue_signed_workflow}, }; #[cfg(feature = "runtime")] @@ -968,6 +968,7 @@ pub enum OrderStatusNextActionKind { InspectEvidenceIssues, AwaitSellerDecision, DecideRevision, + AwaitRhiValidation, Terminal, } @@ -1109,7 +1110,7 @@ impl SdkOrderStatusIssueKind { } #[cfg(feature = "runtime")] -impl<'sdk> OrdersClient<'sdk> { +impl<'sdk> TradesClient<'sdk> { pub async fn ingest_evidence( &self, request: OrderEvidenceIngestRequest, @@ -2007,6 +2008,7 @@ impl OrderStatusEligibility { let clean = projection.issues.is_empty(); let open = clean && !projection.lifecycle_terminal; let requested = projection.status == RadrootsTradeWorkflowState::Requested; + let revision_proposed = projection.status == RadrootsTradeWorkflowState::RevisionProposed; let has_pending_revision = projection.pending_revision_event_id.is_some(); Self { @@ -2015,7 +2017,7 @@ impl OrderStatusEligibility { && projection.decision_event_id.is_none() && !has_pending_revision, can_propose_revision: open && requested && !has_pending_revision, - can_decide_revision: open && requested && has_pending_revision, + can_decide_revision: open && revision_proposed && has_pending_revision, can_cancel: open && requested && !has_pending_revision, } } @@ -2034,6 +2036,9 @@ impl OrderStatusNextActionKind { { return Self::InspectEvidenceIssues; } + if projection.status == RadrootsTradeWorkflowState::AgreedPendingRhi { + return Self::AwaitRhiValidation; + } if projection.lifecycle_terminal { return Self::Terminal; } @@ -2719,7 +2724,11 @@ fn require_revision_decision_state( previous_event_id: &plan.previous_event_id, }; require_clean_lifecycle_projection(refs, projection)?; - require_lifecycle_status(&refs, projection, RadrootsTradeWorkflowState::Requested)?; + require_lifecycle_status( + &refs, + projection, + RadrootsTradeWorkflowState::RevisionProposed, + )?; require_no_lifecycle_terminal(&refs, projection)?; require_pending_revision(&refs, projection)?; require_lifecycle_previous_is_current(&refs, projection) diff --git a/crates/sdk/src/product_clients.rs b/crates/sdk/src/product_clients.rs @@ -1,54 +1,80 @@ #[cfg(feature = "runtime")] -use crate::RadrootsSdk; +use crate::RadrootsClient; #[cfg(feature = "runtime")] #[derive(Clone, Copy)] -pub struct FarmsClient<'sdk> { - pub(crate) sdk: &'sdk RadrootsSdk, +pub struct FarmsClient<'client> { + pub(crate) sdk: &'client RadrootsClient, } #[cfg(feature = "runtime")] -impl<'sdk> FarmsClient<'sdk> { - pub(crate) fn new(sdk: &'sdk RadrootsSdk) -> Self { +impl<'client> FarmsClient<'client> { + pub(crate) fn new(sdk: &'client RadrootsClient) -> Self { Self { sdk } } } #[cfg(feature = "runtime")] #[derive(Clone, Copy)] -pub struct ListingsClient<'sdk> { - pub(crate) sdk: &'sdk RadrootsSdk, +pub struct ListingsClient<'client> { + pub(crate) sdk: &'client RadrootsClient, } #[cfg(feature = "runtime")] -impl<'sdk> ListingsClient<'sdk> { - pub(crate) fn new(sdk: &'sdk RadrootsSdk) -> Self { +impl<'client> ListingsClient<'client> { + pub(crate) fn new(sdk: &'client RadrootsClient) -> Self { Self { sdk } } } #[cfg(feature = "runtime")] #[derive(Clone, Copy)] -pub struct OrdersClient<'sdk> { - pub(crate) sdk: &'sdk RadrootsSdk, +pub struct MarketClient<'client> { + pub(crate) _sdk: &'client RadrootsClient, } #[cfg(feature = "runtime")] -impl<'sdk> OrdersClient<'sdk> { - pub(crate) fn new(sdk: &'sdk RadrootsSdk) -> Self { +impl<'client> MarketClient<'client> { + pub(crate) fn new(sdk: &'client RadrootsClient) -> Self { + Self { _sdk: sdk } + } +} + +#[cfg(feature = "runtime")] +#[derive(Clone, Copy)] +pub struct TradesClient<'client> { + pub(crate) sdk: &'client RadrootsClient, +} + +#[cfg(feature = "runtime")] +impl<'client> TradesClient<'client> { + pub(crate) fn new(sdk: &'client RadrootsClient) -> Self { Self { sdk } } } #[cfg(feature = "runtime")] #[derive(Clone, Copy)] -pub struct SyncClient<'sdk> { - pub(crate) sdk: &'sdk RadrootsSdk, +pub struct DvmClient<'client> { + pub(crate) _sdk: &'client RadrootsClient, +} + +#[cfg(feature = "runtime")] +impl<'client> DvmClient<'client> { + pub(crate) fn new(sdk: &'client RadrootsClient) -> Self { + Self { _sdk: sdk } + } +} + +#[cfg(feature = "runtime")] +#[derive(Clone, Copy)] +pub struct SyncClient<'client> { + pub(crate) sdk: &'client RadrootsClient, } #[cfg(feature = "runtime")] -impl<'sdk> SyncClient<'sdk> { - pub(crate) fn new(sdk: &'sdk RadrootsSdk) -> Self { +impl<'client> SyncClient<'client> { + pub(crate) fn new(sdk: &'client RadrootsClient) -> Self { Self { sdk } } } diff --git a/crates/sdk/src/runtime.rs b/crates/sdk/src/runtime.rs @@ -1,7 +1,7 @@ #[cfg(feature = "runtime")] use crate::{ - FarmsClient, ListingsClient, OrdersClient, RadrootsSdkError, SdkRelayTargetSet, - SdkRelayUrlPolicy, SyncClient, + DvmClient, FarmsClient, ListingsClient, MarketClient, RadrootsSdkError, SdkRelayTargetSet, + SdkRelayUrlPolicy, SyncClient, TradesClient, }; #[cfg(all(feature = "runtime", feature = "signer-adapters"))] use crate::{ @@ -390,7 +390,7 @@ pub struct RestoreReceipt { #[cfg(feature = "runtime")] #[derive(Clone)] -pub struct RadrootsSdkBuilder { +pub struct RadrootsClientBuilder { storage: RadrootsSdkStorageConfig, clock: RadrootsSdkClock, relay_urls: Vec<String>, @@ -401,7 +401,7 @@ pub struct RadrootsSdkBuilder { } #[cfg(feature = "runtime")] -impl Default for RadrootsSdkBuilder { +impl Default for RadrootsClientBuilder { fn default() -> Self { Self { storage: RadrootsSdkStorageConfig::Memory, @@ -416,7 +416,7 @@ impl Default for RadrootsSdkBuilder { } #[cfg(feature = "runtime")] -impl RadrootsSdkBuilder { +impl RadrootsClientBuilder { pub fn storage(mut self, storage: RadrootsSdkStorageConfig) -> Self { self.storage = storage; self @@ -458,11 +458,11 @@ impl RadrootsSdkBuilder { self } - pub async fn build(self) -> Result<RadrootsSdk, RadrootsSdkError> { + pub async fn build(self) -> Result<RadrootsClient, RadrootsSdkError> { let storage = open_storage(&self.storage).await?; let relay_urls = SdkRelayTargetSet::from_configured_relays(&self.relay_urls, self.relay_url_policy)?; - Ok(RadrootsSdk { + Ok(RadrootsClient { _event_store: storage.event_store, _outbox: storage.outbox, storage_paths: storage.paths, @@ -477,7 +477,7 @@ impl RadrootsSdkBuilder { #[cfg(feature = "runtime")] #[derive(Clone)] -pub struct RadrootsSdk { +pub struct RadrootsClient { pub(crate) _event_store: RadrootsEventStore, pub(crate) _outbox: RadrootsOutbox, storage_paths: Option<RadrootsSdkStoragePaths>, @@ -489,9 +489,9 @@ pub struct RadrootsSdk { } #[cfg(feature = "runtime")] -impl RadrootsSdk { - pub fn builder() -> RadrootsSdkBuilder { - RadrootsSdkBuilder::default() +impl RadrootsClient { + pub fn builder() -> RadrootsClientBuilder { + RadrootsClientBuilder::default() } pub fn farms(&self) -> FarmsClient<'_> { @@ -502,14 +502,22 @@ impl RadrootsSdk { ListingsClient::new(self) } - pub fn orders(&self) -> OrdersClient<'_> { - OrdersClient::new(self) + pub fn market(&self) -> MarketClient<'_> { + MarketClient::new(self) + } + + pub fn trades(&self) -> TradesClient<'_> { + TradesClient::new(self) } pub fn sync(&self) -> SyncClient<'_> { SyncClient::new(self) } + pub fn dvm(&self) -> DvmClient<'_> { + DvmClient::new(self) + } + pub fn now(&self) -> Result<RadrootsSdkTimestamp, RadrootsSdkError> { self.clock.now() } @@ -771,7 +779,7 @@ fn write_backup_receipt( } #[cfg(feature = "runtime")] -pub(crate) fn sdk_now_ms(sdk: &RadrootsSdk) -> Result<i64, RadrootsSdkError> { +pub(crate) fn sdk_now_ms(sdk: &RadrootsClient) -> Result<i64, RadrootsSdkError> { let seconds = sdk.now()?.unix_seconds(); let millis = seconds .checked_mul(1_000) diff --git a/crates/sdk/src/workflow_runtime.rs b/crates/sdk/src/workflow_runtime.rs @@ -1,7 +1,7 @@ #[cfg(feature = "signer-adapters")] use crate::RadrootsSdkSignRequest; use crate::{ - RadrootsSdk, RadrootsSdkError, SdkIdempotencyKey, SdkRelayTargetPolicy, SdkRelayTargetSet, + RadrootsClient, RadrootsSdkError, SdkIdempotencyKey, SdkRelayTargetPolicy, SdkRelayTargetSet, runtime::sdk_now_ms, }; use radroots_authority::{RadrootsActorContext, RadrootsEventSigner, sign_authorized_draft}; @@ -32,7 +32,7 @@ pub(crate) struct SdkWorkflowEnqueueReceipt { } pub(crate) async fn enqueue_signed_workflow( - sdk: &RadrootsSdk, + sdk: &RadrootsClient, request: SdkWorkflowEnqueueRequest<'_>, signer: &dyn RadrootsEventSigner, ) -> Result<SdkWorkflowEnqueueReceipt, RadrootsSdkError> { @@ -43,7 +43,7 @@ pub(crate) async fn enqueue_signed_workflow( #[cfg(feature = "signer-adapters")] pub(crate) async fn enqueue_configured_signed_workflow( - sdk: &RadrootsSdk, + sdk: &RadrootsClient, request: SdkWorkflowEnqueueRequest<'_>, ) -> Result<SdkWorkflowEnqueueReceipt, RadrootsSdkError> { let target_relays = resolved_target_relays(sdk, &request.target_relays)?; @@ -59,7 +59,7 @@ pub(crate) async fn enqueue_configured_signed_workflow( } async fn enqueue_signed_workflow_event( - sdk: &RadrootsSdk, + sdk: &RadrootsClient, request: SdkWorkflowEnqueueRequest<'_>, signed_event: RadrootsSignedNostrEvent, target_relays: SdkResolvedRelayTargets, @@ -137,7 +137,7 @@ struct SdkResolvedRelayTargets { } fn resolved_target_relays( - sdk: &RadrootsSdk, + sdk: &RadrootsClient, target_relays: &SdkRelayTargetPolicy, ) -> Result<SdkResolvedRelayTargets, RadrootsSdkError> { match target_relays { diff --git a/crates/sdk/tests/facade.rs b/crates/sdk/tests/facade.rs @@ -105,9 +105,9 @@ fn sample_listing() -> RadrootsListing { delivery_method: Some(RadrootsListingDeliveryMethod::Pickup), location: Some(RadrootsListingPublicLocation { primary: "North Farm".into(), - city: None, - region: None, - country: None, + city: Some("San Francisco".into()), + region: Some("CA".into()), + country: Some("US".into()), geohash: "9q8yy".into(), }), images: None, diff --git a/crates/sdk/tests/farms_runtime.rs b/crates/sdk/tests/farms_runtime.rs @@ -14,7 +14,7 @@ use radroots_outbox::{RadrootsOutbox, RadrootsOutboxEventState}; use radroots_relay_transport::RadrootsMockRelayPublishAdapter; use radroots_sdk::{ FARM_PUBLISH_OPERATION_KIND, FarmEnqueuePublishRequest, FarmPreparePublishRequest, - PushOutboxEventState, PushOutboxRelayOutcomeKind, PushOutboxRequest, RadrootsSdk, + PushOutboxEventState, PushOutboxRelayOutcomeKind, PushOutboxRequest, RadrootsClient, RadrootsSdkError, RadrootsSdkPartialLocalMutationFailure, RadrootsSdkRecoveryAction, RadrootsSdkTimestamp, SdkIdempotencyKey, SdkMutationState, SdkRelayTargetPolicy, SdkRelayTargetSet, SdkRelayUrlPolicy, @@ -111,13 +111,13 @@ fn farm(d_tag: &str, name: &str) -> RadrootsFarm { } } -async fn directory_sdk() -> (tempfile::TempDir, RadrootsSdk) { +async fn directory_sdk() -> (tempfile::TempDir, RadrootsClient) { directory_sdk_with_relays(&[RELAY]).await } -async fn directory_sdk_with_relays(relays: &[&str]) -> (tempfile::TempDir, RadrootsSdk) { +async fn directory_sdk_with_relays(relays: &[&str]) -> (tempfile::TempDir, RadrootsClient) { let tempdir = tempfile::tempdir().expect("tempdir"); - let mut builder = RadrootsSdk::builder() + let mut builder = RadrootsClient::builder() .directory_storage(tempdir.path().join("sdk")) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)); for relay in relays { diff --git a/crates/sdk/tests/listings_runtime.rs b/crates/sdk/tests/listings_runtime.rs @@ -19,7 +19,7 @@ use radroots_events::{ use radroots_outbox::{RadrootsOutbox, RadrootsOutboxEventState}; use radroots_sdk::{ LISTING_PUBLISH_OPERATION_KIND, ListingEnqueuePublishRequest, ListingPreparePublishRequest, - RadrootsSdk, RadrootsSdkError, RadrootsSdkPartialLocalMutationFailure, + RadrootsClient, RadrootsSdkError, RadrootsSdkPartialLocalMutationFailure, RadrootsSdkRecoveryAction, RadrootsSdkTimestamp, SdkIdempotencyKey, SdkMutationState, SdkRelayTargetPolicy, SdkRelayTargetSet, SdkRelayUrlPolicy, }; @@ -162,13 +162,13 @@ fn listing(d_tag: &str, title: &str) -> RadrootsListing { } } -async fn directory_sdk() -> (tempfile::TempDir, RadrootsSdk) { +async fn directory_sdk() -> (tempfile::TempDir, RadrootsClient) { directory_sdk_with_relays(&[RELAY]).await } -async fn directory_sdk_with_relays(relays: &[&str]) -> (tempfile::TempDir, RadrootsSdk) { +async fn directory_sdk_with_relays(relays: &[&str]) -> (tempfile::TempDir, RadrootsClient) { let tempdir = tempfile::tempdir().expect("tempdir"); - let mut builder = RadrootsSdk::builder() + let mut builder = RadrootsClient::builder() .directory_storage(tempdir.path().join("sdk")) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)); for relay in relays { diff --git a/crates/sdk/tests/orders_runtime.rs b/crates/sdk/tests/orders_runtime.rs @@ -42,7 +42,7 @@ use radroots_sdk::{ OrderRevisionProposalEnqueueRequest, OrderRevisionProposalPrepareRequest, OrderStatusKind, OrderStatusNextActionKind, OrderStatusRequest, OrderSubmitEnqueueRequest, OrderSubmitPrepareRequest, OrderWorkflowKind, PushOutboxEventState, PushOutboxRelayOutcomeKind, - PushOutboxRequest, RadrootsSdk, RadrootsSdkError, RadrootsSdkPartialLocalMutationFailure, + PushOutboxRequest, RadrootsClient, RadrootsSdkError, RadrootsSdkPartialLocalMutationFailure, RadrootsSdkRecoveryAction, RadrootsSdkTimestamp, SdkIdempotencyKey, SdkMutationState, SdkOrderStatusIssue, SdkOrderStatusIssueKind, SdkOrderStatusSource, SdkRelayTargetPolicy, SdkRelayTargetSet, SdkRelayUrlPolicy, @@ -371,9 +371,9 @@ impl RadrootsEventSigner for FixtureSigner { } } -async fn directory_sdk_and_store() -> (tempfile::TempDir, RadrootsSdk, RadrootsEventStore) { +async fn directory_sdk_and_store() -> (tempfile::TempDir, RadrootsClient, RadrootsEventStore) { let tempdir = tempfile::tempdir().expect("tempdir"); - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .directory_storage(tempdir.path().join("sdk")) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)) .build() @@ -513,7 +513,7 @@ async fn order_submit_prepare_is_side_effect_free() { order_request("order-submit-prepare"), ); - let prepared = sdk.orders().prepare_submit(request).expect("prepared"); + let prepared = sdk.trades().prepare_submit(request).expect("prepared"); assert_eq!(prepared.order_id.as_str(), "order-submit-prepare"); assert_eq!(prepared.listing_addr, listing_address()); @@ -566,7 +566,7 @@ async fn order_submit_prepare_rejects_missing_listing_evidence() { ); let error = sdk - .orders() + .trades() .prepare_submit(request) .expect_err("missing listing evidence"); @@ -578,7 +578,7 @@ async fn order_submit_prepare_rejects_invalid_actor_or_payload() { let (_tempdir, sdk, _store) = directory_sdk_and_store().await; let non_buyer = sdk - .orders() + .trades() .prepare_submit(OrderSubmitPrepareRequest::new( non_buyer_actor(), listing_event_ptr(), @@ -591,7 +591,7 @@ async fn order_submit_prepare_rejects_invalid_actor_or_payload() { )); let wrong_actor = sdk - .orders() + .trades() .prepare_submit(OrderSubmitPrepareRequest::new( other_buyer_actor(), listing_event_ptr(), @@ -606,7 +606,7 @@ async fn order_submit_prepare_rejects_invalid_actor_or_payload() { let mut seller_mismatch = order_request("order-submit-seller-mismatch"); seller_mismatch.seller_pubkey = OTHER_PUBLIC_KEY_HEX.parse().expect("seller pubkey"); let seller_error = sdk - .orders() + .trades() .prepare_submit(OrderSubmitPrepareRequest::new( buyer_actor(), listing_event_ptr(), @@ -621,7 +621,7 @@ async fn order_submit_prepare_rejects_invalid_actor_or_payload() { let mut empty_items = order_request("order-submit-empty-items"); empty_items.items.clear(); let empty_items_error = sdk - .orders() + .trades() .prepare_submit(OrderSubmitPrepareRequest::new( buyer_actor(), listing_event_ptr(), @@ -636,7 +636,7 @@ async fn order_submit_prepare_rejects_invalid_actor_or_payload() { let mut empty_economics = order_request("order-submit-empty-economics"); empty_economics.economics.items.clear(); let empty_economics_error = sdk - .orders() + .trades() .prepare_submit(OrderSubmitPrepareRequest::new( buyer_actor(), listing_event_ptr(), @@ -654,7 +654,7 @@ async fn order_submit_enqueue_stores_event_queues_outbox_and_status_sees_request let (_tempdir, sdk, store) = directory_sdk_and_store().await; let order = order_request("order-submit-enqueue"); let prepared = sdk - .orders() + .trades() .prepare_submit(OrderSubmitPrepareRequest::new( buyer_actor(), listing_event_ptr(), @@ -684,7 +684,7 @@ async fn order_submit_enqueue_stores_event_queues_outbox_and_status_sees_request .expect("idempotency key"); let receipt = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer(request, &FixtureSigner::new(BUYER_SECRET_KEY_HEX)) .await .expect("enqueue"); @@ -770,7 +770,7 @@ async fn order_submit_enqueue_stores_event_queues_outbox_and_status_sees_request assert!(outbox_event.signed_event.is_some()); let status = sdk - .orders() + .trades() .status(status_request("order-submit-enqueue")) .await .expect("status"); @@ -799,7 +799,7 @@ async fn order_submit_enqueue_returns_sanitized_signer_errors_before_mutation() .expect("target relays"); let error = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer(request, &FixtureSigner::new(SELLER_SECRET_KEY_HEX)) .await .expect_err("signer error"); @@ -855,12 +855,12 @@ async fn order_submit_enqueue_derives_order_independent_idempotency_key() { ); let first_receipt = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer(first, &FixtureSigner::new(BUYER_SECRET_KEY_HEX)) .await .expect("first enqueue"); let second_receipt = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer(second, &FixtureSigner::new(BUYER_SECRET_KEY_HEX)) .await .expect("second enqueue"); @@ -927,7 +927,7 @@ async fn order_submit_enqueue_pushes_queued_event_with_mock_relay_sync() { .try_with_target_relays([RELAY], SdkRelayUrlPolicy::Public) .expect("target relays"); let enqueue_receipt = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer( enqueue_request, &FixtureSigner::new(BUYER_SECRET_KEY_HEX), @@ -989,7 +989,7 @@ async fn order_submit_enqueue_reports_partial_local_mutation_after_outbox_confli .expect("first target relays") .try_with_idempotency_key("order-submit-conflict-idempotency") .expect("first idempotency key"); - sdk.orders() + sdk.trades() .enqueue_submit_with_explicit_signer(first, &FixtureSigner::new(BUYER_SECRET_KEY_HEX)) .await .expect("first enqueue"); @@ -1005,7 +1005,7 @@ async fn order_submit_enqueue_reports_partial_local_mutation_after_outbox_confli .try_with_idempotency_key("order-submit-conflict-idempotency") .expect("second idempotency key"); let error = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer(second, &FixtureSigner::new(BUYER_SECRET_KEY_HEX)) .await .expect_err("partial"); @@ -1131,7 +1131,7 @@ async fn order_submit_runtime_dtos_serialize_deterministically() { ); let receipt = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer( enqueue_request, &FixtureSigner::new(BUYER_SECRET_KEY_HEX), @@ -1306,7 +1306,7 @@ fn order_event_ptr(event_id: &RadrootsEventId) -> RadrootsNostrEventPtr { } } -async fn outbox_operation_kind(sdk: &RadrootsSdk, operation_id: i64) -> String { +async fn outbox_operation_kind(sdk: &RadrootsClient, operation_id: i64) -> String { let paths = sdk.storage_paths().expect("paths"); let outbox = RadrootsOutbox::open_file(&paths.outbox_path) .await @@ -1354,7 +1354,7 @@ async fn order_request_evidence_ingest_stores_request_and_enables_decision_enque .with_observed_at(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_039)); let ingest_receipt = sdk - .orders() + .trades() .ingest_request_evidence(ingest_request) .await .expect("ingest request evidence"); @@ -1369,7 +1369,7 @@ async fn order_request_evidence_ingest_stores_request_and_enables_decision_enque let actor = seller_actor(); let plan = sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( actor.clone(), request_event_ptr(&request_event), @@ -1377,7 +1377,7 @@ async fn order_request_evidence_ingest_stores_request_and_enables_decision_enque )) .expect("prepare decision"); let receipt = sdk - .orders() + .trades() .enqueue_prepared_decision_with_explicit_signer( &actor, plan, @@ -1391,7 +1391,7 @@ async fn order_request_evidence_ingest_stores_request_and_enables_decision_enque assert_eq!(receipt.local_event_seq, 2); let duplicate_receipt = sdk - .orders() + .trades() .ingest_request_evidence(OrderRequestEvidenceIngestRequest::new( request_event.clone(), )) @@ -1418,7 +1418,7 @@ async fn order_evidence_ingest_stores_lifecycle_evidence_for_projection() { signed_order_decision_event("order-evidence-ingest", &request_event_id, 40); let request_receipt = sdk - .orders() + .trades() .ingest_evidence(OrderEvidenceIngestRequest::new(request_event.clone())) .await .expect("request evidence"); @@ -1428,7 +1428,7 @@ async fn order_evidence_ingest_stores_lifecycle_evidence_for_projection() { assert!(request_receipt.inserted); let decision_receipt = sdk - .orders() + .trades() .ingest_evidence(OrderEvidenceIngestRequest::new(decision_event.clone())) .await .expect("decision evidence"); @@ -1438,7 +1438,7 @@ async fn order_evidence_ingest_stores_lifecycle_evidence_for_projection() { assert!(decision_receipt.inserted); let duplicate_receipt = sdk - .orders() + .trades() .ingest_evidence(OrderEvidenceIngestRequest::new(decision_event)) .await .expect("duplicate decision evidence"); @@ -1454,11 +1454,11 @@ async fn order_evidence_ingest_stores_lifecycle_evidence_for_projection() { ); let status = sdk - .orders() + .trades() .status(status_request("order-evidence-ingest")) .await .expect("status"); - assert_eq!(status.status, OrderStatusKind::Accepted); + assert_eq!(status.status, OrderStatusKind::AgreedPendingRhi); assert_eq!(status.event_count, 2); assert_eq!( status @@ -1473,7 +1473,7 @@ async fn order_evidence_ingest_stores_lifecycle_evidence_for_projection() { async fn order_evidence_ingest_rejects_non_order_events() { let (_tempdir, sdk, store) = directory_sdk_and_store().await; let error = sdk - .orders() + .trades() .ingest_evidence(OrderEvidenceIngestRequest::new(signed_non_order_event(41))) .await .expect_err("non order event"); @@ -1496,7 +1496,7 @@ async fn order_request_evidence_ingest_rejects_non_request_events() { let decision_event = signed_order_decision_event("non-request-root", &root_event_id, 40); let error = sdk - .orders() + .trades() .ingest_request_evidence(OrderRequestEvidenceIngestRequest::new(decision_event)) .await .expect_err("non request event"); @@ -1527,7 +1527,7 @@ async fn order_decision_prepare_accept_and_decline_are_side_effect_free() { ); let accepted = sdk - .orders() + .trades() .prepare_decision(accepted_request) .expect("accepted plan"); @@ -1548,7 +1548,7 @@ async fn order_decision_prepare_accept_and_decline_are_side_effect_free() { reason: " out of stock ".to_owned(), }; let declined = sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( seller_actor(), request_event, @@ -1591,7 +1591,7 @@ async fn order_decision_prepare_rejects_invalid_actor_evidence_and_payload() { }; let non_seller = sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( non_seller_actor(), request_event.clone(), @@ -1604,7 +1604,7 @@ async fn order_decision_prepare_rejects_invalid_actor_evidence_and_payload() { )); let wrong_actor = sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( other_seller_actor(), request_event.clone(), @@ -1617,7 +1617,7 @@ async fn order_decision_prepare_rejects_invalid_actor_evidence_and_payload() { )); let invalid_evidence = sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( seller_actor(), RadrootsNostrEventPtr { @@ -1637,7 +1637,7 @@ async fn order_decision_prepare_rejects_invalid_actor_evidence_and_payload() { inventory_commitments: Vec::new(), }; let commitment_error = sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( seller_actor(), request_event.clone(), @@ -1654,7 +1654,7 @@ async fn order_decision_prepare_rejects_invalid_actor_evidence_and_payload() { reason: " ".to_owned(), }; let reason_error = sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( seller_actor(), request_event, @@ -1763,7 +1763,7 @@ async fn order_decision_runtime_dtos_serialize_deterministically() { ); let receipt = sdk - .orders() + .trades() .enqueue_decision_with_explicit_signer( enqueue_request, &FixtureSigner::new(SELLER_SECRET_KEY_HEX), @@ -2096,7 +2096,7 @@ async fn order_decision_enqueue_accept_stores_event_queues_outbox_and_updates_st .expect("idempotency"); let receipt = sdk - .orders() + .trades() .enqueue_decision_with_explicit_signer(request, &FixtureSigner::new(SELLER_SECRET_KEY_HEX)) .await .expect("enqueue"); @@ -2144,12 +2144,12 @@ async fn order_decision_enqueue_accept_stores_event_queues_outbox_and_updates_st assert!(outbox_event.signed_event.is_some()); let status = sdk - .orders() + .trades() .status(status_request("order-decision-accept")) .await .expect("status"); assert!(status.found); - assert_eq!(status.status, OrderStatusKind::Accepted); + assert_eq!(status.status, OrderStatusKind::AgreedPendingRhi); assert_eq!(status.event_count, 2); assert_eq!( status @@ -2198,14 +2198,14 @@ async fn order_decision_enqueue_decline_stores_event_and_status_sees_declined() .expect("target relays"); let receipt = sdk - .orders() + .trades() .enqueue_decision_with_explicit_signer(request, &FixtureSigner::new(SELLER_SECRET_KEY_HEX)) .await .expect("enqueue"); assert_eq!(receipt.state, SdkMutationState::StoredAndQueued); let status = sdk - .orders() + .trades() .status(status_request("order-decision-decline")) .await .expect("status"); @@ -2239,7 +2239,7 @@ async fn order_decision_enqueue_rejects_missing_request_evidence_before_mutation .expect("target relays"); let error = sdk - .orders() + .trades() .enqueue_decision_with_explicit_signer(request, &FixtureSigner::new(SELLER_SECRET_KEY_HEX)) .await .expect_err("missing request evidence"); @@ -2284,7 +2284,7 @@ async fn order_decision_enqueue_returns_sanitized_signer_errors_before_decision_ .expect("target relays"); let error = sdk - .orders() + .trades() .enqueue_decision_with_explicit_signer(request, &FixtureSigner::new(BUYER_SECRET_KEY_HEX)) .await .expect_err("signer error"); @@ -2336,7 +2336,7 @@ async fn order_decision_enqueue_rejects_existing_decision_state_before_mutation( .expect("target relays"); let error = sdk - .orders() + .trades() .enqueue_decision_with_explicit_signer(request, &FixtureSigner::new(SELLER_SECRET_KEY_HEX)) .await .expect_err("existing decision"); @@ -2351,11 +2351,11 @@ async fn order_decision_enqueue_rejects_existing_decision_state_before_mutation( 2 ); let status = sdk - .orders() + .trades() .status(status_request("order-decision-conflict")) .await .expect("status"); - assert_eq!(status.status, OrderStatusKind::Accepted); + assert_eq!(status.status, OrderStatusKind::AgreedPendingRhi); assert_eq!( status .decision_event_id @@ -2366,7 +2366,7 @@ async fn order_decision_enqueue_rejects_existing_decision_state_before_mutation( } #[tokio::test] -async fn order_revision_lifecycle_accepts_proposal_and_finalizes_agreement() { +async fn order_revision_lifecycle_accepts_proposal_and_waits_for_rhi() { let (_tempdir, sdk, store) = directory_sdk_and_store().await; let request_event = signed_order_request_event("order-lifecycle-agreement", 50); let request_event_id = RadrootsEventId::parse(request_event.id.as_str()).expect("request id"); @@ -2382,7 +2382,7 @@ async fn order_revision_lifecycle_accepts_proposal_and_finalizes_agreement() { ); let proposal_actor = seller_actor(); let proposal_plan = sdk - .orders() + .trades() .prepare_revision_proposal(OrderRevisionProposalPrepareRequest::new( proposal_actor.clone(), request_event_ptr(&request_event), @@ -2391,7 +2391,7 @@ async fn order_revision_lifecycle_accepts_proposal_and_finalizes_agreement() { )) .expect("prepare revision proposal"); let proposal_receipt = sdk - .orders() + .trades() .enqueue_prepared_revision_proposal_with_explicit_signer( &proposal_actor, proposal_plan, @@ -2431,7 +2431,7 @@ async fn order_revision_lifecycle_accepts_proposal_and_finalizes_agreement() { ); let revision_decision_actor = buyer_actor(); let revision_decision_plan = sdk - .orders() + .trades() .prepare_revision_decision(OrderRevisionDecisionPrepareRequest::new( revision_decision_actor.clone(), request_event_ptr(&request_event), @@ -2440,7 +2440,7 @@ async fn order_revision_lifecycle_accepts_proposal_and_finalizes_agreement() { )) .expect("prepare revision decision"); let revision_decision_receipt = sdk - .orders() + .trades() .enqueue_prepared_revision_decision_with_explicit_signer( &revision_decision_actor, revision_decision_plan, @@ -2466,11 +2466,11 @@ async fn order_revision_lifecycle_accepts_proposal_and_finalizes_agreement() { ); let status = sdk - .orders() + .trades() .status(status_request("order-lifecycle-agreement")) .await .expect("status"); - assert_eq!(status.status, OrderStatusKind::Accepted); + assert_eq!(status.status, OrderStatusKind::AgreedPendingRhi); assert_eq!(status.event_count, 3); assert_eq!( status @@ -2492,8 +2492,11 @@ async fn order_revision_lifecycle_accepts_proposal_and_finalizes_agreement() { Some(SELLER_PUBLIC_KEY_HEX.to_owned()) ); assert_eq!(status.economics, Some(revision_economics())); - assert!(status.lifecycle_terminal); - assert_eq!(status.next_action, OrderStatusNextActionKind::Terminal); + assert!(!status.lifecycle_terminal); + assert_eq!( + status.next_action, + OrderStatusNextActionKind::AwaitRhiValidation + ); assert!(status.evidence.has_request); assert!(!status.evidence.has_decision); assert!(status.evidence.has_agreement); @@ -2522,7 +2525,7 @@ async fn order_revision_proposal_status_exposes_pending_and_blocks_follow_on_lif &request_event_id, ); let proposal_receipt = sdk - .orders() + .trades() .enqueue_revision_proposal_with_explicit_signer( OrderRevisionProposalEnqueueRequest::new( seller_actor(), @@ -2539,11 +2542,11 @@ async fn order_revision_proposal_status_exposes_pending_and_blocks_follow_on_lif .expect("enqueue revision proposal"); let status = sdk - .orders() + .trades() .status(status_request("order-lifecycle-pending-revision")) .await .expect("status"); - assert_eq!(status.status, OrderStatusKind::Requested); + assert_eq!(status.status, OrderStatusKind::RevisionProposed); assert_eq!(status.event_count, 2); assert!(status.agreement_event_id.is_none()); assert_eq!( @@ -2564,7 +2567,7 @@ async fn order_revision_proposal_status_exposes_pending_and_blocks_follow_on_lif assert!(!status.eligibility.can_cancel); let decision_error = sdk - .orders() + .trades() .enqueue_decision_with_explicit_signer( OrderDecisionEnqueueRequest::new( seller_actor(), @@ -2589,7 +2592,7 @@ async fn order_revision_proposal_status_exposes_pending_and_blocks_follow_on_lif &proposal_receipt.signed_event_id, ); let proposal_error = sdk - .orders() + .trades() .enqueue_revision_proposal_with_explicit_signer( OrderRevisionProposalEnqueueRequest::new( seller_actor(), @@ -2633,7 +2636,7 @@ async fn order_declined_revision_finalizes_declined_negotiation() { &request_event_id, ); let proposal_receipt = sdk - .orders() + .trades() .enqueue_revision_proposal_with_explicit_signer( OrderRevisionProposalEnqueueRequest::new( seller_actor(), @@ -2656,7 +2659,7 @@ async fn order_declined_revision_finalizes_declined_negotiation() { }, ); let declined_revision_receipt = sdk - .orders() + .trades() .enqueue_revision_decision_with_explicit_signer( OrderRevisionDecisionEnqueueRequest::new( buyer_actor(), @@ -2673,7 +2676,7 @@ async fn order_declined_revision_finalizes_declined_negotiation() { .expect("enqueue declined revision"); let status = sdk - .orders() + .trades() .status(status_request("order-lifecycle-declined-revision")) .await .expect("status"); @@ -2704,7 +2707,7 @@ async fn order_declined_revision_finalizes_declined_negotiation() { RadrootsOrderRevisionOutcome::Accepted, ); let second_decision_error = sdk - .orders() + .trades() .enqueue_revision_decision_with_explicit_signer( OrderRevisionDecisionEnqueueRequest::new( buyer_actor(), @@ -2744,7 +2747,7 @@ async fn order_cancel_lifecycle_enqueue_updates_status() { .expect("ingest request"); let cancellation_actor = buyer_actor(); let cancellation_plan = sdk - .orders() + .trades() .prepare_cancellation(OrderCancellationPrepareRequest::new( cancellation_actor.clone(), request_event_ptr(&request_event), @@ -2753,7 +2756,7 @@ async fn order_cancel_lifecycle_enqueue_updates_status() { )) .expect("prepare cancellation"); let cancellation = sdk - .orders() + .trades() .enqueue_prepared_cancellation_with_explicit_signer( &cancellation_actor, cancellation_plan, @@ -2783,7 +2786,7 @@ async fn order_cancel_lifecycle_enqueue_updates_status() { KIND_ORDER_CANCELLATION ); let replay = sdk - .orders() + .trades() .enqueue_cancellation_with_explicit_signer( OrderCancellationEnqueueRequest::new( buyer_actor(), @@ -2804,7 +2807,7 @@ async fn order_cancel_lifecycle_enqueue_updates_status() { assert_eq!(replay.signed_event_id, cancellation.signed_event_id); assert_eq!(replay.outbox_event_id, cancellation.outbox_event_id); let status = sdk - .orders() + .trades() .status(status_request("order-lifecycle-cancel")) .await .expect("status"); @@ -2832,7 +2835,7 @@ async fn order_lifecycle_enqueue_rejects_invalid_state_before_mutation() { let request_event = signed_order_request_event("order-lifecycle-invalid", 70); let request_event_id = RadrootsEventId::parse(request_event.id.as_str()).expect("request id"); let missing = sdk - .orders() + .trades() .enqueue_revision_proposal_with_explicit_signer( OrderRevisionProposalEnqueueRequest::new( seller_actor(), @@ -2866,7 +2869,7 @@ async fn order_lifecycle_enqueue_rejects_invalid_state_before_mutation() { .await .expect("ingest request"); let decision_receipt = sdk - .orders() + .trades() .enqueue_decision_with_explicit_signer( OrderDecisionEnqueueRequest::new( seller_actor(), @@ -2890,7 +2893,7 @@ async fn order_lifecycle_enqueue_rejects_invalid_state_before_mutation() { RadrootsOrderRevisionOutcome::Accepted, ); let revision_error = sdk - .orders() + .trades() .enqueue_revision_decision_with_explicit_signer( OrderRevisionDecisionEnqueueRequest::new( buyer_actor(), @@ -2911,7 +2914,7 @@ async fn order_lifecycle_enqueue_rejects_invalid_state_before_mutation() { )); let cancellation_error = sdk - .orders() + .trades() .enqueue_cancellation_with_explicit_signer( OrderCancellationEnqueueRequest::new( buyer_actor(), @@ -2947,7 +2950,7 @@ async fn order_status_returns_not_found_for_missing_local_order() { assert_eq!(request.limit, ORDER_STATUS_DEFAULT_LIMIT); - let receipt = sdk.orders().status(request).await.expect("status"); + let receipt = sdk.trades().status(request).await.expect("status"); assert!(!receipt.found); assert_eq!(receipt.order_id.as_str(), "order-1"); @@ -2977,12 +2980,12 @@ async fn order_status_rejects_invalid_limits_before_querying() { let (_tempdir, sdk, _store) = directory_sdk_and_store().await; let zero = sdk - .orders() + .trades() .status(status_request("order-1").with_limit(0)) .await .expect_err("zero limit"); let too_large = sdk - .orders() + .trades() .status(status_request("order-1").with_limit(ORDER_STATUS_MAX_LIMIT + 1)) .await .expect_err("too large"); @@ -3027,7 +3030,7 @@ async fn order_status_contract_dtos_serialize_deterministically() { }) ); - let receipt = sdk.orders().status(request).await.expect("status"); + let receipt = sdk.trades().status(request).await.expect("status"); let receipt_json = serde_json::to_value(&receipt).expect("receipt json"); assert_eq!(receipt_json["source"], "local_event_store"); @@ -3392,7 +3395,7 @@ async fn order_status_projects_local_request_and_decision_events() { } let receipt = sdk - .orders() + .trades() .status(status_request("order-1").with_limit(1_000)) .await .expect("status"); @@ -3410,7 +3413,7 @@ async fn order_status_projects_local_request_and_decision_events() { .collect::<Vec<_>>(), vec![request_event.id.as_str(), decision_event.id.as_str()] ); - assert_eq!(receipt.status, OrderStatusKind::Accepted); + assert_eq!(receipt.status, OrderStatusKind::AgreedPendingRhi); assert_eq!( receipt .request_event_id @@ -3440,8 +3443,11 @@ async fn order_status_projects_local_request_and_decision_events() { ); assert_eq!(receipt.economics, Some(economics())); assert!(receipt.issues.is_empty()); - assert!(receipt.lifecycle_terminal); - assert_eq!(receipt.next_action, OrderStatusNextActionKind::Terminal); + assert!(!receipt.lifecycle_terminal); + assert_eq!( + receipt.next_action, + OrderStatusNextActionKind::AwaitRhiValidation + ); assert_eq!(receipt.evidence.event_count, 2); assert!(receipt.evidence.has_request); assert!(receipt.evidence.has_decision); @@ -3469,7 +3475,7 @@ async fn order_status_reports_limited_local_results() { } let receipt = sdk - .orders() + .trades() .status(status_request("order-1").with_limit(1)) .await .expect("status"); @@ -3518,7 +3524,7 @@ async fn order_status_reports_typed_reducer_issues() { } let receipt = sdk - .orders() + .trades() .status(status_request("order-1")) .await .expect("status"); @@ -3571,7 +3577,7 @@ async fn order_status_maps_malformed_local_data_to_sanitized_error() { .expect("corrupt tags"); let error = sdk - .orders() + .trades() .status(status_request("order-1")) .await .expect_err("projection error"); diff --git a/crates/sdk/tests/runtime_foundation.rs b/crates/sdk/tests/runtime_foundation.rs @@ -1,30 +1,32 @@ #![cfg(feature = "runtime")] use radroots_sdk::{ - BackupRequest, IntegrityRequest, LISTING_PUBLISH_OPERATION_KIND, RadrootsSdk, RadrootsSdkClock, - RadrootsSdkError, RadrootsSdkErrorClass, RadrootsSdkRecoveryAction, RadrootsSdkStorageConfig, - RadrootsSdkTimestamp, RestoreRequest, SDK_IDEMPOTENCY_KEY_MAX_LEN, SDK_RELAY_TARGET_MAX_COUNT, - SdkBackupState, SdkBackupVerification, SdkEventStoreStorageStatus, SdkIdempotencyKey, - SdkOutboxStorageStatus, SdkRelayTargetPolicy, SdkRelayTargetSet, SdkRelayUrlPolicy, - SdkRestoreState, SdkSqliteStoreStatus, SdkStorageKind, StorageStatusReceipt, + BackupRequest, IntegrityRequest, LISTING_PUBLISH_OPERATION_KIND, RadrootsClient, + RadrootsSdkClock, RadrootsSdkError, RadrootsSdkErrorClass, RadrootsSdkRecoveryAction, + RadrootsSdkStorageConfig, RadrootsSdkTimestamp, RestoreRequest, SDK_IDEMPOTENCY_KEY_MAX_LEN, + SDK_RELAY_TARGET_MAX_COUNT, SdkBackupState, SdkBackupVerification, SdkEventStoreStorageStatus, + SdkIdempotencyKey, SdkOutboxStorageStatus, SdkRelayTargetPolicy, SdkRelayTargetSet, + SdkRelayUrlPolicy, SdkRestoreState, SdkSqliteStoreStatus, SdkStorageKind, StorageStatusReceipt, StorageStatusRequest, }; use std::path::PathBuf; #[tokio::test] async fn sdk_builder_defaults_to_memory_storage_and_no_relays() { - let sdk = RadrootsSdk::builder().build().await.expect("sdk"); + let sdk = RadrootsClient::builder().build().await.expect("sdk"); assert!(sdk.relay_urls().is_empty()); assert!(sdk.storage_paths().is_none()); let _listings = sdk.listings(); - let _orders = sdk.orders(); + let _market = sdk.market(); + let _trades = sdk.trades(); let _sync = sdk.sync(); + let _dvm = sdk.dvm(); } #[tokio::test] async fn sdk_builder_validates_configured_relay_targets() { - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .relay_url(" wss://relay-b.example.com/ ") .relay_url("wss://relay-a.example.com") .relay_url("wss://relay-a.example.com") @@ -43,7 +45,7 @@ async fn sdk_builder_validates_configured_relay_targets() { #[tokio::test] async fn sdk_builder_rejects_ws_relay_without_localhost_policy() { - let result = RadrootsSdk::builder() + let result = RadrootsClient::builder() .relay_url("ws://127.0.0.1:8080") .build() .await; @@ -88,7 +90,7 @@ fn invalid_relay_url_errors_redact_userinfo() { #[tokio::test] async fn sdk_builder_allows_only_local_ws_targets_with_localhost_policy() { - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .relay_url_policy(SdkRelayUrlPolicy::Localhost) .relay_url("ws://localhost:8080") .relay_url("ws://127.0.0.1:8081") @@ -99,7 +101,7 @@ async fn sdk_builder_allows_only_local_ws_targets_with_localhost_policy() { assert_eq!(sdk.relay_urls().len(), 3); - let result = RadrootsSdk::builder() + let result = RadrootsClient::builder() .relay_url_policy(SdkRelayUrlPolicy::Localhost) .relay_url("ws://relay.example.com") .build() @@ -110,7 +112,7 @@ async fn sdk_builder_allows_only_local_ws_targets_with_localhost_policy() { Err(RadrootsSdkError::InvalidRelayUrl { .. }) )); - let result = RadrootsSdk::builder() + let result = RadrootsClient::builder() .relay_url_policy(SdkRelayUrlPolicy::Localhost) .relay_url("ws://192.168.1.10:8080") .build() @@ -125,7 +127,7 @@ async fn sdk_builder_allows_only_local_ws_targets_with_localhost_policy() { #[tokio::test] async fn sdk_directory_storage_creates_deterministic_sqlite_files() { let tempdir = tempfile::tempdir().expect("tempdir"); - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .storage(RadrootsSdkStorageConfig::Directory( tempdir.path().join("sdk-runtime"), )) @@ -151,7 +153,7 @@ async fn sdk_directory_storage_creates_deterministic_sqlite_files() { #[tokio::test] async fn sdk_memory_storage_status_and_integrity_report_canonical_stores() { - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)) .build() .await @@ -187,7 +189,7 @@ async fn sdk_memory_storage_status_and_integrity_report_canonical_stores() { #[tokio::test] async fn sdk_fixed_clock_is_used_by_runtime() { let timestamp = RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000); - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .clock(RadrootsSdkClock::Fixed(timestamp)) .build() .await @@ -211,7 +213,7 @@ async fn runtime_defaults_and_clock_overflow_paths_are_explicit() { > 0 ); - let overflow_sdk = RadrootsSdk::builder() + let overflow_sdk = RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(u64::MAX)) .build() .await @@ -225,7 +227,7 @@ async fn runtime_defaults_and_clock_overflow_paths_are_explicit() { )); let too_large_for_i64 = u64::try_from(i64::MAX).expect("i64 max") / 1_000 + 1; - let i64_overflow_sdk = RadrootsSdk::builder() + let i64_overflow_sdk = RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(too_large_for_i64)) .build() .await @@ -245,7 +247,7 @@ async fn runtime_directory_storage_rejects_file_path() { let file_path = tempdir.path().join("sdk-file"); std::fs::write(&file_path, b"not a directory").expect("file"); - let result = RadrootsSdk::builder() + let result = RadrootsClient::builder() .directory_storage(file_path.clone()) .build() .await; @@ -794,12 +796,12 @@ fn sdk_examples_stay_on_product_api_boundary() { } let listing_prepare = include_str!("../examples/sdk_v1_listing_prepare.rs"); - assert!(listing_prepare.contains("RadrootsSdk::builder()")); + assert!(listing_prepare.contains("RadrootsClient::builder()")); assert!(listing_prepare.contains("ListingPreparePublishRequest")); assert!(listing_prepare.contains("prepare_publish")); let local_enqueue = include_str!("../examples/sdk_v1_local_enqueue_and_mock_sync.rs"); - assert!(local_enqueue.contains("RadrootsSdk::builder()")); + assert!(local_enqueue.contains("RadrootsClient::builder()")); assert!(local_enqueue.contains("ListingPreparePublishRequest")); assert!(local_enqueue.contains("SdkRelayTargetPolicy")); assert!(local_enqueue.contains("SdkRelayTargetSet")); diff --git a/crates/sdk/tests/source_boundary.rs b/crates/sdk/tests/source_boundary.rs @@ -182,7 +182,7 @@ fn sdk_sources_do_not_import_app_or_cli_concepts() { let source = read_source(path.as_path()); for concept in FORBIDDEN_SDK_SOURCE_CONCEPTS { assert!( - !source.contains(concept.pattern), + !contains_forbidden_concept(&source, concept.pattern), "{} contains forbidden SDK source concept `{}`: {}", path.display(), concept.pattern, @@ -292,21 +292,21 @@ fn orders_client_surface_is_inventory_guarded() { ); assert!( - source.contains("impl<'sdk> OrdersClient<'sdk> {"), - "src/orders_runtime.rs must own OrdersClient runtime methods" + source.contains("impl<'sdk> TradesClient<'sdk> {"), + "src/orders_runtime.rs must own TradesClient runtime methods" ); for method in REQUIRED_ORDERS_CLIENT_METHODS { assert!( source.contains(method), - "OrdersClient must expose inventory-guarded method `{method}`" + "TradesClient must expose inventory-guarded method `{method}`" ); } for method in REQUIRED_ORDERS_CLIENT_ADVANCED_SIGNER_METHODS { assert!( source.contains(method), - "OrdersClient must expose explicit-signer advanced method `{method}`" + "TradesClient must expose explicit-signer advanced method `{method}`" ); } } @@ -329,7 +329,7 @@ fn product_clients_remain_thin_sdk_handles() { "src/lib.rs must keep product_clients internal" ); assert!( - lib_source.contains("pub use crate::product_clients::{FarmsClient, ListingsClient, OrdersClient, SyncClient};"), + lib_source.contains("pub use crate::product_clients::{"), "src/lib.rs must explicitly export product client handles" ); assert!( @@ -338,13 +338,19 @@ fn product_clients_remain_thin_sdk_handles() { ); for client in [ + "DvmClient", "FarmsClient", "ListingsClient", - "OrdersClient", + "MarketClient", "SyncClient", + "TradesClient", ] { assert!( - clients_source.contains(format!("pub struct {client}<'sdk>").as_str()), + lib_source.contains(client), + "src/lib.rs must export product client handle `{client}`" + ); + assert!( + clients_source.contains(format!("pub struct {client}<'client>").as_str()), "product_clients.rs must define thin handle `{client}`" ); } @@ -436,6 +442,19 @@ fn read_source(path: &Path) -> String { .unwrap_or_else(|error| panic!("failed to read source {}: {error}", path.display())) } +fn contains_forbidden_concept(source: &str, pattern: &str) -> bool { + source.match_indices(pattern).any(|(index, _)| { + let before = source[..index].chars().next_back(); + let after = source[index + pattern.len()..].chars().next(); + before.is_none_or(|character| !is_rust_identifier_character(character)) + && after.is_none_or(|character| !is_rust_identifier_character(character)) + }) +} + +fn is_rust_identifier_character(character: char) -> bool { + character == '_' || character.is_ascii_alphanumeric() +} + fn rust_source_files(root: &Path) -> Vec<PathBuf> { let mut paths = Vec::new(); collect_rust_source_files(root, &mut paths); diff --git a/crates/sdk/tests/sync_runtime.rs b/crates/sdk/tests/sync_runtime.rs @@ -26,7 +26,7 @@ use radroots_sdk::{ ListingPreparePublishRequest, PUSH_OUTBOX_DEFAULT_CLAIM_TTL_MS, PUSH_OUTBOX_DEFAULT_LIMIT, PUSH_OUTBOX_DEFAULT_NEXT_ATTEMPT_DELAY_MS, PUSH_OUTBOX_MAX_LIMIT, PushOutboxEventReceipt, PushOutboxEventState, PushOutboxReceipt, PushOutboxRelayOutcomeKind, PushOutboxRelayReceipt, - PushOutboxRequest, RadrootsSdk, RadrootsSdkError, RadrootsSdkTimestamp, RestoreRequest, + PushOutboxRequest, RadrootsClient, RadrootsSdkError, RadrootsSdkTimestamp, RestoreRequest, SdkBackupManifestKind, SdkRelayAuthPolicy, SdkRelayTargetPolicy, SdkRelayUrlPolicy, SdkRestoreState, StorageStatusRequest, SyncStatusRequest, SyncStatusSource, }; @@ -406,9 +406,9 @@ fn listing(d_tag: &str, title: &str) -> RadrootsListing { } } -async fn directory_sdk(relays: &[&str]) -> (tempfile::TempDir, RadrootsSdk) { +async fn directory_sdk(relays: &[&str]) -> (tempfile::TempDir, RadrootsClient) { let tempdir = tempfile::tempdir().expect("tempdir"); - let mut builder = RadrootsSdk::builder() + let mut builder = RadrootsClient::builder() .directory_storage(tempdir.path().join("sdk")) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)); for relay in relays { @@ -418,9 +418,9 @@ async fn directory_sdk(relays: &[&str]) -> (tempfile::TempDir, RadrootsSdk) { (tempdir, sdk) } -async fn system_clock_directory_sdk(relays: &[&str]) -> (tempfile::TempDir, RadrootsSdk) { +async fn system_clock_directory_sdk(relays: &[&str]) -> (tempfile::TempDir, RadrootsClient) { let tempdir = tempfile::tempdir().expect("tempdir"); - let mut builder = RadrootsSdk::builder().directory_storage(tempdir.path().join("sdk")); + let mut builder = RadrootsClient::builder().directory_storage(tempdir.path().join("sdk")); for relay in relays { builder = builder.relay_url(*relay); } @@ -428,11 +428,11 @@ async fn system_clock_directory_sdk(relays: &[&str]) -> (tempfile::TempDir, Radr (tempdir, sdk) } -async fn enqueue_listing(sdk: &RadrootsSdk, d_tag: &str, title: &str, relays: &[&str]) -> i64 { +async fn enqueue_listing(sdk: &RadrootsClient, d_tag: &str, title: &str, relays: &[&str]) -> i64 { enqueue_listing_with_policy(sdk, d_tag, title, relays, SdkRelayUrlPolicy::Public).await } -async fn backup_source(sdk: &RadrootsSdk, root: &Path, name: &str) -> PathBuf { +async fn backup_source(sdk: &RadrootsClient, root: &Path, name: &str) -> PathBuf { let source = root.join(name); sdk.backup(BackupRequest::new(source.clone())) .await @@ -454,7 +454,7 @@ fn rewrite_backup_manifest(source: &Path, mutate: impl FnOnce(&mut serde_json::V } async fn enqueue_listing_with_policy( - sdk: &RadrootsSdk, + sdk: &RadrootsClient, d_tag: &str, title: &str, relays: &[&str], @@ -641,7 +641,7 @@ async fn sdk_directory_backup_creates_verified_canonical_store_copy() { assert!(backup.manifest.backup_verification.event_store_ok); assert!(backup.manifest.backup_verification.outbox_ok); - let restore_archive = RadrootsSdk::inspect_restore_archive(backup_destination.clone()) + let restore_archive = RadrootsClient::inspect_restore_archive(backup_destination.clone()) .await .expect("restore archive"); assert_eq!(restore_archive.manifest, backup.manifest); @@ -770,7 +770,7 @@ async fn sdk_restore_archive_rejects_missing_manifest() { let source = tempdir.path().join("backup"); std::fs::create_dir(&source).expect("source"); - let error = RadrootsSdk::inspect_restore_archive(source) + let error = RadrootsClient::inspect_restore_archive(source) .await .expect_err("missing manifest"); assert!(matches!(error, RadrootsSdkError::Io { .. })); @@ -783,7 +783,7 @@ async fn sdk_restore_archive_rejects_malformed_manifest() { std::fs::create_dir(&source).expect("source"); std::fs::write(source.join("manifest.json"), b"{not json").expect("manifest"); - let error = RadrootsSdk::inspect_restore_archive(source) + let error = RadrootsClient::inspect_restore_archive(source) .await .expect_err("malformed manifest"); assert!(matches!(error, RadrootsSdkError::InvalidRequest { .. })); @@ -793,7 +793,7 @@ async fn sdk_restore_archive_rejects_malformed_manifest() { async fn runtime_restore_rejects_empty_missing_file_and_manifest_sources() { let tempdir = tempfile::tempdir().expect("tempdir"); - let empty_source = RadrootsSdk::inspect_restore_archive(PathBuf::new()) + let empty_source = RadrootsClient::inspect_restore_archive(PathBuf::new()) .await .expect_err("empty source"); assert!(matches!( @@ -801,14 +801,14 @@ async fn runtime_restore_rejects_empty_missing_file_and_manifest_sources() { RadrootsSdkError::InvalidRequest { .. } )); - let missing_source = RadrootsSdk::inspect_restore_archive(tempdir.path().join("missing")) + let missing_source = RadrootsClient::inspect_restore_archive(tempdir.path().join("missing")) .await .expect_err("missing source"); assert!(matches!(missing_source, RadrootsSdkError::Io { .. })); let file_source = tempdir.path().join("backup-file"); std::fs::write(&file_source, b"not a directory").expect("source file"); - let file_error = RadrootsSdk::inspect_restore_archive(file_source) + let file_error = RadrootsClient::inspect_restore_archive(file_source) .await .expect_err("file source"); assert!(matches!( @@ -819,7 +819,7 @@ async fn runtime_restore_rejects_empty_missing_file_and_manifest_sources() { let manifest_dir_source = tempdir.path().join("manifest-dir-source"); std::fs::create_dir(&manifest_dir_source).expect("manifest source"); std::fs::create_dir(manifest_dir_source.join("manifest.json")).expect("manifest dir"); - let manifest_dir_error = RadrootsSdk::inspect_restore_archive(manifest_dir_source) + let manifest_dir_error = RadrootsClient::inspect_restore_archive(manifest_dir_source) .await .expect_err("manifest dir"); assert!(matches!( @@ -836,7 +836,7 @@ async fn runtime_restore_rejects_symlink_source_and_manifest() { let source_link = tempdir.path().join("backup-source-link"); std::os::unix::fs::symlink(&source, &source_link).expect("source symlink"); - let source_error = RadrootsSdk::inspect_restore_archive(source_link) + let source_error = RadrootsClient::inspect_restore_archive(source_link) .await .expect_err("source symlink"); assert!(matches!( @@ -850,7 +850,7 @@ async fn runtime_restore_rejects_symlink_source_and_manifest() { std::fs::copy(&manifest_path, &manifest_copy).expect("manifest copy"); std::fs::remove_file(&manifest_path).expect("remove manifest"); std::os::unix::fs::symlink(&manifest_copy, &manifest_path).expect("manifest symlink"); - let manifest_error = RadrootsSdk::inspect_restore_archive(manifest_link_source) + let manifest_error = RadrootsClient::inspect_restore_archive(manifest_link_source) .await .expect_err("manifest symlink"); assert!(matches!( @@ -867,7 +867,7 @@ async fn runtime_restore_rejects_manifest_contract_edges() { rewrite_backup_manifest(&version_source, |manifest| { manifest["manifest_version"] = serde_json::json!(2); }); - let version_error = RadrootsSdk::inspect_restore_archive(version_source) + let version_error = RadrootsClient::inspect_restore_archive(version_source) .await .expect_err("unsupported manifest version"); assert!(matches!( @@ -879,7 +879,7 @@ async fn runtime_restore_rejects_manifest_contract_edges() { rewrite_backup_manifest(&empty_path_source, |manifest| { manifest["backup_paths"]["event_store_path"] = serde_json::json!(""); }); - let empty_path_error = RadrootsSdk::inspect_restore_archive(empty_path_source) + let empty_path_error = RadrootsClient::inspect_restore_archive(empty_path_source) .await .expect_err("empty archive path"); assert!(matches!( @@ -891,7 +891,7 @@ async fn runtime_restore_rejects_manifest_contract_edges() { rewrite_backup_manifest(&mismatch_source, |manifest| { manifest["backup_verification"]["event_store_events"] = serde_json::json!(999); }); - let mismatch_error = RadrootsSdk::inspect_restore_archive(mismatch_source) + let mismatch_error = RadrootsClient::inspect_restore_archive(mismatch_source) .await .expect_err("verification mismatch"); assert!(matches!( @@ -920,7 +920,7 @@ async fn sdk_restore_archive_rejects_traversal_backup_paths() { ) .expect("write manifest"); - let error = RadrootsSdk::inspect_restore_archive(source) + let error = RadrootsClient::inspect_restore_archive(source) .await .expect_err("traversal path"); assert!(matches!(error, RadrootsSdkError::InvalidRequest { .. })); @@ -936,7 +936,7 @@ async fn sdk_restore_archive_rejects_corrupt_store() { .expect("backup"); std::fs::write(source.join("event_store.sqlite"), b"not sqlite").expect("corrupt store"); - let error = RadrootsSdk::inspect_restore_archive(source) + let error = RadrootsClient::inspect_restore_archive(source) .await .expect_err("corrupt store"); assert!(matches!( @@ -959,7 +959,7 @@ async fn sdk_restore_archive_rejects_symlink_store_member() { std::fs::remove_file(&event_store_path).expect("remove backup event store"); std::os::unix::fs::symlink(target, &event_store_path).expect("symlink"); - let error = RadrootsSdk::inspect_restore_archive(source) + let error = RadrootsClient::inspect_restore_archive(source) .await .expect_err("symlink member"); assert!(matches!(error, RadrootsSdkError::InvalidRequest { .. })); @@ -970,7 +970,7 @@ async fn runtime_restore_rejects_missing_destination_and_empty_destination() { let (tempdir, sdk) = directory_sdk(&[RELAY_A]).await; let source = backup_source(&sdk, tempdir.path(), "backup-destination-required").await; - let missing_destination = RadrootsSdk::restore(RestoreRequest::new(source.clone())) + let missing_destination = RadrootsClient::restore(RestoreRequest::new(source.clone())) .await .expect_err("missing destination"); assert!(matches!( @@ -978,7 +978,7 @@ async fn runtime_restore_rejects_missing_destination_and_empty_destination() { RadrootsSdkError::InvalidRequest { .. } )); - let empty_destination = RadrootsSdk::restore( + let empty_destination = RadrootsClient::restore( RestoreRequest::new(source) .with_destination(PathBuf::new()) .dry_run(), @@ -1001,7 +1001,7 @@ async fn sdk_restore_dry_run_validates_destination_without_writing() { .await .expect("backup"); - let receipt = RadrootsSdk::restore( + let receipt = RadrootsClient::restore( RestoreRequest::new(source.clone()) .with_destination(destination.clone()) .dry_run(), @@ -1035,7 +1035,7 @@ async fn sdk_restore_dry_run_rejects_existing_destination_without_overwrite() { std::fs::create_dir(&destination).expect("destination"); std::fs::write(destination.join("event_store.sqlite"), b"existing").expect("existing file"); - let error = RadrootsSdk::restore( + let error = RadrootsClient::restore( RestoreRequest::new(source) .with_destination(destination.clone()) .dry_run(), @@ -1059,7 +1059,7 @@ async fn sdk_restore_dry_run_overwrite_keeps_existing_destination_untouched() { std::fs::create_dir(&destination).expect("destination"); std::fs::write(destination.join("event_store.sqlite"), b"existing").expect("existing file"); - let receipt = RadrootsSdk::restore( + let receipt = RadrootsClient::restore( RestoreRequest::new(source) .with_destination(destination.clone()) .with_overwrite(true) @@ -1084,7 +1084,7 @@ async fn sdk_restore_dry_run_rejects_destination_inside_source() { .await .expect("backup"); - let error = RadrootsSdk::restore( + let error = RadrootsClient::restore( RestoreRequest::new(source.clone()) .with_destination(source.join("restore")) .with_overwrite(true) @@ -1107,7 +1107,7 @@ async fn sdk_restore_dry_run_rejects_corrupt_source_without_destination_writes() .expect("backup"); std::fs::write(source.join("event_store.sqlite"), b"not sqlite").expect("corrupt store"); - let error = RadrootsSdk::restore( + let error = RadrootsClient::restore( RestoreRequest::new(source) .with_destination(destination.clone()) .dry_run(), @@ -1136,7 +1136,7 @@ async fn sdk_restore_dry_run_rejects_symlink_destination() { std::fs::create_dir(&target).expect("target"); std::os::unix::fs::symlink(&target, &destination).expect("symlink"); - let error = RadrootsSdk::restore( + let error = RadrootsClient::restore( RestoreRequest::new(source) .with_destination(destination) .with_overwrite(true) @@ -1157,7 +1157,7 @@ async fn runtime_restore_handles_existing_file_destinations_by_overwrite_policy( std::fs::write(&destination, b"old restore file").expect("destination file"); let without_overwrite = - RadrootsSdk::restore(RestoreRequest::new(source.clone()).with_destination(&destination)) + RadrootsClient::restore(RestoreRequest::new(source.clone()).with_destination(&destination)) .await .expect_err("file destination without overwrite"); assert!(matches!( @@ -1165,7 +1165,7 @@ async fn runtime_restore_handles_existing_file_destinations_by_overwrite_policy( RadrootsSdkError::InvalidRequest { .. } )); - let receipt = RadrootsSdk::restore( + let receipt = RadrootsClient::restore( RestoreRequest::new(source) .with_destination(destination.clone()) .with_overwrite(true), @@ -1195,7 +1195,7 @@ async fn sdk_restore_to_empty_destination_succeeds() { .await .expect("backup"); - let receipt = RadrootsSdk::restore( + let receipt = RadrootsClient::restore( RestoreRequest::new(source.clone()).with_destination(destination.clone()), ) .await @@ -1209,7 +1209,7 @@ async fn sdk_restore_to_empty_destination_succeeds() { ); assert!(destination.join("event_store.sqlite").exists()); assert!(destination.join("outbox.sqlite").exists()); - let restored_sdk = RadrootsSdk::builder() + let restored_sdk = RadrootsClient::builder() .directory_storage(destination) .build() .await @@ -1242,7 +1242,7 @@ async fn sdk_restore_existing_destination_fails_without_overwrite() { std::fs::create_dir(&destination).expect("destination"); std::fs::write(destination.join("sentinel"), b"keep").expect("sentinel"); - let error = RadrootsSdk::restore(RestoreRequest::new(source).with_destination(&destination)) + let error = RadrootsClient::restore(RestoreRequest::new(source).with_destination(&destination)) .await .expect_err("existing destination"); @@ -1265,7 +1265,7 @@ async fn sdk_restore_overwrite_replaces_existing_destination() { std::fs::create_dir(&destination).expect("destination"); std::fs::write(destination.join("sentinel"), b"replace").expect("sentinel"); - let receipt = RadrootsSdk::restore( + let receipt = RadrootsClient::restore( RestoreRequest::new(source) .with_destination(destination.clone()) .with_overwrite(true), @@ -1275,7 +1275,7 @@ async fn sdk_restore_overwrite_replaces_existing_destination() { assert_eq!(receipt.state, SdkRestoreState::Completed); assert!(!destination.join("sentinel").exists()); - let restored_sdk = RadrootsSdk::builder() + let restored_sdk = RadrootsClient::builder() .directory_storage(destination) .build() .await @@ -1301,7 +1301,7 @@ async fn sdk_restore_corrupt_backup_leaves_destination_unchanged() { std::fs::create_dir(&destination).expect("destination"); std::fs::write(destination.join("sentinel"), b"keep").expect("sentinel"); - let error = RadrootsSdk::restore( + let error = RadrootsClient::restore( RestoreRequest::new(source) .with_destination(destination.clone()) .with_overwrite(true), @@ -1360,7 +1360,7 @@ async fn push_outbox_empty_queue_returns_zero_counts() { async fn product_push_outbox_uses_radrootsd_proxy_transport_with_daemon_resolved_relays() { let (endpoint, handle) = spawn_publish_proxy_server(); let tempdir = tempfile::tempdir().expect("tempdir"); - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .directory_storage(tempdir.path().join("sdk")) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)) .publish_transport(SdkPublishTransport::RadrootsdProxy( @@ -1438,7 +1438,7 @@ async fn product_push_outbox_radrootsd_proxy_idempotency_is_attempt_scoped() { let tempdir = tempfile::tempdir().expect("tempdir"); let storage = tempdir.path().join("sdk"); let transport = SdkPublishTransport::RadrootsdProxy(RadrootsdProxyConfig::new(endpoint)); - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .directory_storage(storage.clone()) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)) .publish_transport(transport.clone()) @@ -1478,7 +1478,7 @@ async fn product_push_outbox_radrootsd_proxy_idempotency_is_attempt_scoped() { ); drop(sdk); - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .directory_storage(storage) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_001)) .publish_transport(transport) diff --git a/crates/sdk/tests/unit/farms_runtime_tests.rs b/crates/sdk/tests/unit/farms_runtime_tests.rs @@ -141,7 +141,7 @@ fn farm_request_builders_reject_invalid_options_and_timestamp_bounds() { #[tokio::test] async fn farm_client_prepare_resolves_default_and_explicit_created_at() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_400)) .build() .await @@ -176,7 +176,7 @@ async fn farm_client_prepare_resolves_default_and_explicit_created_at() { #[tokio::test] async fn farm_client_prepare_reports_clock_errors() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .clock(crate::RadrootsSdkClock::BeforeUnixEpoch) .build() .await @@ -193,7 +193,7 @@ async fn farm_client_prepare_reports_clock_errors() { #[tokio::test] async fn farm_enqueue_publish_reports_prepare_errors_before_signing() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_500)) .build() .await @@ -216,7 +216,7 @@ async fn farm_enqueue_publish_reports_prepare_errors_before_signing() { #[tokio::test] async fn farm_client_enqueue_methods_cover_source_attached_workflow_paths() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_500)) .build() .await @@ -268,7 +268,7 @@ async fn farm_client_enqueue_methods_cover_source_attached_workflow_paths() { async fn farm_configured_local_signer_enqueues_publish_without_explicit_signer() { let keys = RadrootsNostrKeys::generate(); let farmer = keys.public_key().to_hex(); - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_500)) .signer_provider(RadrootsSdkSignerProvider::LocalKey( RadrootsSdkLocalKeySigner::new(keys).expect("signer"), diff --git a/crates/sdk/tests/unit/listings_runtime_tests.rs b/crates/sdk/tests/unit/listings_runtime_tests.rs @@ -172,7 +172,7 @@ fn listing_request_builders_reject_invalid_options_and_timestamp_bounds() { #[tokio::test] async fn listing_client_prepare_resolves_default_and_explicit_created_at() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_400)) .build() .await @@ -207,7 +207,7 @@ async fn listing_client_prepare_resolves_default_and_explicit_created_at() { #[tokio::test] async fn listing_client_prepare_reports_clock_errors() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .clock(crate::RadrootsSdkClock::BeforeUnixEpoch) .build() .await @@ -224,7 +224,7 @@ async fn listing_client_prepare_reports_clock_errors() { #[tokio::test] async fn listing_enqueue_publish_reports_prepare_errors_before_signing() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_500)) .build() .await @@ -251,7 +251,7 @@ async fn listing_enqueue_publish_reports_prepare_errors_before_signing() { #[tokio::test] async fn listing_client_enqueue_methods_cover_source_attached_workflow_paths() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_500)) .build() .await @@ -303,7 +303,7 @@ async fn listing_client_enqueue_methods_cover_source_attached_workflow_paths() { async fn listing_configured_local_signer_enqueues_publish_without_explicit_signer() { let keys = RadrootsNostrKeys::generate(); let seller = keys.public_key().to_hex(); - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_500)) .signer_provider(RadrootsSdkSignerProvider::LocalKey( RadrootsSdkLocalKeySigner::new(keys).expect("signer"), diff --git a/crates/sdk/tests/unit/orders_runtime_tests.rs b/crates/sdk/tests/unit/orders_runtime_tests.rs @@ -1,5 +1,5 @@ use super::*; -use crate::{RadrootsSdk, RadrootsSdkLocalKeySigner, RadrootsSdkSignerProvider}; +use crate::{RadrootsClient, RadrootsSdkLocalKeySigner, RadrootsSdkSignerProvider}; use radroots_authority::{RadrootsSignerError, RadrootsSignerIdentity}; use radroots_core::{ RadrootsCoreCurrency, RadrootsCoreDecimal, RadrootsCoreMoney, RadrootsCoreUnit, @@ -17,7 +17,10 @@ use radroots_events::{ use radroots_nostr::prelude::{ RadrootsNostrKeys, RadrootsNostrSecretKey, radroots_nostr_sign_frozen_draft, }; -use radroots_trade::order::{RadrootsOrderEventDecodeError, RadrootsOrderIssue}; +use radroots_trade::{ + order::{RadrootsOrderEventDecodeError, RadrootsOrderIssue}, + workflow::RadrootsTradeWorkflowState, +}; #[path = "../support/serializer_failure.rs"] mod serializer_failure; @@ -72,14 +75,17 @@ fn projection( ) -> RadrootsOrderProjection { RadrootsOrderProjection { order_id: order_id.clone(), - status: RadrootsOrderStatus::Requested, + status: RadrootsTradeWorkflowState::Requested, request_event_id: Some(root_event_id.clone()), decision_event_id: None, cancellation_event_id: None, + validation_receipt_event_id: None, lifecycle_terminal: false, economics: None, agreement_event_id: None, pending_revision_event_id: None, + pending_inventory_reservations: Vec::new(), + committed_inventory_reservations: Vec::new(), listing_addr: Some(listing_addr.clone()), buyer_pubkey: Some(buyer_pubkey.clone()), seller_pubkey: Some(seller_pubkey.clone()), @@ -407,8 +413,8 @@ fn fixture_target_relays() -> SdkRelayTargetPolicy { SdkRelayTargetPolicy::try_explicit([RELAY], SdkRelayUrlPolicy::Public).expect("target relays") } -async fn prepared_order_sdk() -> RadrootsSdk { - RadrootsSdk::builder() +async fn prepared_order_sdk() -> RadrootsClient { + RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)) .build() .await @@ -417,7 +423,7 @@ async fn prepared_order_sdk() -> RadrootsSdk { #[tokio::test] async fn order_configured_local_signer_enqueues_submit_without_explicit_signer() { - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000)) .signer_provider(RadrootsSdkSignerProvider::LocalKey( RadrootsSdkLocalKeySigner::new(keys_from_secret(BUYER_SECRET_KEY_HEX)).expect("signer"), @@ -427,7 +433,7 @@ async fn order_configured_local_signer_enqueues_submit_without_explicit_signer() .expect("sdk"); let receipt = sdk - .orders() + .trades() .enqueue_submit(OrderSubmitEnqueueRequest::new( fixture_buyer_actor(), fixture_event_ptr('a'), @@ -441,17 +447,17 @@ async fn order_configured_local_signer_enqueues_submit_without_explicit_signer() assert_eq!(receipt.state, SdkMutationState::StoredAndQueued); } -async fn enqueue_fixture_submit(sdk: &RadrootsSdk, raw_order_id: &str) -> OrderSubmitReceipt { +async fn enqueue_fixture_submit(sdk: &RadrootsClient, raw_order_id: &str) -> OrderSubmitReceipt { let buyer = fixture_buyer_actor(); let plan = sdk - .orders() + .trades() .prepare_submit(OrderSubmitPrepareRequest::new( buyer.clone(), fixture_event_ptr('a'), fixture_order_request(raw_order_id), )) .expect("submit plan"); - sdk.orders() + sdk.trades() .enqueue_prepared_submit_with_explicit_signer( &buyer, plan, @@ -1189,13 +1195,13 @@ fn decision_request_evidence_preflight_covers_all_rejection_branches() { ); projection.request_event_id = Some(request_event_id.clone()); - projection.status = RadrootsOrderStatus::Accepted; + projection.status = RadrootsTradeWorkflowState::AgreedPendingRhi; assert!( invalid_request_message(require_decision_request_evidence(&plan, &projection).unwrap_err()) .contains("requires requested local state") ); - projection.status = RadrootsOrderStatus::Requested; + projection.status = RadrootsTradeWorkflowState::Requested; projection.pending_revision_event_id = Some(event_id('c')); assert!( invalid_request_message(require_decision_request_evidence(&plan, &projection).unwrap_err()) @@ -1247,6 +1253,7 @@ fn order_status_next_action_covers_revision_and_fallback_terminal_paths() { &root_event_id, &previous_event_id, ); + projection.status = RadrootsTradeWorkflowState::RevisionProposed; projection.pending_revision_event_id = Some(previous_event_id.clone()); let eligibility = OrderStatusEligibility::from_projection(&projection); @@ -1269,6 +1276,7 @@ fn order_status_next_action_covers_revision_and_fallback_terminal_paths() { assert!(receipt.evidence.has_pending_revision); projection.pending_revision_event_id = None; + projection.status = RadrootsTradeWorkflowState::Requested; let fallback = OrderStatusNextActionKind::from_projection( &projection, &OrderStatusEligibility { @@ -1496,7 +1504,7 @@ fn lifecycle_projection_helpers_reject_unclean_mismatched_and_stale_state() { &previous_event_id, ); assert!(require_clean_lifecycle_projection(refs, &clean).is_ok()); - assert!(require_lifecycle_status(&refs, &clean, RadrootsOrderStatus::Requested).is_ok()); + assert!(require_lifecycle_status(&refs, &clean, RadrootsTradeWorkflowState::Requested).is_ok()); assert!(require_no_lifecycle_terminal(&refs, &clean).is_ok()); assert!(require_no_pending_revision(&refs, &clean).is_ok()); assert!(require_lifecycle_previous_is_current(&refs, &clean).is_ok()); @@ -1547,10 +1555,11 @@ fn lifecycle_projection_helpers_reject_unclean_mismatched_and_stale_state() { ); let mut accepted = clean.clone(); - accepted.status = RadrootsOrderStatus::Accepted; + accepted.status = RadrootsTradeWorkflowState::AgreedPendingRhi; assert!( invalid_request_message( - require_lifecycle_status(&refs, &accepted, RadrootsOrderStatus::Requested).unwrap_err() + require_lifecycle_status(&refs, &accepted, RadrootsTradeWorkflowState::Requested) + .unwrap_err() ) .contains("requires Requested") ); @@ -1665,7 +1674,7 @@ fn lifecycle_plan_state_wrappers_reject_invalid_status_terminal_and_pending_stat assert!(require_revision_proposal_state(&proposal_plan, &base).is_ok()); let mut accepted = base.clone(); - accepted.status = RadrootsOrderStatus::Accepted; + accepted.status = RadrootsTradeWorkflowState::AgreedPendingRhi; assert!( invalid_request_message( require_revision_proposal_state(&proposal_plan, &accepted).unwrap_err() @@ -1683,6 +1692,7 @@ fn lifecycle_plan_state_wrappers_reject_invalid_status_terminal_and_pending_stat ); let mut revision_ready = base.clone(); + revision_ready.status = RadrootsTradeWorkflowState::RevisionProposed; revision_ready.last_event_id = Some(proposal_plan.expected_event_id.clone()); revision_ready.pending_revision_event_id = Some(proposal_plan.expected_event_id.clone()); assert!(require_revision_decision_state(&revision_plan, &revision_ready).is_ok()); @@ -1708,7 +1718,7 @@ fn lifecycle_plan_state_wrappers_reject_invalid_status_terminal_and_pending_stat assert!(require_cancellation_state(&cancellation_plan, &base).is_ok()); let mut cancellation_accepted = base.clone(); - cancellation_accepted.status = RadrootsOrderStatus::Accepted; + cancellation_accepted.status = RadrootsTradeWorkflowState::AgreedPendingRhi; assert!( invalid_request_message( require_cancellation_state(&cancellation_plan, &cancellation_accepted).unwrap_err() @@ -1992,7 +2002,7 @@ fn order_enqueue_request_mutators_reject_invalid_relays_and_idempotency_keys() { #[tokio::test] async fn orders_client_prepare_methods_resolve_request_created_at() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_010)) .build() .await @@ -2003,7 +2013,7 @@ async fn orders_client_prepare_methods_resolve_request_created_at() { let previous_event = ptr(previous_event_id.as_str().to_owned()); assert_eq!( - sdk.orders() + sdk.trades() .prepare_submit(OrderSubmitPrepareRequest::new( buyer_actor(), root_event.clone(), @@ -2014,7 +2024,7 @@ async fn orders_client_prepare_methods_resolve_request_created_at() { RadrootsSdkTimestamp::from_unix_seconds(1_700_000_010) ); assert_eq!( - sdk.orders() + sdk.trades() .prepare_decision( OrderDecisionPrepareRequest::new( seller_actor(), @@ -2030,7 +2040,7 @@ async fn orders_client_prepare_methods_resolve_request_created_at() { let proposal = revision_proposal_payload(&root_event_id, &previous_event_id); assert_eq!( - sdk.orders() + sdk.trades() .prepare_revision_proposal( OrderRevisionProposalPrepareRequest::new( seller_actor(), @@ -2045,7 +2055,7 @@ async fn orders_client_prepare_methods_resolve_request_created_at() { RadrootsSdkTimestamp::from_unix_seconds(1_700_000_012) ); assert_eq!( - sdk.orders() + sdk.trades() .prepare_revision_decision( OrderRevisionDecisionPrepareRequest::new( buyer_actor(), @@ -2064,7 +2074,7 @@ async fn orders_client_prepare_methods_resolve_request_created_at() { RadrootsSdkTimestamp::from_unix_seconds(1_700_000_013) ); assert_eq!( - sdk.orders() + sdk.trades() .prepare_cancellation( OrderCancellationPrepareRequest::new( buyer_actor(), @@ -2090,7 +2100,7 @@ async fn prepared_submit_and_decision_enqueue_cover_source_attached_success_path let seller = fixture_seller_actor(); let decision_plan = sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( seller.clone(), fixture_order_event_ptr(&submit.signed_event_id), @@ -2098,7 +2108,7 @@ async fn prepared_submit_and_decision_enqueue_cover_source_attached_success_path )) .expect("decision plan"); let decision = sdk - .orders() + .trades() .enqueue_prepared_decision_with_explicit_signer( &seller, decision_plan, @@ -2125,7 +2135,7 @@ async fn prepared_revision_lifecycle_enqueue_cover_source_attached_success_paths &submit.signed_event_id, ); let proposal_plan = sdk - .orders() + .trades() .prepare_revision_proposal(OrderRevisionProposalPrepareRequest::new( seller.clone(), fixture_order_event_ptr(&submit.signed_event_id), @@ -2134,7 +2144,7 @@ async fn prepared_revision_lifecycle_enqueue_cover_source_attached_success_paths )) .expect("proposal plan"); let proposal = sdk - .orders() + .trades() .enqueue_prepared_revision_proposal_with_explicit_signer( &seller, proposal_plan, @@ -2153,7 +2163,7 @@ async fn prepared_revision_lifecycle_enqueue_cover_source_attached_success_paths let buyer = fixture_buyer_actor(); let revision_decision = fixture_revision_decision(&proposal_payload, &proposal.signed_event_id); let revision_decision_plan = sdk - .orders() + .trades() .prepare_revision_decision(OrderRevisionDecisionPrepareRequest::new( buyer.clone(), fixture_order_event_ptr(&submit.signed_event_id), @@ -2162,7 +2172,7 @@ async fn prepared_revision_lifecycle_enqueue_cover_source_attached_success_paths )) .expect("revision decision plan"); let revision = sdk - .orders() + .trades() .enqueue_prepared_revision_decision_with_explicit_signer( &buyer, revision_decision_plan, @@ -2185,7 +2195,7 @@ async fn prepared_cancellation_enqueue_covers_source_attached_success_path() { let submit = enqueue_fixture_submit(&sdk, "order-prepared-cancellation").await; let buyer = fixture_buyer_actor(); let cancellation_plan = sdk - .orders() + .trades() .prepare_cancellation(OrderCancellationPrepareRequest::new( buyer.clone(), fixture_order_event_ptr(&submit.signed_event_id), @@ -2194,7 +2204,7 @@ async fn prepared_cancellation_enqueue_covers_source_attached_success_path() { )) .expect("cancellation plan"); let cancellation = sdk - .orders() + .trades() .enqueue_prepared_cancellation_with_explicit_signer( &buyer, cancellation_plan, @@ -2215,7 +2225,7 @@ async fn prepared_cancellation_enqueue_covers_source_attached_success_path() { async fn convenience_order_enqueue_methods_cover_source_attached_wrappers() { let sdk = prepared_order_sdk().await; let decision_submit = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer( OrderSubmitEnqueueRequest::new( fixture_buyer_actor(), @@ -2228,7 +2238,7 @@ async fn convenience_order_enqueue_methods_cover_source_attached_wrappers() { .await .expect("enqueue submit"); let decision = sdk - .orders() + .trades() .enqueue_decision_with_explicit_signer( OrderDecisionEnqueueRequest::new( fixture_seller_actor(), @@ -2243,7 +2253,7 @@ async fn convenience_order_enqueue_methods_cover_source_attached_wrappers() { assert_eq!(decision.request_event_id, decision_submit.signed_event_id); let revision_submit = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer( OrderSubmitEnqueueRequest::new( fixture_buyer_actor(), @@ -2261,7 +2271,7 @@ async fn convenience_order_enqueue_methods_cover_source_attached_wrappers() { &revision_submit.signed_event_id, ); let proposal = sdk - .orders() + .trades() .enqueue_revision_proposal_with_explicit_signer( OrderRevisionProposalEnqueueRequest::new( fixture_seller_actor(), @@ -2275,7 +2285,7 @@ async fn convenience_order_enqueue_methods_cover_source_attached_wrappers() { .await .expect("enqueue proposal"); let revision = sdk - .orders() + .trades() .enqueue_revision_decision_with_explicit_signer( OrderRevisionDecisionEnqueueRequest::new( fixture_buyer_actor(), @@ -2291,7 +2301,7 @@ async fn convenience_order_enqueue_methods_cover_source_attached_wrappers() { assert_eq!(revision.previous_event_id, proposal.signed_event_id); let cancellation_submit = sdk - .orders() + .trades() .enqueue_submit_with_explicit_signer( OrderSubmitEnqueueRequest::new( fixture_buyer_actor(), @@ -2304,7 +2314,7 @@ async fn convenience_order_enqueue_methods_cover_source_attached_wrappers() { .await .expect("enqueue cancellation submit"); let cancellation = sdk - .orders() + .trades() .enqueue_cancellation_with_explicit_signer( OrderCancellationEnqueueRequest::new( fixture_buyer_actor(), @@ -2336,7 +2346,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( fixture_revision_proposal("order-preflight-errors", &root_event_id, &previous_event_id); let decision_plan = sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( seller.clone(), root.clone(), @@ -2344,7 +2354,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )) .expect("decision plan"); let decision_missing = sdk - .orders() + .trades() .enqueue_prepared_decision_with_explicit_signer( &seller, decision_plan, @@ -2360,7 +2370,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )); let proposal_plan = sdk - .orders() + .trades() .prepare_revision_proposal(OrderRevisionProposalPrepareRequest::new( seller.clone(), root.clone(), @@ -2369,7 +2379,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )) .expect("proposal plan"); let proposal_missing = sdk - .orders() + .trades() .enqueue_prepared_revision_proposal_with_explicit_signer( &seller, proposal_plan, @@ -2385,7 +2395,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )); let revision_decision_plan = sdk - .orders() + .trades() .prepare_revision_decision(OrderRevisionDecisionPrepareRequest::new( buyer.clone(), root.clone(), @@ -2394,7 +2404,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )) .expect("revision decision plan"); let revision_missing = sdk - .orders() + .trades() .enqueue_prepared_revision_decision_with_explicit_signer( &buyer, revision_decision_plan, @@ -2410,7 +2420,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )); let cancellation_plan = sdk - .orders() + .trades() .prepare_cancellation(OrderCancellationPrepareRequest::new( buyer.clone(), root, @@ -2419,7 +2429,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )) .expect("cancellation plan"); let cancellation_missing = sdk - .orders() + .trades() .enqueue_prepared_cancellation_with_explicit_signer( &buyer, cancellation_plan, @@ -2445,7 +2455,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( &closed_previous_event_id, ); let closed_plan = closed_sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( seller.clone(), closed_root.clone(), @@ -2453,7 +2463,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )) .expect("closed decision plan"); let closed_proposal_plan = closed_sdk - .orders() + .trades() .prepare_revision_proposal(OrderRevisionProposalPrepareRequest::new( seller.clone(), closed_root.clone(), @@ -2462,7 +2472,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )) .expect("closed proposal plan"); let closed_revision_plan = closed_sdk - .orders() + .trades() .prepare_revision_decision(OrderRevisionDecisionPrepareRequest::new( buyer.clone(), closed_root.clone(), @@ -2471,7 +2481,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( )) .expect("closed revision decision plan"); let closed_cancellation_plan = closed_sdk - .orders() + .trades() .prepare_cancellation(OrderCancellationPrepareRequest::new( buyer.clone(), closed_root, @@ -2481,7 +2491,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( .expect("closed cancellation plan"); closed_sdk._event_store.pool().close().await; let closed_error = closed_sdk - .orders() + .trades() .enqueue_prepared_decision_with_explicit_signer( &seller, closed_plan, @@ -2493,7 +2503,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( .expect_err("closed preflight"); assert!(matches!(closed_error, RadrootsSdkError::EventStore { .. })); let closed_proposal_error = closed_sdk - .orders() + .trades() .enqueue_prepared_revision_proposal_with_explicit_signer( &seller, closed_proposal_plan, @@ -2508,7 +2518,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( RadrootsSdkError::EventStore { .. } )); let closed_revision_error = closed_sdk - .orders() + .trades() .enqueue_prepared_revision_decision_with_explicit_signer( &buyer, closed_revision_plan, @@ -2523,7 +2533,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( RadrootsSdkError::EventStore { .. } )); let closed_cancellation_error = closed_sdk - .orders() + .trades() .enqueue_prepared_cancellation_with_explicit_signer( &buyer, closed_cancellation_plan, @@ -2542,7 +2552,7 @@ async fn prepared_lifecycle_enqueues_report_missing_and_closed_preflight_errors( #[tokio::test] async fn lifecycle_preflight_helpers_map_projection_query_failures() { let sdk = prepared_order_sdk().await; - let client = sdk.orders(); + let client = sdk.trades(); let buyer = fixture_buyer_actor(); let seller = fixture_seller_actor(); let root_event_id = event_id('e'); @@ -2624,7 +2634,7 @@ async fn prepared_lifecycle_enqueues_report_closed_outbox_after_preflight() { &proposal_submit.signed_event_id, ); let proposal_plan = proposal_sdk - .orders() + .trades() .prepare_revision_proposal(OrderRevisionProposalPrepareRequest::new( seller.clone(), fixture_order_event_ptr(&proposal_submit.signed_event_id), @@ -2634,7 +2644,7 @@ async fn prepared_lifecycle_enqueues_report_closed_outbox_after_preflight() { .expect("proposal plan"); proposal_sdk._outbox.pool().close().await; let proposal_error = proposal_sdk - .orders() + .trades() .enqueue_prepared_revision_proposal_with_explicit_signer( &seller, proposal_plan, @@ -2655,7 +2665,7 @@ async fn prepared_lifecycle_enqueues_report_closed_outbox_after_preflight() { &revision_submit.signed_event_id, ); let proposal_plan = revision_sdk - .orders() + .trades() .prepare_revision_proposal(OrderRevisionProposalPrepareRequest::new( seller.clone(), fixture_order_event_ptr(&revision_submit.signed_event_id), @@ -2664,7 +2674,7 @@ async fn prepared_lifecycle_enqueues_report_closed_outbox_after_preflight() { )) .expect("revision proposal plan"); let proposal = revision_sdk - .orders() + .trades() .enqueue_prepared_revision_proposal_with_explicit_signer( &seller, proposal_plan, @@ -2676,7 +2686,7 @@ async fn prepared_lifecycle_enqueues_report_closed_outbox_after_preflight() { .expect("enqueue proposal"); let buyer = fixture_buyer_actor(); let revision_plan = revision_sdk - .orders() + .trades() .prepare_revision_decision(OrderRevisionDecisionPrepareRequest::new( buyer.clone(), fixture_order_event_ptr(&revision_submit.signed_event_id), @@ -2686,7 +2696,7 @@ async fn prepared_lifecycle_enqueues_report_closed_outbox_after_preflight() { .expect("revision plan"); revision_sdk._outbox.pool().close().await; let revision_error = revision_sdk - .orders() + .trades() .enqueue_prepared_revision_decision_with_explicit_signer( &buyer, revision_plan, @@ -2702,7 +2712,7 @@ async fn prepared_lifecycle_enqueues_report_closed_outbox_after_preflight() { let cancellation_submit = enqueue_fixture_submit(&cancellation_sdk, "order-closed-outbox-cancellation").await; let cancellation_plan = cancellation_sdk - .orders() + .trades() .prepare_cancellation(OrderCancellationPrepareRequest::new( buyer.clone(), fixture_order_event_ptr(&cancellation_submit.signed_event_id), @@ -2712,7 +2722,7 @@ async fn prepared_lifecycle_enqueues_report_closed_outbox_after_preflight() { .expect("cancellation plan"); cancellation_sdk._outbox.pool().close().await; let cancellation_error = cancellation_sdk - .orders() + .trades() .enqueue_prepared_cancellation_with_explicit_signer( &buyer, cancellation_plan, @@ -2731,7 +2741,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { let decision_submit = enqueue_fixture_submit(&decision_sdk, "order-existing-decision").await; let seller = fixture_seller_actor(); let decision_plan = decision_sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( seller.clone(), fixture_order_event_ptr(&decision_submit.signed_event_id), @@ -2739,7 +2749,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { )) .expect("decision plan"); decision_sdk - .orders() + .trades() .enqueue_prepared_decision_with_explicit_signer( &seller, decision_plan.clone(), @@ -2750,7 +2760,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { .await .expect("enqueue decision"); let decision_repeat = decision_sdk - .orders() + .trades() .enqueue_prepared_decision_with_explicit_signer( &seller, decision_plan, @@ -2779,7 +2789,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { &proposal_submit.signed_event_id, ); let proposal_plan = proposal_sdk - .orders() + .trades() .prepare_revision_proposal(OrderRevisionProposalPrepareRequest::new( seller.clone(), fixture_order_event_ptr(&proposal_submit.signed_event_id), @@ -2788,7 +2798,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { )) .expect("proposal plan"); proposal_sdk - .orders() + .trades() .enqueue_prepared_revision_proposal_with_explicit_signer( &seller, proposal_plan.clone(), @@ -2799,7 +2809,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { .await .expect("enqueue proposal"); let proposal_repeat = proposal_sdk - .orders() + .trades() .enqueue_prepared_revision_proposal_with_explicit_signer( &seller, proposal_plan, @@ -2828,7 +2838,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { &revision_submit.signed_event_id, ); let proposal_plan = revision_sdk - .orders() + .trades() .prepare_revision_proposal(OrderRevisionProposalPrepareRequest::new( seller.clone(), fixture_order_event_ptr(&revision_submit.signed_event_id), @@ -2837,7 +2847,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { )) .expect("revision proposal plan"); let proposal = revision_sdk - .orders() + .trades() .enqueue_prepared_revision_proposal_with_explicit_signer( &seller, proposal_plan, @@ -2849,7 +2859,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { .expect("enqueue proposal"); let buyer = fixture_buyer_actor(); let revision_plan = revision_sdk - .orders() + .trades() .prepare_revision_decision(OrderRevisionDecisionPrepareRequest::new( buyer.clone(), fixture_order_event_ptr(&revision_submit.signed_event_id), @@ -2858,7 +2868,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { )) .expect("revision plan"); revision_sdk - .orders() + .trades() .enqueue_prepared_revision_decision_with_explicit_signer( &buyer, revision_plan.clone(), @@ -2869,7 +2879,7 @@ async fn prepared_lifecycle_enqueues_skip_preflight_for_existing_events() { .await .expect("enqueue revision"); let revision_repeat = revision_sdk - .orders() + .trades() .enqueue_prepared_revision_decision_with_explicit_signer( &buyer, revision_plan, @@ -2899,7 +2909,7 @@ async fn order_ingest_and_enqueue_wrappers_report_prepare_timestamp_errors() { let seller = fixture_seller_actor(); assert!(matches!( - sdk.orders() + sdk.trades() .ingest_evidence( OrderEvidenceIngestRequest::new(request_event()).with_observed_at(out_of_range,) ) @@ -2907,7 +2917,7 @@ async fn order_ingest_and_enqueue_wrappers_report_prepare_timestamp_errors() { Err(RadrootsSdkError::TimestampOutOfRange { .. }) )); assert!(matches!( - sdk.orders() + sdk.trades() .ingest_request_evidence( OrderRequestEvidenceIngestRequest::new(request_event()) .with_observed_at(out_of_range,), @@ -2916,7 +2926,7 @@ async fn order_ingest_and_enqueue_wrappers_report_prepare_timestamp_errors() { Err(RadrootsSdkError::TimestampOutOfRange { .. }) )); assert!(matches!( - sdk.orders() + sdk.trades() .enqueue_submit_with_explicit_signer( OrderSubmitEnqueueRequest::new( buyer.clone(), @@ -2931,7 +2941,7 @@ async fn order_ingest_and_enqueue_wrappers_report_prepare_timestamp_errors() { Err(RadrootsSdkError::TimestampOutOfRange { .. }) )); assert!(matches!( - sdk.orders() + sdk.trades() .enqueue_decision_with_explicit_signer( OrderDecisionEnqueueRequest::new( seller.clone(), @@ -2954,7 +2964,7 @@ async fn order_ingest_and_enqueue_wrappers_report_prepare_timestamp_errors() { &previous_event_id, ); assert!(matches!( - sdk.orders() + sdk.trades() .enqueue_revision_proposal_with_explicit_signer( OrderRevisionProposalEnqueueRequest::new( seller.clone(), @@ -2970,7 +2980,7 @@ async fn order_ingest_and_enqueue_wrappers_report_prepare_timestamp_errors() { Err(RadrootsSdkError::TimestampOutOfRange { .. }) )); assert!(matches!( - sdk.orders() + sdk.trades() .enqueue_revision_decision_with_explicit_signer( OrderRevisionDecisionEnqueueRequest::new( buyer.clone(), @@ -2986,7 +2996,7 @@ async fn order_ingest_and_enqueue_wrappers_report_prepare_timestamp_errors() { Err(RadrootsSdkError::TimestampOutOfRange { .. }) )); assert!(matches!( - sdk.orders() + sdk.trades() .enqueue_cancellation_with_explicit_signer( OrderCancellationEnqueueRequest::new( buyer, @@ -3005,7 +3015,7 @@ async fn order_ingest_and_enqueue_wrappers_report_prepare_timestamp_errors() { #[tokio::test] async fn order_default_timestamp_paths_report_clock_errors() { - let clock_error_sdk = crate::RadrootsSdk::builder() + let clock_error_sdk = crate::RadrootsClient::builder() .clock(crate::RadrootsSdkClock::BeforeUnixEpoch) .build() .await @@ -3018,21 +3028,21 @@ async fn order_default_timestamp_paths_report_clock_errors() { assert!(matches!( clock_error_sdk - .orders() + .trades() .ingest_evidence(OrderEvidenceIngestRequest::new(request_event())) .await, Err(RadrootsSdkError::ClockBeforeUnixEpoch) )); assert!(matches!( clock_error_sdk - .orders() + .trades() .ingest_request_evidence(OrderRequestEvidenceIngestRequest::new(request_event())) .await, Err(RadrootsSdkError::ClockBeforeUnixEpoch) )); assert!(matches!( clock_error_sdk - .orders() + .trades() .prepare_submit(OrderSubmitPrepareRequest::new( buyer.clone(), ptr(root_event_id.as_str().to_owned()), @@ -3042,7 +3052,7 @@ async fn order_default_timestamp_paths_report_clock_errors() { )); assert!(matches!( clock_error_sdk - .orders() + .trades() .prepare_decision(OrderDecisionPrepareRequest::new( seller.clone(), ptr(root_event_id.as_str().to_owned()), @@ -3051,7 +3061,7 @@ async fn order_default_timestamp_paths_report_clock_errors() { Err(RadrootsSdkError::ClockBeforeUnixEpoch) )); assert!(matches!( - clock_error_sdk.orders().prepare_revision_proposal( + clock_error_sdk.trades().prepare_revision_proposal( OrderRevisionProposalPrepareRequest::new( seller, ptr(root_event_id.as_str().to_owned()), @@ -3062,7 +3072,7 @@ async fn order_default_timestamp_paths_report_clock_errors() { Err(RadrootsSdkError::ClockBeforeUnixEpoch) )); assert!(matches!( - clock_error_sdk.orders().prepare_revision_decision( + clock_error_sdk.trades().prepare_revision_decision( OrderRevisionDecisionPrepareRequest::new( buyer.clone(), ptr(root_event_id.as_str().to_owned()), @@ -3078,7 +3088,7 @@ async fn order_default_timestamp_paths_report_clock_errors() { )); assert!(matches!( clock_error_sdk - .orders() + .trades() .prepare_cancellation(OrderCancellationPrepareRequest::new( buyer, ptr(root_event_id.as_str().to_owned()), @@ -3237,19 +3247,19 @@ fn order_runtime_request_builders_and_serializers_cover_source_attached_paths() #[tokio::test] async fn closed_event_store_errors_are_mapped_for_ingest_and_prepared_lookup() { - let sdk = crate::RadrootsSdk::builder().build().await.expect("sdk"); + let sdk = crate::RadrootsClient::builder().build().await.expect("sdk"); sdk._event_store.pool().close().await; let ingest_error = sdk - .orders() + .trades() .ingest_evidence(OrderEvidenceIngestRequest::new(request_event())) .await .expect_err("closed ingest evidence"); assert!(matches!(ingest_error, RadrootsSdkError::EventStore { .. })); - let sdk = crate::RadrootsSdk::builder().build().await.expect("sdk"); + let sdk = crate::RadrootsClient::builder().build().await.expect("sdk"); sdk._event_store.pool().close().await; let request_ingest_error = sdk - .orders() + .trades() .ingest_request_evidence(OrderRequestEvidenceIngestRequest::new(request_event())) .await .expect_err("closed request evidence ingest"); @@ -3258,10 +3268,10 @@ async fn closed_event_store_errors_are_mapped_for_ingest_and_prepared_lookup() { RadrootsSdkError::EventStore { .. } )); - let sdk = crate::RadrootsSdk::builder().build().await.expect("sdk"); + let sdk = crate::RadrootsClient::builder().build().await.expect("sdk"); sdk._event_store.pool().close().await; let lookup_error = sdk - .orders() + .trades() .prepared_order_event_exists(&event_id('a')) .await .expect_err("closed prepared lookup"); @@ -3273,7 +3283,7 @@ async fn order_status_and_evidence_ingest_cover_source_attached_success_paths() let sdk = prepared_order_sdk().await; let request_event = request_event(); let request_receipt = sdk - .orders() + .trades() .ingest_request_evidence(OrderRequestEvidenceIngestRequest::new( request_event.clone(), )) @@ -3284,7 +3294,7 @@ async fn order_status_and_evidence_ingest_cover_source_attached_success_paths() let submit = enqueue_fixture_submit(&sdk, "order-status-source-attached").await; let status = sdk - .orders() + .trades() .status(OrderStatusRequest::parse(submit.order_id.as_str()).expect("status request")) .await .expect("order status"); @@ -3292,7 +3302,7 @@ async fn order_status_and_evidence_ingest_cover_source_attached_success_paths() assert!(status.evidence.has_request); let duplicate_receipt = sdk - .orders() + .trades() .ingest_evidence(OrderEvidenceIngestRequest::new(request_event)) .await .expect("order evidence ingest"); diff --git a/crates/sdk/tests/unit/runtime_tests.rs b/crates/sdk/tests/unit/runtime_tests.rs @@ -124,7 +124,7 @@ async fn open_storage_and_storage_kind_cover_memory_directory_and_file_failures( .await .expect("memory storage"); assert!(memory.paths.is_none()); - let memory_sdk = RadrootsSdk { + let memory_sdk = RadrootsClient { _event_store: memory.event_store, _outbox: memory.outbox, storage_paths: None, @@ -144,7 +144,7 @@ async fn open_storage_and_storage_kind_cover_memory_directory_and_file_failures( let directory_paths = directory_storage.paths.expect("directory paths"); assert!(directory_paths.event_store_path.exists()); assert!(directory_paths.outbox_path.exists()); - let directory_sdk = RadrootsSdk { + let directory_sdk = RadrootsClient { _event_store: directory_storage.event_store, _outbox: directory_storage.outbox, storage_paths: Some(directory_paths), @@ -185,7 +185,7 @@ async fn runtime_public_surface_covers_builders_status_integrity_backup_and_rest .is_err() ); - let memory_sdk = RadrootsSdk::builder() + let memory_sdk = RadrootsClient::builder() .storage(RadrootsSdkStorageConfig::Memory) .clock(RadrootsSdkClock::Fixed( RadrootsSdkTimestamp::from_unix_seconds(1_700_000_000), @@ -203,7 +203,7 @@ async fn runtime_public_surface_covers_builders_status_integrity_backup_and_rest assert!(memory_sdk.storage_paths().is_none()); let _ = memory_sdk.farms(); let _ = memory_sdk.listings(); - let _ = memory_sdk.orders(); + let _ = memory_sdk.trades(); let _ = memory_sdk.sync(); let memory_status = memory_sdk .storage_status(StorageStatusRequest::new()) @@ -219,7 +219,7 @@ async fn runtime_public_surface_covers_builders_status_integrity_backup_and_rest let tempdir = tempfile::tempdir().expect("tempdir"); let directory = tempdir.path().join("sdk"); - let directory_sdk = RadrootsSdk::builder() + let directory_sdk = RadrootsClient::builder() .directory_storage(&directory) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_001)) .build() @@ -240,13 +240,13 @@ async fn runtime_public_surface_covers_builders_status_integrity_backup_and_rest .is_some_and(|path| path.exists()) ); - let archive = RadrootsSdk::inspect_restore_archive(&backup_destination) + let archive = RadrootsClient::inspect_restore_archive(&backup_destination) .await .expect("restore archive"); assert_eq!(archive.manifest, backup.manifest); let restore_destination = tempdir.path().join("restore"); - let dry_run = RadrootsSdk::restore( + let dry_run = RadrootsClient::restore( RestoreRequest::new(&backup_destination) .with_destination(&restore_destination) .with_overwrite(false) @@ -257,7 +257,7 @@ async fn runtime_public_surface_covers_builders_status_integrity_backup_and_rest assert_eq!(dry_run.state, SdkRestoreState::DryRun); assert!(dry_run.restored_paths.is_none()); - let restore = RadrootsSdk::restore( + let restore = RadrootsClient::restore( RestoreRequest::new(&backup_destination) .with_destination(&restore_destination) .with_overwrite(true), @@ -279,7 +279,7 @@ async fn runtime_clock_errors_cover_sdk_now_callers() { RadrootsSdkClock::BeforeUnixEpoch.now(), Err(RadrootsSdkError::ClockBeforeUnixEpoch) )); - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .clock(RadrootsSdkClock::BeforeUnixEpoch) .build() .await @@ -324,7 +324,7 @@ fn system_time_converters_cover_epoch_success_and_failure_edges() { #[tokio::test] async fn storage_status_integrity_and_backup_map_closed_pool_errors() { - let event_store_closed = RadrootsSdk::builder().build().await.expect("sdk"); + let event_store_closed = RadrootsClient::builder().build().await.expect("sdk"); event_store_closed._event_store.pool().close().await; assert!(matches!( event_store_closed @@ -347,7 +347,7 @@ async fn storage_status_integrity_and_backup_map_closed_pool_errors() { Err(RadrootsSdkError::EventStore { .. }) )); - let outbox_closed = RadrootsSdk::builder().build().await.expect("sdk"); + let outbox_closed = RadrootsClient::builder().build().await.expect("sdk"); outbox_closed._outbox.pool().close().await; assert!(matches!( outbox_closed @@ -551,7 +551,11 @@ fn restore_destination_preflight_covers_empty_existing_new_and_overlap_paths() { #[cfg(unix)] { - let socket_destination = parent.join("socket-destination"); + let socket_parent = tempfile::Builder::new() + .prefix("rrsdk") + .tempdir_in("/tmp") + .expect("short socket tempdir"); + let socket_destination = socket_parent.path().join("socket-destination"); let _listener = std::os::unix::net::UnixListener::bind(&socket_destination).expect("socket"); assert!( @@ -990,7 +994,7 @@ async fn restore_archive_private_failures_cover_staging_and_verification_edges() set_mode(&protected_parent, 0o700); assert!(!io_message(protected_result).is_empty()); - let sdk = RadrootsSdk::builder() + let sdk = RadrootsClient::builder() .directory_storage(tempdir.path().join("sdk")) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_001)) .build() @@ -1007,7 +1011,7 @@ async fn restore_archive_private_failures_cover_staging_and_verification_edges() fs::create_dir(&public_protected_parent).expect("public protected parent"); let public_protected_destination = public_protected_parent.join("restore"); set_mode(&public_protected_parent, 0o500); - let public_protected_result = RadrootsSdk::restore( + let public_protected_result = RadrootsClient::restore( RestoreRequest::new(&backup_destination).with_destination(&public_protected_destination), ) .await; @@ -1059,7 +1063,7 @@ async fn restore_archive_private_failures_cover_staging_and_verification_edges() .contains("does not match manifest") ); - let populated_sdk = RadrootsSdk::builder() + let populated_sdk = RadrootsClient::builder() .directory_storage(tempdir.path().join("populated-sdk")) .fixed_clock(RadrootsSdkTimestamp::from_unix_seconds(1_700_000_002)) .build() diff --git a/crates/sdk/tests/unit/signer_provider_tests.rs b/crates/sdk/tests/unit/signer_provider_tests.rs @@ -535,7 +535,7 @@ async fn myc_nip46_provider_rejects_returned_event_drift() { #[tokio::test] async fn sdk_builder_installs_configured_signer_provider() { let signer = RadrootsSdkLocalKeySigner::new(user_keys()).expect("signer"); - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .signer_provider(RadrootsSdkSignerProvider::LocalKey(signer)) .build() .await diff --git a/crates/sdk/tests/unit/sync_runtime_tests.rs b/crates/sdk/tests/unit/sync_runtime_tests.rs @@ -298,7 +298,7 @@ fn relay_outcome_kind_mapping_covers_all_transport_outcomes() { #[tokio::test] async fn sync_status_maps_closed_store_errors() { - let event_store_closed = crate::RadrootsSdk::builder().build().await.expect("sdk"); + let event_store_closed = crate::RadrootsClient::builder().build().await.expect("sdk"); event_store_closed._event_store.pool().close().await; assert!(matches!( event_store_closed @@ -308,7 +308,7 @@ async fn sync_status_maps_closed_store_errors() { Err(RadrootsSdkError::EventStore { .. }) )); - let outbox_closed = crate::RadrootsSdk::builder().build().await.expect("sdk"); + let outbox_closed = crate::RadrootsClient::builder().build().await.expect("sdk"); outbox_closed._outbox.pool().close().await; assert!(matches!( outbox_closed @@ -321,7 +321,7 @@ async fn sync_status_maps_closed_store_errors() { #[tokio::test] async fn sync_runtime_reports_clock_errors_before_store_or_relay_work() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .clock(crate::RadrootsSdkClock::BeforeUnixEpoch) .build() .await diff --git a/crates/sdk/tests/unit/workflow_runtime_tests.rs b/crates/sdk/tests/unit/workflow_runtime_tests.rs @@ -125,7 +125,7 @@ fn workflow_digest_and_event_helpers_cover_error_and_input_paths() { #[tokio::test] async fn enqueue_signed_workflow_reports_partial_mutation_when_outbox_fails() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .relay_url("wss://relay.example.com") .build() .await @@ -166,7 +166,7 @@ async fn enqueue_signed_workflow_reports_store_failures() { let actor = RadrootsActorContext::test(FARMER_PUBLIC_KEY_HEX, [RadrootsActorRole::Farmer]) .expect("actor"); let draft = frozen_draft_for(FARMER_PUBLIC_KEY_HEX); - let closed_store_sdk = crate::RadrootsSdk::builder() + let closed_store_sdk = crate::RadrootsClient::builder() .relay_url("wss://relay.example.com") .build() .await @@ -192,7 +192,7 @@ async fn enqueue_signed_workflow_reports_store_failures() { #[tokio::test] async fn enqueue_signed_workflow_reports_clock_failures() { - let sdk = crate::RadrootsSdk::builder() + let sdk = crate::RadrootsClient::builder() .clock(crate::RadrootsSdkClock::BeforeUnixEpoch) .relay_url("wss://relay.example.com") .build() @@ -216,7 +216,7 @@ async fn enqueue_signed_workflow_reports_clock_failures() { #[tokio::test] async fn enqueue_signed_workflow_rejects_publish_transport_targets_without_proxy_transport() { - let sdk = crate::RadrootsSdk::builder().build().await.expect("sdk"); + let sdk = crate::RadrootsClient::builder().build().await.expect("sdk"); let actor = RadrootsActorContext::test(FARMER_PUBLIC_KEY_HEX, [RadrootsActorRole::Farmer]) .expect("actor"); let draft = frozen_draft_for(FARMER_PUBLIC_KEY_HEX); diff --git a/packages/events-bindings/src/generated/types.ts b/packages/events-bindings/src/generated/types.ts @@ -19,19 +19,13 @@ export type JobPaymentRequest = { amount_sat: number, bolt11?: string | null, }; export type RadrootsAccountClaim = { username: string, pubkey: string, nip05?: string | null, }; -export type RadrootsAppData = { d_tag: string, content: string, }; - -export type RadrootsComment = { root: RadrootsNostrEventRef, parent: RadrootsNostrEventRef, content: string, }; - -export type RadrootsCommercialDomain = "trade:listing"; +export type RadrootsActiveTradeEnvelope<T> = { version: number, domain: RadrootsTradeDomain, type: RadrootsActiveTradeMessageType, order_id: string, listing_addr: string, payload: T, }; -export type RadrootsCommercialEnvelope<T> = { version: number, domain: RadrootsCommercialDomain, type: RadrootsCommercialMessageType, order_id?: string | null, listing_addr: string, payload: T, }; +export type RadrootsActiveTradeMessageType = "TradeOrderRequested" | "TradeOrderDecision" | "TradeOrderRevisionProposed" | "TradeOrderRevisionDecision" | "TradeOrderCancelled"; -export type RadrootsCommercialMessagePayload = { kind: "listing_validate_request", amount: RadrootsTradeListingValidateRequest, } | { kind: "listing_validate_result", amount: RadrootsTradeListingValidateResult, } | { kind: "trade_order_requested", amount: RadrootsOrderRequest, } | { kind: "order_response", amount: RadrootsOrderResponse, } | { kind: "order_revision", amount: RadrootsOrderRevision, } | { kind: "order_revision_accept", amount: RadrootsOrderRevisionResponse, } | { kind: "order_revision_decline", amount: RadrootsOrderRevisionResponse, } | { kind: "question", amount: RadrootsListingQuestion, } | { kind: "answer", amount: RadrootsListingAnswer, } | { kind: "discount_request", amount: RadrootsListingDiscountRequest, } | { kind: "discount_offer", amount: RadrootsListingDiscountOffer, } | { kind: "discount_accept", amount: RadrootsListingDiscountDecision, } | { kind: "discount_decline", amount: RadrootsListingDiscountDecision, } | { kind: "cancel", amount: RadrootsListingCancel, }; - -export type RadrootsCommercialMessageType = "listing_validate_request" | "listing_validate_result" | "order_request" | "order_response" | "order_revision" | "order_revision_accept" | "order_revision_decline" | "question" | "answer" | "discount_request" | "discount_offer" | "discount_accept" | "discount_decline" | "cancel"; +export type RadrootsAppData = { d_tag: string, content: string, }; -export type RadrootsCommercialTransportLane = "service" | "public"; +export type RadrootsComment = { root: RadrootsNostrEventRef, parent: RadrootsNostrEventRef, content: string, }; export type RadrootsCoop = { d_tag: string, name: string, about?: string | null, website?: string | null, picture?: string | null, banner?: string | null, location?: RadrootsCoopLocation | null, tags?: Array<string> | null, }; @@ -83,36 +77,22 @@ export type RadrootsListSet = { d_tag: string, content: string, entries: Array<R export type RadrootsListing = { d_tag: string, published_at?: number | null, farm: RadrootsFarmRef, product: RadrootsListingProduct, primary_bin_id: string, bins: Array<RadrootsListingBin>, resource_area?: RadrootsResourceAreaRef | null, plot?: RadrootsPlotRef | null, discounts?: Array<RadrootsCoreDiscount> | null, inventory_available?: RadrootsCoreDecimal | null, availability?: RadrootsListingAvailability | null, delivery_method?: RadrootsListingDeliveryMethod | null, location?: RadrootsListingPublicLocation | null, images?: Array<RadrootsListingImage> | null, }; -export type RadrootsListingAnswer = { question_id: string, }; - export type RadrootsListingAvailability = { kind: "window", amount: { start?: number | null, end?: number | null, }, } | { kind: "status", amount: { status: RadrootsListingStatus, }, }; export type RadrootsListingBin = { bin_id: string, quantity: RadrootsCoreQuantity, price_per_canonical_unit: RadrootsCoreQuantityPrice, display_amount?: RadrootsCoreDecimal | null, display_unit?: RadrootsCoreUnit | null, display_label?: string | null, display_price?: RadrootsCoreMoney | null, display_price_unit?: RadrootsCoreUnit | null, }; -export type RadrootsListingCancel = { reason?: string | null, }; - export type RadrootsListingDeliveryMethod = { kind: "pickup", } | { kind: "local_delivery", } | { kind: "shipping", } | { kind: "other", amount: { method: string, }, }; -export type RadrootsListingDiscountDecision = { kind: "accept", amount: { value: RadrootsCoreDiscountValue, }, } | { kind: "decline", amount: { reason?: string | null, }, }; - -export type RadrootsListingDiscountOffer = { discount_id: string, value: RadrootsCoreDiscountValue, }; - -export type RadrootsListingDiscountRequest = { discount_id: string, value: RadrootsCoreDiscountValue, }; - export type RadrootsListingImage = { url: string, size?: RadrootsListingImageSize | null, }; export type RadrootsListingImageSize = { w: number, h: number, }; -export type RadrootsListingParseError = { InvalidKind: number, } | { MissingTag: string, } | { InvalidTag: string, } | { InvalidNumber: string, } | "InvalidUnit" | "InvalidCurrency" | { InvalidJson: string, } | { InvalidDiscount: string, }; - export type RadrootsListingProduct = { key: string, title: string, category: string, summary?: string | null, process?: string | null, lot?: string | null, location?: string | null, profile?: string | null, year?: string | null, }; export type RadrootsListingProductTagKeys = readonly ["key", "title", "category", "summary", "process", "lot", "location", "profile", "year"]; export type RadrootsListingPublicLocation = { primary: string, city?: string | null, region?: string | null, country?: string | null, geohash: string, }; -export type RadrootsListingQuestion = { question_id: string, }; - export type RadrootsListingStatus = { kind: "active", } | { kind: "sold", } | { kind: "other", amount: { value: string, }, }; export type RadrootsMessage = { recipients: Array<RadrootsMessageRecipient>, content: string, reply_to?: RadrootsNostrEventPtr | null, subject?: string | null, }; @@ -129,84 +109,104 @@ export type RadrootsNostrEventPtr = { id: string, relays?: string | null, }; export type RadrootsNostrEventRef = { id: string, author: string, kind: number, d_tag?: string | null, relays?: Array<string> | null, }; -export type RadrootsOrderCancellation = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, reason: string, }; +export type RadrootsPlot = { d_tag: string, farm: RadrootsFarmRef, name: string, about?: string | null, location?: RadrootsPlotLocation | null, tags?: Array<string> | null, }; + +export type RadrootsPlotLocation = { primary?: string | null, city?: string | null, region?: string | null, country?: string | null, gcs: RadrootsGcsLocation, }; + +export type RadrootsPlotRef = { pubkey: string, d_tag: string, }; + +export type RadrootsPost = { content: string, }; + +export type RadrootsProfile = { name: string, display_name?: string | null, nip05?: string | null, about?: string | null, website?: string | null, picture?: string | null, banner?: string | null, lud06?: string | null, lud16?: string | null, bot?: string | null, }; + +export type RadrootsProfileType = "individual" | "farm" | "coop" | "any" | "radrootsd"; + +export type RadrootsReaction = { root: RadrootsNostrEventRef, content: string, }; + +export type RadrootsRelayDocument = { name?: string | null, description?: string | null, pubkey?: string | null, contact?: string | null, supported_nips?: Array<number> | null, software?: string | null, version?: string | null, }; -export type RadrootsOrderChange = { kind: "bin_count", amount: { item_index: number, bin_count: number, }, } | { kind: "item_add", amount: { item: RadrootsOrderItem, }, } | { kind: "item_remove", amount: { item_index: number, }, }; +export type RadrootsResourceArea = { d_tag: string, name: string, about?: string | null, location: RadrootsResourceAreaLocation, tags?: Array<string> | null, }; -export type RadrootsOrderDecision = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, decision: RadrootsOrderDecisionOutcome, }; +export type RadrootsResourceAreaLocation = { primary?: string | null, city?: string | null, region?: string | null, country?: string | null, gcs: RadrootsGcsLocation, }; -export type RadrootsOrderDecisionOutcome = { decision: "accepted", inventory_commitments: Array<RadrootsOrderInventoryCommitment>, } | { decision: "declined", reason: string, }; +export type RadrootsResourceAreaRef = { pubkey: string, d_tag: string, }; -export type RadrootsOrderEconomicActor = "buyer" | "seller"; +export type RadrootsResourceHarvestCap = { d_tag: string, resource_area: RadrootsResourceAreaRef, product: RadrootsResourceHarvestProduct, start: bigint, end: bigint, cap_quantity: RadrootsCoreQuantity, display_amount?: RadrootsCoreDecimal | null, display_unit?: RadrootsCoreUnit | null, display_label?: string | null, tags?: Array<string> | null, }; -export type RadrootsOrderEconomicEffect = "increase" | "decrease"; +export type RadrootsResourceHarvestProduct = { key: string, category?: string | null, }; -export type RadrootsOrderEconomicItem = { bin_id: string, bin_count: number, quantity_amount: RadrootsCoreDecimal, quantity_unit: RadrootsCoreUnit, unit_price_amount: RadrootsCoreDecimal, unit_price_currency: RadrootsCoreCurrency, line_subtotal: RadrootsCoreMoney, }; +export type RadrootsSeal = { content: string, }; -export type RadrootsOrderEconomicLine = { id: string, kind: RadrootsOrderEconomicLineKind, actor: RadrootsOrderEconomicActor, effect: RadrootsOrderEconomicEffect, amount: RadrootsCoreMoney, reason: string, }; +export type RadrootsTradeAnswer = { question_id: string, }; -export type RadrootsOrderEconomicLineKind = "listing_discount" | "basket_adjustment" | "revision_adjustment"; +export type RadrootsTradeDiscountDecision = { kind: "accept", amount: { value: RadrootsCoreDiscountValue, }, } | { kind: "decline", amount: { reason?: string | null, }, }; -export type RadrootsOrderEconomicTotals = { subtotal: RadrootsCoreMoney, discount_total: RadrootsCoreMoney, adjustment_total: RadrootsCoreMoney, total: RadrootsCoreMoney, }; +export type RadrootsTradeDiscountOffer = { discount_id: string, value: RadrootsCoreDiscountValue, }; -export type RadrootsOrderEconomics = { quote_id: string, quote_version: number, pricing_basis: RadrootsOrderPricingBasis, currency: RadrootsCoreCurrency, items: Array<RadrootsOrderEconomicItem>, discounts: Array<RadrootsOrderEconomicLine>, adjustments: Array<RadrootsOrderEconomicLine>, subtotal: RadrootsCoreMoney, discount_total: RadrootsCoreMoney, adjustment_total: RadrootsCoreMoney, total: RadrootsCoreMoney, }; +export type RadrootsTradeDiscountRequest = { discount_id: string, value: RadrootsCoreDiscountValue, }; -export type RadrootsOrderEnvelope<T> = { version: number, domain: RadrootsCommercialDomain, type: RadrootsOrderEventType, order_id: string, listing_addr: string, payload: T, }; +export type RadrootsTradeDomain = "trade:listing"; -export type RadrootsOrderEventType = "TradeOrderRequested" | "TradeOrderDecision" | "TradeOrderRevisionProposed" | "TradeOrderRevisionDecision" | "TradeOrderCancelled"; +export type RadrootsTradeEconomicActor = "buyer" | "seller"; -export type RadrootsOrderInventoryCommitment = { bin_id: string, bin_count: number, }; +export type RadrootsTradeEconomicEffect = "increase" | "decrease"; -export type RadrootsOrderItem = { bin_id: string, bin_count: number, }; +export type RadrootsTradeEconomicLineKind = "listing_discount" | "basket_adjustment" | "revision_adjustment"; -export type RadrootsOrderPricingBasis = "listing_event"; +export type RadrootsTradeEnvelope<T> = { version: number, domain: RadrootsTradeDomain, type: RadrootsTradeMessageType, order_id?: string | null, listing_addr: string, payload: T, }; -export type RadrootsOrderRequest = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, items: Array<RadrootsOrderItem>, economics: RadrootsOrderEconomics, }; +export type RadrootsTradeInventoryCommitment = { bin_id: string, bin_count: number, }; -export type RadrootsOrderResponse = { accepted: boolean, reason?: string | null, }; +export type RadrootsTradeListingCancel = { reason?: string | null, }; -export type RadrootsOrderRevision = { revision_id: string, changes: Array<RadrootsOrderChange>, }; +export type RadrootsTradeListingParseError = { InvalidKind: number, } | { MissingTag: string, } | { InvalidTag: string, } | { InvalidNumber: string, } | "InvalidUnit" | "InvalidCurrency" | { InvalidJson: string, } | { InvalidDiscount: string, }; -export type RadrootsOrderRevisionDecision = { decision: "accepted", } | { decision: "declined", reason: string, }; +export type RadrootsTradeListingValidateRequest = { listing_event?: RadrootsNostrEventPtr | null, }; -export type RadrootsOrderRevisionDecisionEvent = { revision_id: string, order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, root_event_id: string, prev_event_id: string, decision: RadrootsOrderRevisionDecision, }; +export type RadrootsTradeListingValidateResult = { valid: boolean, errors: Array<RadrootsTradeListingValidationError>, }; -export type RadrootsOrderRevisionProposed = { revision_id: string, order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, root_event_id: string, prev_event_id: string, items: Array<RadrootsOrderItem>, economics: RadrootsOrderEconomics, reason: string, }; +export type RadrootsTradeListingValidationError = { kind: "invalid_kind", amount: { kind: number, }, } | { kind: "missing_listing_id", } | { kind: "listing_event_not_found", amount: { listing_addr: string, }, } | { kind: "listing_event_fetch_failed", amount: { listing_addr: string, }, } | { kind: "parse_error", amount: { error: RadrootsTradeListingParseError, }, } | { kind: "invalid_seller", } | { kind: "missing_farm_profile", } | { kind: "missing_farm_record", } | { kind: "missing_title", } | { kind: "missing_description", } | { kind: "missing_product_type", } | { kind: "missing_bins", } | { kind: "missing_primary_bin", } | { kind: "invalid_bin", } | { kind: "missing_price", } | { kind: "invalid_price", } | { kind: "missing_inventory", } | { kind: "invalid_inventory", } | { kind: "missing_availability", } | { kind: "missing_location", } | { kind: "missing_delivery_method", }; -export type RadrootsOrderRevisionResponse = { accepted: boolean, reason?: string | null, }; +export type RadrootsTradeMessagePayload = { kind: "listing_validate_request", amount: RadrootsTradeListingValidateRequest, } | { kind: "listing_validate_result", amount: RadrootsTradeListingValidateResult, } | { kind: "trade_order_requested", amount: RadrootsTradeOrderRequested, } | { kind: "order_response", amount: RadrootsTradeOrderResponse, } | { kind: "order_revision", amount: RadrootsTradeOrderRevision, } | { kind: "order_revision_accept", amount: RadrootsTradeOrderRevisionResponse, } | { kind: "order_revision_decline", amount: RadrootsTradeOrderRevisionResponse, } | { kind: "question", amount: RadrootsTradeQuestion, } | { kind: "answer", amount: RadrootsTradeAnswer, } | { kind: "discount_request", amount: RadrootsTradeDiscountRequest, } | { kind: "discount_offer", amount: RadrootsTradeDiscountOffer, } | { kind: "discount_accept", amount: RadrootsTradeDiscountDecision, } | { kind: "discount_decline", amount: RadrootsTradeDiscountDecision, } | { kind: "cancel", amount: RadrootsTradeListingCancel, }; -export type RadrootsOrderStatus = "draft" | "validated" | "requested" | "questioned" | "revised" | "accepted" | "declined" | "cancelled"; +export type RadrootsTradeMessageType = "listing_validate_request" | "listing_validate_result" | "order_request" | "order_response" | "order_revision" | "order_revision_accept" | "order_revision_decline" | "question" | "answer" | "discount_request" | "discount_offer" | "discount_accept" | "discount_decline" | "cancel"; -export type RadrootsPlot = { d_tag: string, farm: RadrootsFarmRef, name: string, about?: string | null, location?: RadrootsPlotLocation | null, tags?: Array<string> | null, }; +export type RadrootsTradeOrderCancelled = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, reason: string, }; -export type RadrootsPlotLocation = { primary?: string | null, city?: string | null, region?: string | null, country?: string | null, gcs: RadrootsGcsLocation, }; +export type RadrootsTradeOrderChange = { kind: "bin_count", amount: { item_index: number, bin_count: number, }, } | { kind: "item_add", amount: { item: RadrootsTradeOrderItem, }, } | { kind: "item_remove", amount: { item_index: number, }, }; -export type RadrootsPlotRef = { pubkey: string, d_tag: string, }; +export type RadrootsTradeOrderDecision = { decision: "accepted", inventory_commitments: Array<RadrootsTradeInventoryCommitment>, } | { decision: "declined", reason: string, }; -export type RadrootsPost = { content: string, }; +export type RadrootsTradeOrderDecisionEvent = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, decision: RadrootsTradeOrderDecision, }; -export type RadrootsProfile = { name: string, display_name?: string | null, nip05?: string | null, about?: string | null, website?: string | null, picture?: string | null, banner?: string | null, lud06?: string | null, lud16?: string | null, bot?: string | null, }; +export type RadrootsTradeOrderEconomicItem = { bin_id: string, bin_count: number, quantity_amount: RadrootsCoreDecimal, quantity_unit: RadrootsCoreUnit, unit_price_amount: RadrootsCoreDecimal, unit_price_currency: RadrootsCoreCurrency, line_subtotal: RadrootsCoreMoney, }; -export type RadrootsProfileType = "individual" | "farm" | "coop" | "any" | "radrootsd"; +export type RadrootsTradeOrderEconomicLine = { id: string, kind: RadrootsTradeEconomicLineKind, actor: RadrootsTradeEconomicActor, effect: RadrootsTradeEconomicEffect, amount: RadrootsCoreMoney, reason: string, }; -export type RadrootsReaction = { root: RadrootsNostrEventRef, content: string, }; +export type RadrootsTradeOrderEconomicTotals = { subtotal: RadrootsCoreMoney, discount_total: RadrootsCoreMoney, adjustment_total: RadrootsCoreMoney, total: RadrootsCoreMoney, }; -export type RadrootsRelayDocument = { name?: string | null, description?: string | null, pubkey?: string | null, contact?: string | null, supported_nips?: Array<number> | null, software?: string | null, version?: string | null, }; +export type RadrootsTradeOrderEconomics = { quote_id: string, quote_version: number, pricing_basis: RadrootsTradePricingBasis, currency: RadrootsCoreCurrency, items: Array<RadrootsTradeOrderEconomicItem>, discounts: Array<RadrootsTradeOrderEconomicLine>, adjustments: Array<RadrootsTradeOrderEconomicLine>, subtotal: RadrootsCoreMoney, discount_total: RadrootsCoreMoney, adjustment_total: RadrootsCoreMoney, total: RadrootsCoreMoney, }; -export type RadrootsResourceArea = { d_tag: string, name: string, about?: string | null, location: RadrootsResourceAreaLocation, tags?: Array<string> | null, }; +export type RadrootsTradeOrderItem = { bin_id: string, bin_count: number, }; -export type RadrootsResourceAreaLocation = { primary?: string | null, city?: string | null, region?: string | null, country?: string | null, gcs: RadrootsGcsLocation, }; +export type RadrootsTradeOrderRequested = { order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, items: Array<RadrootsTradeOrderItem>, economics: RadrootsTradeOrderEconomics, }; -export type RadrootsResourceAreaRef = { pubkey: string, d_tag: string, }; +export type RadrootsTradeOrderResponse = { accepted: boolean, reason?: string | null, }; -export type RadrootsResourceHarvestCap = { d_tag: string, resource_area: RadrootsResourceAreaRef, product: RadrootsResourceHarvestProduct, start: bigint, end: bigint, cap_quantity: RadrootsCoreQuantity, display_amount?: RadrootsCoreDecimal | null, display_unit?: RadrootsCoreUnit | null, display_label?: string | null, tags?: Array<string> | null, }; +export type RadrootsTradeOrderRevision = { revision_id: string, changes: Array<RadrootsTradeOrderChange>, }; -export type RadrootsResourceHarvestProduct = { key: string, category?: string | null, }; +export type RadrootsTradeOrderRevisionDecision = { decision: "accepted", } | { decision: "declined", reason: string, }; -export type RadrootsSeal = { content: string, }; +export type RadrootsTradeOrderRevisionDecisionEvent = { revision_id: string, order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, root_event_id: string, prev_event_id: string, decision: RadrootsTradeOrderRevisionDecision, }; -export type RadrootsTradeListingValidateRequest = { listing_event?: RadrootsNostrEventPtr | null, }; +export type RadrootsTradeOrderRevisionProposed = { revision_id: string, order_id: string, listing_addr: string, buyer_pubkey: string, seller_pubkey: string, root_event_id: string, prev_event_id: string, items: Array<RadrootsTradeOrderItem>, economics: RadrootsTradeOrderEconomics, reason: string, }; -export type RadrootsTradeListingValidateResult = { valid: boolean, errors: Array<RadrootsTradeListingValidationError>, }; +export type RadrootsTradeOrderRevisionResponse = { accepted: boolean, reason?: string | null, }; + +export type RadrootsTradeOrderStatus = "draft" | "validated" | "requested" | "questioned" | "revised" | "accepted" | "declined" | "cancelled"; + +export type RadrootsTradePricingBasis = "listing_event"; + +export type RadrootsTradeQuestion = { question_id: string, }; -export type RadrootsTradeListingValidationError = { kind: "invalid_kind", amount: { kind: number, }, } | { kind: "missing_listing_id", } | { kind: "listing_event_not_found", amount: { listing_addr: string, }, } | { kind: "listing_event_fetch_failed", amount: { listing_addr: string, }, } | { kind: "parse_error", amount: { error: RadrootsListingParseError, }, } | { kind: "invalid_seller", } | { kind: "missing_farm_profile", } | { kind: "missing_farm_record", } | { kind: "missing_title", } | { kind: "missing_description", } | { kind: "missing_product_type", } | { kind: "missing_bins", } | { kind: "missing_primary_bin", } | { kind: "invalid_bin", } | { kind: "missing_price", } | { kind: "invalid_price", } | { kind: "missing_inventory", } | { kind: "invalid_inventory", } | { kind: "missing_availability", } | { kind: "missing_location", } | { kind: "missing_delivery_method", }; +export type RadrootsTradeTransportLane = "service" | "public";