-
Notifications
You must be signed in to change notification settings - Fork 57
feat(swift-sdk): add production create-document flow via platform-wallet FFI #3908
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
f647d58
92a5ce4
ae6ec62
a469074
ac0a4f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| //! FFI bindings for document create operations on `IdentityWallet`. | ||
|
|
||
| use std::ffi::CStr; | ||
| use std::os::raw::c_char; | ||
| use std::slice; | ||
|
|
||
| use dpp::document::DocumentV0Getters; | ||
| use dpp::prelude::Identifier; | ||
| use rs_sdk_ffi::{SignerHandle, VTableSigner}; | ||
|
|
||
| use crate::check_ptr; | ||
| use crate::error::*; | ||
| use crate::handle::*; | ||
| use crate::runtime::block_on_worker; | ||
| use crate::types::read_identifier; | ||
| use crate::{unwrap_option_or_return, unwrap_result_or_return}; | ||
|
|
||
| /// Create + broadcast a new document on `contract_id`'s | ||
| /// `document_type_name`, owned by `owner_identity_id`, signed via the | ||
| /// external `signer_handle`. | ||
| /// | ||
| /// Goes through `IdentityWallet::create_document_with_signer`, which | ||
| /// fetches the on-chain contract, builds a revision-1 document from the | ||
| /// supplied `properties_json`, selects an AUTHENTICATION + ECDSA key | ||
| /// from the in-process `IdentityManager` whose security level satisfies | ||
| /// the document type's requirement, broadcasts on the platform-wallet | ||
| /// 8 MB worker stack (required to avoid the GroveDB proof-verification | ||
| /// stack overflow), and waits for the confirmed document. | ||
| /// | ||
| /// On success the confirmed document's 32-byte id is written to | ||
| /// `out_document_id`. The signature never crosses into Swift logic — | ||
| /// it routes back through the supplied `signer_handle` (typically | ||
| /// `KeychainSigner.handle`); the caller retains ownership of the | ||
| /// signer. | ||
| /// | ||
| /// `properties_json` is a NUL-terminated UTF-8 JSON object keyed by | ||
| /// property name. Byte-array fields are passed as hex (or base64) | ||
| /// strings and identifier fields as base58 (or hex) strings; the | ||
| /// schema-driven sanitize step on the Rust side converts them to the | ||
| /// protocol's native types. Pass `"{}"` for a document type with no | ||
| /// required properties. | ||
| #[no_mangle] | ||
| pub unsafe extern "C" fn platform_wallet_create_document_with_signer( | ||
| wallet_handle: Handle, | ||
| owner_identity_id: *const u8, | ||
| contract_id: *const u8, | ||
| document_type_name: *const c_char, | ||
| properties_json: *const c_char, | ||
| signer_handle: *mut SignerHandle, | ||
| out_document_id: *mut u8, | ||
| ) -> PlatformWalletFFIResult { | ||
| check_ptr!(signer_handle); | ||
| check_ptr!(document_type_name); | ||
| check_ptr!(properties_json); | ||
| check_ptr!(out_document_id); | ||
|
|
||
| let owner_id = unwrap_result_or_return!(read_identifier(owner_identity_id)); | ||
| let contract_id_value = unwrap_result_or_return!(read_identifier(contract_id)); | ||
|
|
||
| let document_type_str = | ||
| unwrap_result_or_return!(CStr::from_ptr(document_type_name).to_str()).to_string(); | ||
| let properties_str = unwrap_result_or_return!(CStr::from_ptr(properties_json).to_str()); | ||
|
|
||
| let signer_addr = signer_handle as usize; | ||
| let owner_id_for_async = owner_id; | ||
| let contract_id_for_async = contract_id_value; | ||
|
|
||
| let option = PLATFORM_WALLET_STORAGE.with_item(wallet_handle, |wallet| { | ||
| let identity_wallet = wallet.identity().clone(); | ||
| let result: Result<Identifier, _> = block_on_worker(async move { | ||
| let signer: &VTableSigner = &*(signer_addr as *const VTableSigner); | ||
| identity_wallet | ||
| .create_document_with_signer( | ||
| &owner_id_for_async, | ||
| &contract_id_for_async, | ||
| &document_type_str, | ||
| properties_str, | ||
| signer, | ||
| ) | ||
| .await | ||
| .map(|document| document.id()) | ||
| }); | ||
| result | ||
| }); | ||
| let result = unwrap_option_or_return!(option); | ||
| let document_id = unwrap_result_or_return!(result); | ||
| let bytes = document_id.to_buffer(); | ||
| let dst = slice::from_raw_parts_mut(out_document_id, 32); | ||
| dst.copy_from_slice(&bytes); | ||
| PlatformWalletFFIResult::ok() | ||
|
Comment on lines
+130
to
+145
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💬 Nitpick: Successful broadcast is reported as an error if By the time source: ['claude'] |
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.