diff --git a/native/cpp/CommonCpp/BlobClient/BlobClient.h b/native/cpp/CommonCpp/BlobClient/BlobClient.h
--- a/native/cpp/CommonCpp/BlobClient/BlobClient.h
+++ b/native/cpp/CommonCpp/BlobClient/BlobClient.h
@@ -2,6 +2,8 @@
 
 #include <memory>
 #include <string>
+#include <tuple>
+#include <vector>
 
 namespace comm {
 class UploadBlobClient {
@@ -14,4 +16,12 @@
   bool completeUploadBlocking();
   ~UploadBlobClient();
 };
+
+class DownloadBlobClient {
+  std::unique_ptr<::rust::Box<::DownloadState>> downloadState;
+
+public:
+  DownloadBlobClient(const std::string &holder);
+  std::tuple<bool, std::vector<std::uint8_t>> pullChunkBlocking();
+};
 } // namespace comm
diff --git a/native/cpp/CommonCpp/BlobClient/BlobClient.cpp b/native/cpp/CommonCpp/BlobClient/BlobClient.cpp
--- a/native/cpp/CommonCpp/BlobClient/BlobClient.cpp
+++ b/native/cpp/CommonCpp/BlobClient/BlobClient.cpp
@@ -29,4 +29,20 @@
     ::complete_upload_blocking(std::move(*this->uploadState.release()));
   }
 }
+
+DownloadBlobClient::DownloadBlobClient(const std::string &holder) {
+  this->downloadState = std::make_unique<::rust::Box<::DownloadState>>(
+      ::initialize_download_state_blocking(holder));
+}
+
+std::tuple<bool, std::vector<std::uint8_t>>
+DownloadBlobClient::pullChunkBlocking() {
+  auto blob_chunk_response = ::pull_chunk_blocking(*this->downloadState);
+  if (blob_chunk_response.stream_end) {
+    return {true, {}};
+  }
+  auto data = blob_chunk_response.data;
+  std::vector<std::uint8_t> buffer(data.data(), data.data() + data.size());
+  return {false, buffer};
+}
 } // namespace comm