sdk

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

commit c2e9bcc528248d541365978c3668ed2167062d8f
parent 5a8c47f2a43bed9e0d8e41cc9787287b8f9944f9
Author: triesap <tyson@radroots.org>
Date:   Thu, 30 Jul 2026 07:52:06 +0000

sdk: adopt organized trade surface

- consume trade state evidence and reducer types from final modules
- replace direct projection reads with invariant-preserving accessors
- build reduction inputs and evidence through validated constructors
- remove legacy workflow imports from SDK crate sources and tests

Diffstat:
Mcrates/sdk/src/private_store.rs | 17++++++++---------
Mcrates/sdk/src/sync_runtime.rs | 4+---
Mcrates/sdk/src/trade_runtime.rs | 96+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mcrates/sdk/tests/unit/trade_runtime_tests.rs | 6++----
4 files changed, 63 insertions(+), 60 deletions(-)

diff --git a/crates/sdk/src/private_store.rs b/crates/sdk/src/private_store.rs @@ -6,9 +6,8 @@ use radroots_event::id::{AddressableCoordinate, AddressableCoordinateParts}; use radroots_event::trade::RADROOTS_TRADE_MAX_PRIVATE_ARTIFACT_BYTES; use radroots_protected_store::{RadrootsProtectedFileKeySource, RadrootsProtectedStoreEnvelope}; use radroots_secret_vault::{RadrootsSecretKeyWrapping, RadrootsSecretVaultAccessError}; -use radroots_trade::workflow::{ - RadrootsTradePrivateTermsEvidenceV1, RadrootsTradePrivateTermsStateV1, -}; +use radroots_trade::evidence::RadrootsTradePrivateTermsEvidenceV1; +use radroots_trade::model::RadrootsTradePrivateTermsStateV1; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; @@ -594,14 +593,14 @@ impl SdkPrivateStore { } } }; - Ok(RadrootsTradePrivateTermsEvidenceV1 { - candidate_id: candidate_id.parse().map_err(|error| { - RadrootsSdkError::InvalidRequest { + Ok(RadrootsTradePrivateTermsEvidenceV1::new( + candidate_id + .parse() + .map_err(|error| RadrootsSdkError::InvalidRequest { message: format!("private terms candidate id is invalid: {error}"), - } - })?, + })?, state, - }) + )) } async fn configure_connection(&self, file_backed: bool) -> Result<(), RadrootsSdkError> { diff --git a/crates/sdk/src/sync_runtime.rs b/crates/sdk/src/sync_runtime.rs @@ -32,9 +32,7 @@ use radroots_protocol::radrootsd::transport_publish::v5::{ TargetOutcome as TransportPublishTargetOutcome, TargetPolicy as TransportPublishTargetPolicy, }; #[cfg(feature = "runtime")] -use radroots_trade::workflow::{ - RADROOTS_TRADE_REDUCER_CONTRACT_ID, RADROOTS_TRADE_REDUCER_VERSION, -}; +use radroots_trade::reducer::{RADROOTS_TRADE_REDUCER_CONTRACT_ID, RADROOTS_TRADE_REDUCER_VERSION}; #[cfg(all(feature = "runtime", feature = "radrootsd-execution"))] use radroots_transport::RadrootsTransportTargetFingerprint; #[cfg(feature = "runtime")] diff --git a/crates/sdk/src/trade_runtime.rs b/crates/sdk/src/trade_runtime.rs @@ -33,13 +33,20 @@ use radroots_event_codec::encode::trade::trade_mutation_event_build; #[cfg(feature = "runtime")] use radroots_event_store::{RadrootsStoredTradeMutation, RadrootsTradeProjectionCheckpoint}; #[cfg(feature = "runtime")] -use radroots_trade::workflow::{ - RADROOTS_TRADE_REDUCER_CONTRACT_ID, RADROOTS_TRADE_REDUCER_VERSION, +use radroots_trade::evidence::{ + RadrootsTradeEvidenceStateV1, RadrootsTradeMutationRecordV1, + RadrootsTradePrivateTermsEvidenceV1, +}; +#[cfg(feature = "runtime")] +use radroots_trade::model::{ RadrootsTradeAgreementStateV1, RadrootsTradeAttestationStateV1, RadrootsTradeConflictStateV1, - RadrootsTradeEvidenceStateV1, RadrootsTradeFulfillmentStateV1, RadrootsTradeMutationRecordV1, - RadrootsTradeNegotiationStateV1, RadrootsTradePaymentStateV1, - RadrootsTradePrivateTermsEvidenceV1, RadrootsTradePrivateTermsStateV1, - RadrootsTradeProjectionV1, RadrootsTradeReductionInputV1, reduce_trade_records, + RadrootsTradeFulfillmentStateV1, RadrootsTradeNegotiationStateV1, RadrootsTradePaymentStateV1, + RadrootsTradePrivateTermsStateV1, RadrootsTradeProjectionV1, +}; +#[cfg(feature = "runtime")] +use radroots_trade::reducer::{ + RADROOTS_TRADE_REDUCER_CONTRACT_ID, RADROOTS_TRADE_REDUCER_VERSION, + RadrootsTradeReductionInputV1, reduce_trade_records, }; #[cfg(feature = "runtime")] use serde::{Deserialize, Serialize}; @@ -219,16 +226,16 @@ impl<'client> TradeQueryService<'client> { trade_id: view.trade_id, reducer_contract_id: RADROOTS_TRADE_REDUCER_CONTRACT_ID.to_owned(), reducer_version: RADROOTS_TRADE_REDUCER_VERSION, - projection_digest: view.projection.projection_digest.clone(), - root_mutation_id: view.projection.root_mutation_id, - negotiation_state: enum_label(&view.projection.negotiation_state)?, - agreement_state: enum_label(&view.projection.agreement_state)?, - evidence_state: enum_label(&view.projection.evidence_state)?, - conflict_state: enum_label(&view.projection.conflict_state)?, - private_terms_state: enum_label(&view.projection.private_terms_state)?, - attestation_state: enum_label(&view.projection.attestation_state)?, - fulfillment_state: enum_label(&view.projection.fulfillment_state)?, - payment_state: enum_label(&view.projection.payment_state)?, + projection_digest: view.projection.projection_digest().to_owned(), + root_mutation_id: view.projection.root_mutation_id().copied(), + negotiation_state: enum_label(&view.projection.negotiation_state())?, + agreement_state: enum_label(&view.projection.agreement_state())?, + evidence_state: enum_label(&view.projection.evidence_state())?, + conflict_state: enum_label(&view.projection.conflict_state())?, + private_terms_state: enum_label(&view.projection.private_terms_state())?, + attestation_state: enum_label(&view.projection.attestation_state())?, + fulfillment_state: enum_label(&view.projection.fulfillment_state())?, + payment_state: enum_label(&view.projection.payment_state())?, projection_json: serde_json::to_string(&view.projection) .map_err(trade_query_store_error)?, last_mutation_id: last.mutation_id, @@ -243,8 +250,8 @@ impl<'client> TradeQueryService<'client> { api_version: 1, trade_id: view.trade_id, evidence_count: view.private_terms.len(), - projection_digest: view.projection.projection_digest, - projection_state: view.projection.private_terms_state, + projection_digest: view.projection.projection_digest().to_owned(), + projection_state: view.projection.private_terms_state(), }) } @@ -1456,7 +1463,7 @@ async fn ensure_private_terms_ref_available( private_ref.ciphertext_commitment.as_str(), ) .await?; - match evidence.state { + match evidence.state() { RadrootsTradePrivateTermsStateV1::AvailableVerified => Ok(()), RadrootsTradePrivateTermsStateV1::CommitmentMismatch => Err(trade_command_error( RadrootsSdkTradeErrorKind::PrivateArtifactCommitmentMismatch, @@ -1600,14 +1607,15 @@ async fn trade_projection_for_trade( "trade is not present in the local event store", )); } - let mut input = RadrootsTradeReductionInputV1::new(*trade_id); - input.mutations = stored + let mutations = stored .iter() .map(stored_trade_mutation_record) .collect::<Result<Vec<_>, _>>()?; - input.private_terms = - private_terms_evidence_for_mutations(sdk, trade_id, &input.mutations).await?; - input.observed_at_unix_s = Some(sdk.now()?.unix_seconds()); + let private_terms = private_terms_evidence_for_mutations(sdk, trade_id, &mutations).await?; + let input = RadrootsTradeReductionInputV1::new(*trade_id) + .with_mutations(mutations) + .with_private_terms(private_terms) + .with_observed_at_unix_s(Some(sdk.now()?.unix_seconds())); Ok(reduce_trade_records(input)) } @@ -1627,11 +1635,11 @@ async fn private_terms_views_for_trade( let evidence = private_terms_evidence_for_mutations(sdk, trade_id, &records).await?; let mut evidence_by_candidate = evidence .into_iter() - .map(|item| (item.candidate_id, item.state)) + .map(|item| (*item.candidate_id(), item.state())) .collect::<BTreeMap<_, _>>(); let mut views = BTreeMap::<CandidateId, TradePrivateTermsAvailabilityView>::new(); for record in records { - if let Some((candidate_id, private_ref)) = candidate_private_ref(&record.mutation) { + if let Some((candidate_id, private_ref)) = candidate_private_ref(record.mutation()) { let state = evidence_by_candidate .remove(&candidate_id) .unwrap_or(RadrootsTradePrivateTermsStateV1::Missing); @@ -1660,7 +1668,7 @@ async fn private_terms_evidence_for_mutations( let mut seen = BTreeSet::new(); let trade_id_hex = trade_id.to_hex(); for record in mutations { - if let Some((candidate_id, private_ref)) = candidate_private_ref(&record.mutation) { + if let Some((candidate_id, private_ref)) = candidate_private_ref(record.mutation()) { if !seen.insert(candidate_id) { continue; } @@ -1700,10 +1708,10 @@ fn candidate_private_ref( fn stored_trade_mutation_record( stored: &RadrootsStoredTradeMutation, ) -> Result<RadrootsTradeMutationRecordV1, RadrootsSdkError> { - Ok(RadrootsTradeMutationRecordV1 { - transport_event_id: Some(stored.first_transport_event_id), - mutation: stored_trade_envelope(stored)?, - }) + Ok(RadrootsTradeMutationRecordV1::new( + Some(stored.first_transport_event_id), + stored_trade_envelope(stored)?, + )) } #[cfg(feature = "runtime")] @@ -1742,19 +1750,19 @@ async fn list_trade_views( let view = trade_status_view(sdk, &row.trade_id).await?; items.push(TradeSummaryView { trade_id: view.trade_id, - root_mutation_id: view.projection.root_mutation_id, - buyer_pubkey: view.projection.buyer_pubkey.map(|value| value.to_string()), - seller_pubkey: view.projection.seller_pubkey.map(|value| value.to_string()), - farm_id: view.projection.farm_id.map(|value| value.to_string()), - negotiation_state: view.projection.negotiation_state, - agreement_state: view.projection.agreement_state, - evidence_state: view.projection.evidence_state, - conflict_state: view.projection.conflict_state, - private_terms_state: view.projection.private_terms_state, - attestation_state: view.projection.attestation_state, - fulfillment_state: view.projection.fulfillment_state, - payment_state: view.projection.payment_state, - projection_digest: view.projection.projection_digest, + root_mutation_id: view.projection.root_mutation_id().copied(), + buyer_pubkey: view.projection.buyer_pubkey().map(ToString::to_string), + seller_pubkey: view.projection.seller_pubkey().map(ToString::to_string), + farm_id: view.projection.farm_id().map(ToString::to_string), + negotiation_state: view.projection.negotiation_state(), + agreement_state: view.projection.agreement_state(), + evidence_state: view.projection.evidence_state(), + conflict_state: view.projection.conflict_state(), + private_terms_state: view.projection.private_terms_state(), + attestation_state: view.projection.attestation_state(), + fulfillment_state: view.projection.fulfillment_state(), + payment_state: view.projection.payment_state(), + projection_digest: view.projection.projection_digest().to_owned(), source_event_count: view.source_event_count, updated_event_seq: row.updated_event_seq, }); diff --git a/crates/sdk/tests/unit/trade_runtime_tests.rs b/crates/sdk/tests/unit/trade_runtime_tests.rs @@ -20,10 +20,8 @@ use radroots_event::{ }; use radroots_identity::PublicKey; use radroots_nostr::prelude::RadrootsNostrKeys; -use radroots_trade::workflow::{ - RADROOTS_TRADE_REDUCER_CONTRACT_ID, RADROOTS_TRADE_REDUCER_VERSION, - RadrootsTradePrivateTermsStateV1, -}; +use radroots_trade::model::RadrootsTradePrivateTermsStateV1; +use radroots_trade::reducer::{RADROOTS_TRADE_REDUCER_CONTRACT_ID, RADROOTS_TRADE_REDUCER_VERSION}; fn pubkey(value: &str) -> PublicKey { PublicKey::from_hex(value).expect("pubkey")