Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/rs-sdk-ffi/src/data_contract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
//! - `dash_sdk_data_contract_destroy` — destructor for handles
//! produced by the query layer.
//! - The query function re-exports from `queries::*`.
//! - The `propertyConstraints` rules of a document type, and the
//! pre-check of a document against them (`property_constraints`).

mod property_constraints;
mod put;
mod queries;
mod util;
Expand Down Expand Up @@ -55,6 +58,11 @@ pub unsafe extern "C" fn dash_sdk_data_contract_destroy(handle: *mut DataContrac
}
}

pub use property_constraints::{
dash_sdk_data_contract_check_property_constraints,
dash_sdk_data_contract_get_property_constraints,
};

// Re-export query functions
pub use queries::{
dash_sdk_data_contract_fetch, dash_sdk_data_contract_fetch_history,
Expand Down
852 changes: 852 additions & 0 deletions packages/rs-sdk-ffi/src/data_contract/property_constraints.rs

Large diffs are not rendered by default.

47 changes: 13 additions & 34 deletions packages/rs-sdk-ffi/src/document/create.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Document creation operations

use crate::document::helpers::{build_document_from_properties, parse_document_properties_json};
use crate::sdk::SDKWrapper;
use crate::types::{DashSDKResultDataType, DocumentHandle, SDKHandle};
use crate::{DashSDKError, DashSDKErrorCode, DashSDKResult, FFIError};
Expand Down Expand Up @@ -110,25 +111,9 @@ pub unsafe extern "C" fn dash_sdk_document_create(
};

// Parse properties JSON
let properties_value: serde_json::Value = match serde_json::from_str(properties_str) {
Ok(v) => v,
Err(e) => {
return DashSDKResult::error(DashSDKError::new(
DashSDKErrorCode::InvalidParameter,
format!("Invalid properties JSON: {}", e),
))
}
};

// Convert JSON to platform Value - handle hex strings for byte arrays
let mut properties = match serde_json::from_value::<BTreeMap<String, Value>>(properties_value) {
Ok(map) => map,
Err(e) => {
return DashSDKResult::error(DashSDKError::new(
DashSDKErrorCode::InvalidParameter,
format!("Failed to convert properties: {}", e),
))
}
let properties = match parse_document_properties_json(properties_str) {
Ok(properties) => properties,
Err(error) => return DashSDKResult::error(error),
};

let result: Result<(Document, [u8; 32]), FFIError> = wrapper.runtime.block_on(async {
Expand Down Expand Up @@ -173,21 +158,15 @@ pub unsafe extern "C" fn dash_sdk_document_create(
.map_err(|e| FFIError::InternalError(format!("Failed to get document type: {}", e)))?;

// Sanitize document properties (convert hex/base64 to bytes, base58 to identifiers, etc.)
use dash_sdk::dpp::data_contract::document_type::methods::DocumentTypeV0Methods;
document_type_ref.sanitize_document_properties(&mut properties);
eprintln!("📝 [DOCUMENT CREATE] Sanitized document properties");

// Create document with entropy - this will generate the document ID internally
let document = document_type_ref
.create_document_from_data(
properties.into(),
owner_id,
0, // block_height - will be set by platform
0, // core_block_height - will be set by platform
entropy,
platform_version,
)
.map_err(|e| FFIError::InternalError(format!("Failed to create document: {}", e)))?;
// and create the document with entropy - this will generate the document ID internally
let document = build_document_from_properties(
document_type_ref.as_ref(),
properties,
owner_id,
entropy,
platform_version,
)
.map_err(|e| FFIError::InternalError(format!("Failed to create document: {}", e)))?;

Ok((document, entropy))
});
Expand Down
62 changes: 61 additions & 1 deletion packages/rs-sdk-ffi/src/document/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,76 @@
//! Helper functions for document operations

use std::collections::BTreeMap;

use dash_sdk::dpp::data_contract::document_type::methods::DocumentTypeV0Methods;
use dash_sdk::dpp::data_contract::document_type::DocumentTypeRef;
use dash_sdk::dpp::document::Document;
use dash_sdk::dpp::platform_value::Value;
use dash_sdk::dpp::prelude::Identifier;
use dash_sdk::dpp::state_transition::batch_transition::methods::StateTransitionCreationOptions;
use dash_sdk::dpp::state_transition::StateTransitionSigningOptions;
use dash_sdk::dpp::tokens::gas_fees_paid_by::GasFeesPaidBy;
use dash_sdk::dpp::tokens::token_payment_info::v0::TokenPaymentInfoV0;
use dash_sdk::dpp::tokens::token_payment_info::TokenPaymentInfo;
use dash_sdk::dpp::version::PlatformVersion;
use dash_sdk::dpp::ProtocolError;

use crate::types::{
DashSDKGasFeesPaidBy, DashSDKStateTransitionCreationOptions, DashSDKTokenPaymentInfo,
};
use crate::FFIError;
use crate::{DashSDKError, DashSDKErrorCode, FFIError};

/// Parse the properties JSON of a document to create, as `dash_sdk_document_create`
/// takes it: a JSON object keyed by property name, each value read into a platform
/// `Value` as JSON writes it (integers, booleans, strings, arrays and objects). Byte
/// arrays and identifiers are still the strings the caller wrote here;
/// [`build_document_from_properties`] decodes them against the document type.
///
/// Errors carry `InvalidParameter`: the text is not JSON, or not an object.
pub(crate) fn parse_document_properties_json(
properties_json: &str,
) -> Result<BTreeMap<String, Value>, DashSDKError> {
let properties_value: serde_json::Value =
serde_json::from_str(properties_json).map_err(|e| {
DashSDKError::new(
DashSDKErrorCode::InvalidParameter,
format!("Invalid properties JSON: {}", e),
)
})?;

// Convert JSON to platform Value - handle hex strings for byte arrays
serde_json::from_value::<BTreeMap<String, Value>>(properties_value).map_err(|e| {
DashSDKError::new(
DashSDKErrorCode::InvalidParameter,
format!("Failed to convert properties: {}", e),
)
})
}

/// Build the document `dash_sdk_document_create` creates from `properties`: they are
/// sanitized against `document_type` (hex or base64 strings become byte arrays, base58
/// or hex strings identifiers, integers narrow to their declared width, typed array
/// elements included), then `DocumentType::create_document_from_data` builds the
/// revision-1 document owned by `owner_id`, its id derived from `entropy`, typing the
/// value at each of the document type's identifier paths as an identifier. Block
/// heights are left at 0 for Platform to set.
pub(crate) fn build_document_from_properties(
document_type: DocumentTypeRef<'_>,
mut properties: BTreeMap<String, Value>,
owner_id: Identifier,
entropy: [u8; 32],
platform_version: &PlatformVersion,
) -> Result<Document, ProtocolError> {
document_type.sanitize_document_properties(&mut properties);
document_type.create_document_from_data(
properties.into(),
owner_id,
0, // block_height - will be set by platform
0, // core_block_height - will be set by platform
entropy,
platform_version,
)
}

/// Convert FFI GasFeesPaidBy to Rust enum
///
Expand Down
1 change: 1 addition & 0 deletions packages/rs-sdk-ffi/src/document/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub use transfer::{
pub use util::{dash_sdk_document_destroy, dash_sdk_document_handle_destroy};

// Re-export helper functions for use by submodules
pub(crate) use helpers::{build_document_from_properties, parse_document_properties_json};
pub use helpers::{
convert_gas_fees_paid_by, convert_state_transition_creation_options, convert_token_payment_info,
};
Loading
Loading