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
81 changes: 50 additions & 31 deletions ffi/rust/ant-ffi/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,10 @@ impl Client {

// ===== File Operations =====

/// Upload a file from disk (public). Returns the address.
/// Upload a file from disk (public). The serialized data map is stored as
/// part of the same upload payment batch — one payment covers the file's
/// chunks and the data-map chunk. Returns the shareable address plus
/// chunk/cost details.
pub async fn file_upload_public(
&self,
path: String,
Expand All @@ -606,13 +609,12 @@ impl Client {
.map_err(|e| ClientError::InvalidInput { reason: e })?;
let file_path = PathBuf::from(&path);

let result = self.inner.file_upload_with_mode(&file_path, mode).await?;

let address = self.inner.data_map_store(&result.data_map).await?;
let result = self
.inner
.file_upload_public_with_mode(&file_path, mode)
.await?;

Ok(FilePutPublicResult {
address: hex::encode(address),
})
Self::to_file_put_public_result(result)
}

/// Same as [`Self::file_upload_public`] but reports live progress to
Expand All @@ -634,20 +636,14 @@ impl Client {
let (sender, handle) = upload_progress_bridge(listener);
let result = self
.inner
.file_upload_with_progress(&file_path, mode, Some(sender))
.file_upload_public_with_progress(&file_path, mode, Some(sender))
.await;
// Drop of `sender` inside the call ends the bridge; await it to flush
// any queued progress events before returning either way.
let _ = handle.await;
let result = result?;

// The data-map chunk is small and stored separately (no progress),
// matching `file_upload_public`.
let address = self.inner.data_map_store(&result.data_map).await?;

Ok(FilePutPublicResult {
address: hex::encode(address),
})
Self::to_file_put_public_result(result)
}

/// Upload a file from disk privately. Returns the serialized data map (hex)
Expand All @@ -665,14 +661,7 @@ impl Client {

let result = self.inner.file_upload_with_mode(&file_path, mode).await?;

let data_map_bytes =
rmp_serde::to_vec(&result.data_map).map_err(|e| ClientError::InternalError {
reason: format!("failed to serialize data map: {e}"),
})?;

Ok(FilePutPrivateResult {
data_map: hex::encode(data_map_bytes),
})
Self::to_file_put_private_result(result)
}

/// Same as [`Self::file_upload_private`] but reports live progress to
Expand All @@ -696,14 +685,7 @@ impl Client {
let _ = handle.await;
let result = result?;

let data_map_bytes =
rmp_serde::to_vec(&result.data_map).map_err(|e| ClientError::InternalError {
reason: format!("failed to serialize data map: {e}"),
})?;

Ok(FilePutPrivateResult {
data_map: hex::encode(data_map_bytes),
})
Self::to_file_put_private_result(result)
}

/// Publish an existing private data map as a public network chunk, returning
Expand Down Expand Up @@ -1215,6 +1197,43 @@ impl Client {
.expect("session entry present while holding the lock"))
}

/// Convert ant-core's [`FileUploadResult`] into the FFI
/// [`FilePutPublicResult`]. Public uploads always carry a data-map address.
fn to_file_put_public_result(
result: FileUploadResult,
) -> Result<FilePutPublicResult, ClientError> {
let address = result
.data_map_address
.ok_or_else(|| ClientError::InternalError {
reason: "public upload returned no data-map address".into(),
})?;
Ok(FilePutPublicResult {
address: hex::encode(address),
chunks_stored: result.chunks_stored as u64,
storage_cost_atto: result.storage_cost_atto,
gas_cost_wei: result.gas_cost_wei.to_string(),
payment_mode_used: format_payment_mode(result.payment_mode_used),
})
}

/// Convert ant-core's [`FileUploadResult`] into the FFI
/// [`FilePutPrivateResult`] (serializes the data map for the caller).
fn to_file_put_private_result(
result: FileUploadResult,
) -> Result<FilePutPrivateResult, ClientError> {
let data_map_bytes =
rmp_serde::to_vec(&result.data_map).map_err(|e| ClientError::InternalError {
reason: format!("failed to serialize data map: {e}"),
})?;
Ok(FilePutPrivateResult {
data_map: hex::encode(data_map_bytes),
chunks_stored: result.chunks_stored as u64,
storage_cost_atto: result.storage_cost_atto,
gas_cost_wei: result.gas_cost_wei.to_string(),
payment_mode_used: format_payment_mode(result.payment_mode_used),
})
}

/// Convert ant-core's [`FileUploadResult`] into the FFI [`ExternalUploadResult`].
fn to_external_result(result: FileUploadResult) -> Result<ExternalUploadResult, ClientError> {
let data_map_bytes =
Expand Down
16 changes: 16 additions & 0 deletions ffi/rust/ant-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ pub struct DataPutPrivateResult {
pub struct FilePutPublicResult {
/// Hex-encoded address of the stored data map.
pub address: String,
/// Number of chunks stored on the network.
pub chunks_stored: u64,
/// Total storage cost paid, in atto-tokens (base-10). "0" if all pre-existed.
pub storage_cost_atto: String,
/// Total gas cost in wei (base-10).
pub gas_cost_wei: String,
/// Payment mode that was used: "auto", "merkle", or "single".
pub payment_mode_used: String,
}

/// Result of uploading a file (private). The data map is returned to the
Expand All @@ -54,6 +62,14 @@ pub struct FilePutPublicResult {
pub struct FilePutPrivateResult {
/// Hex-encoded serialized data map (caller keeps this secret).
pub data_map: String,
/// Number of chunks stored on the network.
pub chunks_stored: u64,
/// Total storage cost paid, in atto-tokens (base-10). "0" if all pre-existed.
pub storage_cost_atto: String,
/// Total gas cost in wei (base-10).
pub gas_cost_wei: String,
/// Payment mode that was used: "auto", "merkle", or "single".
pub payment_mode_used: String,
}

/// Estimated cost of uploading a file, produced *before* any payment by
Expand Down
Loading