diff --git a/lib/ops/dm-operations-store-ops.js b/lib/ops/dm-operations-store-ops.js
new file mode 100644
--- /dev/null
+++ b/lib/ops/dm-operations-store-ops.js
@@ -0,0 +1,46 @@
+// @flow
+
+import type { DMOperation } from '../types/dm-ops.js';
+
+type Operation = {
+  +id: string,
+  +type: string,
+  +operation: DMOperation,
+};
+
+export type ReplaceDMOperationOperation = {
+  +type: 'replace_dm_operation',
+  +payload: Operation,
+};
+
+export type RemoveDMOperationsOperation = {
+  +type: 'remove_dm_operations',
+  +payload: {
+    +ids: $ReadOnlyArray<string>,
+  },
+};
+
+export type RemoveAllDMOperationsOperation = {
+  +type: 'remove_all_dm_operations',
+};
+
+export type DMOperationStoreOperation =
+  | ReplaceDMOperationOperation
+  | RemoveDMOperationsOperation
+  | RemoveAllDMOperationsOperation;
+
+export type ClientDBDMOperation = {
+  +id: string,
+  +type: string,
+  +operation: string,
+};
+
+export type ClientDBReplaceDMOperationOperation = {
+  +type: 'replace_dm_operation',
+  +payload: ClientDBDMOperation,
+};
+
+export type ClientDBDMOperationStoreOperation =
+  | ClientDBReplaceDMOperationOperation
+  | RemoveDMOperationsOperation
+  | RemoveAllDMOperationsOperation;
diff --git a/lib/types/store-ops-types.js b/lib/types/store-ops-types.js
--- a/lib/types/store-ops-types.js
+++ b/lib/types/store-ops-types.js
@@ -36,6 +36,11 @@
   ClientDBCommunityStoreOperation,
   CommunityStoreOperation,
 } from '../ops/community-store-ops.js';
+import type {
+  ClientDBDMOperation,
+  ClientDBDMOperationStoreOperation,
+  DMOperationStoreOperation,
+} from '../ops/dm-operations-store-ops.js';
 import type {
   ClientDBEntryInfo,
   EntryStoreOperation,
@@ -94,6 +99,7 @@
   +outboundP2PMessages?: $ReadOnlyArray<OutboundP2PMessage>,
   +entryStoreOperations?: $ReadOnlyArray<EntryStoreOperation>,
   +messageSearchStoreOperations?: $ReadOnlyArray<MessageSearchStoreOperation>,
+  +dmOperationStoreOperations?: $ReadOnlyArray<DMOperationStoreOperation>,
 };
 
 export type ClientDBStoreOperations = {
@@ -111,6 +117,7 @@
   +outboundP2PMessages?: $ReadOnlyArray<OutboundP2PMessage>,
   +entryStoreOperations?: $ReadOnlyArray<ClientDBEntryStoreOperation>,
   +messageSearchStoreOperations?: $ReadOnlyArray<ClientDBMessageSearchStoreOperation>,
+  +dmOperationStoreOperations?: $ReadOnlyArray<ClientDBDMOperationStoreOperation>,
 };
 
 export type ClientDBStore = {
@@ -128,6 +135,7 @@
   +threadActivityEntries: $ReadOnlyArray<ClientDBThreadActivityEntry>,
   +entries: $ReadOnlyArray<ClientDBEntryInfo>,
   +messageStoreLocalMessageInfos: $ReadOnlyArray<ClientDBLocalMessageInfo>,
+  +dmOperations: $ReadOnlyArray<ClientDBDMOperation>,
 };
 
 export type ClientStore = {
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h
@@ -8,6 +8,7 @@
 #include "../_generated/commJSI.h"
 #include "PersistentStorageUtilities/DataStores/AuxUserStore.h"
 #include "PersistentStorageUtilities/DataStores/CommunityStore.h"
+#include "PersistentStorageUtilities/DataStores/DMOperationStore.h"
 #include "PersistentStorageUtilities/DataStores/DraftStore.h"
 #include "PersistentStorageUtilities/DataStores/EntryStore.h"
 #include "PersistentStorageUtilities/DataStores/IntegrityStore.h"
@@ -48,6 +49,7 @@
   ThreadActivityStore threadActivityStore;
   EntryStore entryStore;
   MessageSearchStore messageSearchStore;
+  DMOperationStore dmOperationStore;
 
   void persistCryptoModules(
       bool persistContentModule,
@@ -290,6 +292,8 @@
       jsi::Array notifOneTimeKeys,
       jsi::String deviceList,
       jsi::String backupSecret) override;
+  virtual jsi::Value
+  getDMOperationsByType(jsi::Runtime &rt, jsi::String type) override;
 
 public:
   CommCoreModule(std::shared_ptr<facebook::react::CallInvoker> jsInvoker);
diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
--- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
+++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.cpp
@@ -126,6 +126,7 @@
           std::vector<ThreadActivityEntry> threadActivityStoreVector;
           std::vector<EntryInfo> entryStoreVector;
           std::vector<LocalMessageInfo> messageStoreLocalMessageInfosVector;
+          std::vector<DMOperation> dmOperationsVector;
           try {
             draftsVector = DatabaseManager::getQueryExecutor().getAllDrafts();
             messagesVector =
@@ -153,6 +154,8 @@
             messageStoreLocalMessageInfosVector =
                 DatabaseManager::getQueryExecutor()
                     .getAllMessageStoreLocalMessageInfos();
+            dmOperationsVector =
+                DatabaseManager::getQueryExecutor().getDMOperations();
           } catch (std::system_error &e) {
             error = e.what();
           }
@@ -192,102 +195,111 @@
           auto messageStoreLocalMessageInfosVectorPtr =
               std::make_shared<std::vector<LocalMessageInfo>>(
                   std::move(messageStoreLocalMessageInfosVector));
-          this->jsInvoker_->invokeAsync([&innerRt,
-                                         draftsVectorPtr,
-                                         messagesVectorPtr,
-                                         threadsVectorPtr,
-                                         messageStoreThreadsVectorPtr,
-                                         reportStoreVectorPtr,
-                                         userStoreVectorPtr,
-                                         keyserveStoreVectorPtr,
-                                         communityStoreVectorPtr,
-                                         integrityStoreVectorPtr,
-                                         syncedMetadataStoreVectorPtr,
-                                         auxUserStoreVectorPtr,
-                                         threadActivityStoreVectorPtr,
-                                         entryStoreVectorPtr,
-                                         messageStoreLocalMessageInfosVectorPtr,
-                                         error,
-                                         promise,
-                                         draftStore = this->draftStore,
-                                         threadStore = this->threadStore,
-                                         messageStore = this->messageStore,
-                                         reportStore = this->reportStore,
-                                         userStore = this->userStore,
-                                         keyserverStore = this->keyserverStore,
-                                         communityStore = this->communityStore,
-                                         integrityStore = this->integrityStore,
-                                         syncedMetadataStore =
-                                             this->syncedMetadataStore,
-                                         auxUserStore = this->auxUserStore,
-                                         threadActivityStore =
-                                             this->threadActivityStore,
-                                         entryStore = this->entryStore]() {
-            if (error.size()) {
-              promise->reject(error);
-              return;
-            }
-            jsi::Array jsiDrafts =
-                draftStore.parseDBDataStore(innerRt, draftsVectorPtr);
-            jsi::Array jsiMessages =
-                messageStore.parseDBDataStore(innerRt, messagesVectorPtr);
-            jsi::Array jsiThreads =
-                threadStore.parseDBDataStore(innerRt, threadsVectorPtr);
-            jsi::Array jsiMessageStoreThreads =
-                messageStore.parseDBMessageStoreThreads(
-                    innerRt, messageStoreThreadsVectorPtr);
-            jsi::Array jsiReportStore =
-                reportStore.parseDBDataStore(innerRt, reportStoreVectorPtr);
-            jsi::Array jsiUserStore =
-                userStore.parseDBDataStore(innerRt, userStoreVectorPtr);
-            jsi::Array jsiKeyserverStore = keyserverStore.parseDBDataStore(
-                innerRt, keyserveStoreVectorPtr);
-            jsi::Array jsiCommunityStore = communityStore.parseDBDataStore(
-                innerRt, communityStoreVectorPtr);
-            jsi::Array jsiIntegrityStore = integrityStore.parseDBDataStore(
-                innerRt, integrityStoreVectorPtr);
-            jsi::Array jsiSyncedMetadataStore =
-                syncedMetadataStore.parseDBDataStore(
-                    innerRt, syncedMetadataStoreVectorPtr);
-            jsi::Array jsiAuxUserStore =
-                auxUserStore.parseDBDataStore(innerRt, auxUserStoreVectorPtr);
-            jsi::Array jsiThreadActivityStore =
-                threadActivityStore.parseDBDataStore(
-                    innerRt, threadActivityStoreVectorPtr);
-            jsi::Array jsiEntryStore =
-                entryStore.parseDBDataStore(innerRt, entryStoreVectorPtr);
-            jsi::Array jsiMessageStoreLocalMessageInfos =
-                messageStore.parseDBMessageStoreLocalMessageInfos(
-                    innerRt, messageStoreLocalMessageInfosVectorPtr);
-
-            auto jsiClientDBStore = jsi::Object(innerRt);
-            jsiClientDBStore.setProperty(innerRt, "messages", jsiMessages);
-            jsiClientDBStore.setProperty(innerRt, "threads", jsiThreads);
-            jsiClientDBStore.setProperty(innerRt, "drafts", jsiDrafts);
-            jsiClientDBStore.setProperty(
-                innerRt, "messageStoreThreads", jsiMessageStoreThreads);
-            jsiClientDBStore.setProperty(innerRt, "reports", jsiReportStore);
-            jsiClientDBStore.setProperty(innerRt, "users", jsiUserStore);
-            jsiClientDBStore.setProperty(
-                innerRt, "keyservers", jsiKeyserverStore);
-            jsiClientDBStore.setProperty(
-                innerRt, "communities", jsiCommunityStore);
-            jsiClientDBStore.setProperty(
-                innerRt, "integrityThreadHashes", jsiIntegrityStore);
-            jsiClientDBStore.setProperty(
-                innerRt, "syncedMetadata", jsiSyncedMetadataStore);
-            jsiClientDBStore.setProperty(
-                innerRt, "auxUserInfos", jsiAuxUserStore);
-            jsiClientDBStore.setProperty(
-                innerRt, "threadActivityEntries", jsiThreadActivityStore);
-            jsiClientDBStore.setProperty(innerRt, "entries", jsiEntryStore);
-            jsiClientDBStore.setProperty(
-                innerRt,
-                "messageStoreLocalMessageInfos",
-                jsiMessageStoreLocalMessageInfos);
-
-            promise->resolve(std::move(jsiClientDBStore));
-          });
+          auto dmOperationsVectorPtr =
+              std::make_shared<std::vector<DMOperation>>(
+                  std::move(dmOperationsVector));
+          this->jsInvoker_->invokeAsync(
+              [&innerRt,
+               draftsVectorPtr,
+               messagesVectorPtr,
+               threadsVectorPtr,
+               messageStoreThreadsVectorPtr,
+               reportStoreVectorPtr,
+               userStoreVectorPtr,
+               keyserveStoreVectorPtr,
+               communityStoreVectorPtr,
+               integrityStoreVectorPtr,
+               syncedMetadataStoreVectorPtr,
+               auxUserStoreVectorPtr,
+               threadActivityStoreVectorPtr,
+               entryStoreVectorPtr,
+               messageStoreLocalMessageInfosVectorPtr,
+               dmOperationsVectorPtr,
+               error,
+               promise,
+               draftStore = this->draftStore,
+               threadStore = this->threadStore,
+               messageStore = this->messageStore,
+               reportStore = this->reportStore,
+               userStore = this->userStore,
+               keyserverStore = this->keyserverStore,
+               communityStore = this->communityStore,
+               integrityStore = this->integrityStore,
+               syncedMetadataStore = this->syncedMetadataStore,
+               auxUserStore = this->auxUserStore,
+               threadActivityStore = this->threadActivityStore,
+               entryStore = this->entryStore,
+               dmOperationStore = this->dmOperationStore]() {
+                if (error.size()) {
+                  promise->reject(error);
+                  return;
+                }
+                jsi::Array jsiDrafts =
+                    draftStore.parseDBDataStore(innerRt, draftsVectorPtr);
+                jsi::Array jsiMessages =
+                    messageStore.parseDBDataStore(innerRt, messagesVectorPtr);
+                jsi::Array jsiThreads =
+                    threadStore.parseDBDataStore(innerRt, threadsVectorPtr);
+                jsi::Array jsiMessageStoreThreads =
+                    messageStore.parseDBMessageStoreThreads(
+                        innerRt, messageStoreThreadsVectorPtr);
+                jsi::Array jsiReportStore =
+                    reportStore.parseDBDataStore(innerRt, reportStoreVectorPtr);
+                jsi::Array jsiUserStore =
+                    userStore.parseDBDataStore(innerRt, userStoreVectorPtr);
+                jsi::Array jsiKeyserverStore = keyserverStore.parseDBDataStore(
+                    innerRt, keyserveStoreVectorPtr);
+                jsi::Array jsiCommunityStore = communityStore.parseDBDataStore(
+                    innerRt, communityStoreVectorPtr);
+                jsi::Array jsiIntegrityStore = integrityStore.parseDBDataStore(
+                    innerRt, integrityStoreVectorPtr);
+                jsi::Array jsiSyncedMetadataStore =
+                    syncedMetadataStore.parseDBDataStore(
+                        innerRt, syncedMetadataStoreVectorPtr);
+                jsi::Array jsiAuxUserStore = auxUserStore.parseDBDataStore(
+                    innerRt, auxUserStoreVectorPtr);
+                jsi::Array jsiThreadActivityStore =
+                    threadActivityStore.parseDBDataStore(
+                        innerRt, threadActivityStoreVectorPtr);
+                jsi::Array jsiEntryStore =
+                    entryStore.parseDBDataStore(innerRt, entryStoreVectorPtr);
+                jsi::Array jsiMessageStoreLocalMessageInfos =
+                    messageStore.parseDBMessageStoreLocalMessageInfos(
+                        innerRt, messageStoreLocalMessageInfosVectorPtr);
+                jsi::Array jsiDMOperations = dmOperationStore.parseDBDataStore(
+                    innerRt, dmOperationsVectorPtr);
+
+                auto jsiClientDBStore = jsi::Object(innerRt);
+                jsiClientDBStore.setProperty(innerRt, "messages", jsiMessages);
+                jsiClientDBStore.setProperty(innerRt, "threads", jsiThreads);
+                jsiClientDBStore.setProperty(innerRt, "drafts", jsiDrafts);
+                jsiClientDBStore.setProperty(
+                    innerRt, "messageStoreThreads", jsiMessageStoreThreads);
+                jsiClientDBStore.setProperty(
+                    innerRt, "reports", jsiReportStore);
+                jsiClientDBStore.setProperty(innerRt, "users", jsiUserStore);
+                jsiClientDBStore.setProperty(
+                    innerRt, "keyservers", jsiKeyserverStore);
+                jsiClientDBStore.setProperty(
+                    innerRt, "communities", jsiCommunityStore);
+                jsiClientDBStore.setProperty(
+                    innerRt, "integrityThreadHashes", jsiIntegrityStore);
+                jsiClientDBStore.setProperty(
+                    innerRt, "syncedMetadata", jsiSyncedMetadataStore);
+                jsiClientDBStore.setProperty(
+                    innerRt, "auxUserInfos", jsiAuxUserStore);
+                jsiClientDBStore.setProperty(
+                    innerRt, "threadActivityEntries", jsiThreadActivityStore);
+                jsiClientDBStore.setProperty(innerRt, "entries", jsiEntryStore);
+                jsiClientDBStore.setProperty(
+                    innerRt,
+                    "messageStoreLocalMessageInfos",
+                    jsiMessageStoreLocalMessageInfos);
+                jsiClientDBStore.setProperty(
+                    innerRt, "dmOperations", jsiDMOperations);
+
+                promise->resolve(std::move(jsiClientDBStore));
+              });
         };
         GlobalDBSingleton::instance.scheduleOrRunCancellable(
             job, promise, this->jsInvoker_);
@@ -455,6 +467,12 @@
         "messageSearchStoreOperations",
         this->messageSearchStore,
         storeOpsPtr);
+    this->appendDBStoreOps(
+        rt,
+        operations,
+        "dmOperationStoreOperations",
+        this->dmOperationStore,
+        storeOpsPtr);
   } catch (std::runtime_error &e) {
     createOperationsError = e.what();
   }
@@ -2157,7 +2175,8 @@
       auxUserStore(jsInvoker),
       threadActivityStore(jsInvoker),
       entryStore(jsInvoker),
-      messageSearchStore(jsInvoker) {
+      messageSearchStore(jsInvoker),
+      dmOperationStore(jsInvoker) {
   GlobalDBSingleton::instance.enableMultithreading();
 }
 
@@ -3489,4 +3508,42 @@
       });
 }
 
+jsi::Value
+CommCoreModule::getDMOperationsByType(jsi::Runtime &rt, jsi::String type) {
+  std::string typeCpp = type.utf8(rt);
+
+  return createPromiseAsJSIValue(
+      rt, [=](jsi::Runtime &innerRt, std::shared_ptr<Promise> promise) {
+        taskType job = [=, &innerRt]() {
+          std::string error;
+          std::shared_ptr<std::vector<DMOperation>> operations;
+          try {
+            operations = std::make_shared<std::vector<DMOperation>>(
+                DatabaseManager::getQueryExecutor().getDMOperationsByType(
+                    typeCpp));
+          } catch (std::system_error &e) {
+            error = e.what();
+          }
+
+          this->jsInvoker_->invokeAsync(
+              [&innerRt,
+               error,
+               promise,
+               operations,
+               dmOperationStore = this->dmOperationStore]() {
+                if (error.size()) {
+                  promise->reject(error);
+                  return;
+                }
+
+                jsi::Array jsiOperations =
+                    dmOperationStore.parseDBDataStore(innerRt, operations);
+                promise->resolve(std::move(jsiOperations));
+              });
+        };
+        GlobalDBSingleton::instance.scheduleOrRunCancellable(
+            job, promise, this->jsInvoker_);
+      });
+}
+
 } // namespace comm
diff --git a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
--- a/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
+++ b/native/cpp/CommonCpp/_generated/commJSI-generated.cpp
@@ -250,6 +250,9 @@
 static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreUser(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
   return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->restoreUser(rt, args[0].asString(rt), args[1].isNull() || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt)), args[2].isNull() || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asString(rt)), args[3].asString(rt), args[4].asString(rt), args[5].asString(rt), args[6].asString(rt), args[7].asString(rt), args[8].asString(rt), args[9].asObject(rt).asArray(rt), args[10].asObject(rt).asArray(rt), args[11].asString(rt), args[12].asString(rt));
 }
+static jsi::Value __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getDMOperationsByType(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
+  return static_cast<CommCoreModuleSchemaCxxSpecJSI *>(&turboModule)->getDMOperationsByType(rt, args[0].asString(rt));
+}
 
 CommCoreModuleSchemaCxxSpecJSI::CommCoreModuleSchemaCxxSpecJSI(std::shared_ptr<CallInvoker> jsInvoker)
   : TurboModule("CommTurboModule", jsInvoker) {
@@ -330,6 +333,7 @@
   methodMap_["searchMessages"] = MethodMetadata {4, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_searchMessages};
   methodMap_["fetchMessages"] = MethodMetadata {3, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_fetchMessages};
   methodMap_["restoreUser"] = MethodMetadata {13, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_restoreUser};
+  methodMap_["getDMOperationsByType"] = MethodMetadata {1, __hostFunction_CommCoreModuleSchemaCxxSpecJSI_getDMOperationsByType};
 }
 
 
diff --git a/native/cpp/CommonCpp/_generated/commJSI.h b/native/cpp/CommonCpp/_generated/commJSI.h
--- a/native/cpp/CommonCpp/_generated/commJSI.h
+++ b/native/cpp/CommonCpp/_generated/commJSI.h
@@ -97,6 +97,7 @@
   virtual jsi::Value searchMessages(jsi::Runtime &rt, jsi::String query, jsi::String threadID, std::optional<jsi::String> timestampCursor, std::optional<jsi::String> messageIDCursor) = 0;
   virtual jsi::Value fetchMessages(jsi::Runtime &rt, jsi::String threadID, double limit, double offset) = 0;
   virtual jsi::Value restoreUser(jsi::Runtime &rt, jsi::String userID, std::optional<jsi::String> siweSocialProofMessage, std::optional<jsi::String> siweSocialProofSignature, jsi::String keyPayload, jsi::String keyPayloadSignature, jsi::String contentPrekey, jsi::String contentPrekeySignature, jsi::String notifPrekey, jsi::String notifPrekeySignature, jsi::Array contentOneTimeKeys, jsi::Array notifOneTimeKeys, jsi::String deviceList, jsi::String backupSecret) = 0;
+  virtual jsi::Value getDMOperationsByType(jsi::Runtime &rt, jsi::String type) = 0;
 
 };
 
@@ -734,6 +735,14 @@
       return bridging::callFromJs<jsi::Value>(
           rt, &T::restoreUser, jsInvoker_, instance_, std::move(userID), std::move(siweSocialProofMessage), std::move(siweSocialProofSignature), std::move(keyPayload), std::move(keyPayloadSignature), std::move(contentPrekey), std::move(contentPrekeySignature), std::move(notifPrekey), std::move(notifPrekeySignature), std::move(contentOneTimeKeys), std::move(notifOneTimeKeys), std::move(deviceList), std::move(backupSecret));
     }
+    jsi::Value getDMOperationsByType(jsi::Runtime &rt, jsi::String type) override {
+      static_assert(
+          bridging::getParameterCount(&T::getDMOperationsByType) == 2,
+          "Expected getDMOperationsByType(...) to have 2 parameters");
+
+      return bridging::callFromJs<jsi::Value>(
+          rt, &T::getDMOperationsByType, jsInvoker_, instance_, std::move(type));
+    }
 
   private:
     T *instance_;
diff --git a/native/schema/CommCoreModuleSchema.js b/native/schema/CommCoreModuleSchema.js
--- a/native/schema/CommCoreModuleSchema.js
+++ b/native/schema/CommCoreModuleSchema.js
@@ -5,6 +5,7 @@
 import { TurboModuleRegistry } from 'react-native';
 import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport.js';
 
+import type { ClientDBDMOperation } from 'lib/ops/dm-operations-store-ops.js';
 import type { ClientDBMessageStoreOperation } from 'lib/ops/message-store-ops.js';
 import type { ClientDBReportStoreOperation } from 'lib/ops/report-store-ops.js';
 import type { ClientDBThreadStoreOperation } from 'lib/ops/thread-store-ops.js';
@@ -233,6 +234,7 @@
     deviceList: string,
     backupSecret: string,
   ) => Promise<string>;
+  +getDMOperationsByType: (type: string) => Promise<Array<ClientDBDMOperation>>;
 }
 
 export interface CoreModuleSpec extends Spec {
diff --git a/web/cpp/SQLiteQueryExecutorBindings.cpp b/web/cpp/SQLiteQueryExecutorBindings.cpp
--- a/web/cpp/SQLiteQueryExecutorBindings.cpp
+++ b/web/cpp/SQLiteQueryExecutorBindings.cpp
@@ -75,6 +75,10 @@
   value_object<LocalMessageInfo>("LocalMessageInfo")
       .field("id", &LocalMessageInfo::id)
       .field("localMessageInfo", &LocalMessageInfo::local_message_info);
+  value_object<DMOperation>("DMOperation")
+      .field("id", &DMOperation::id)
+      .field("type", &DMOperation::type)
+      .field("operation", &DMOperation::operation);
 
   value_object<WebThread>("WebThread")
       .field("id", &WebThread::id)
@@ -265,6 +269,11 @@
       .function(
           "getAllMessageStoreLocalMessageInfos",
           &SQLiteQueryExecutor::getAllMessageStoreLocalMessageInfos)
+      .function("replaceDMOperation", &SQLiteQueryExecutor::replaceDMOperation)
+      .function("removeAllDMOperations", &SQLiteQueryExecutor::removeAllDMOperations)
+      .function("removeDMOperations", &SQLiteQueryExecutor::removeDMOperations)
+      .function("getAllDMOperations", &SQLiteQueryExecutor::getDMOperations)
+      .function("getDMOperationsByType", &SQLiteQueryExecutor::getDMOperationsByType)
       .function("beginTransaction", &SQLiteQueryExecutor::beginTransaction)
       .function("commitTransaction", &SQLiteQueryExecutor::commitTransaction)
       .function(
diff --git a/web/shared-worker/_generated/comm_query_executor.wasm b/web/shared-worker/_generated/comm_query_executor.wasm
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001

literal 0
Hc$@<O00001

diff --git a/web/shared-worker/types/sqlite-query-executor.js b/web/shared-worker/types/sqlite-query-executor.js
--- a/web/shared-worker/types/sqlite-query-executor.js
+++ b/web/shared-worker/types/sqlite-query-executor.js
@@ -2,6 +2,7 @@
 
 import type { ClientDBAuxUserInfo } from 'lib/ops/aux-user-store-ops.js';
 import type { ClientDBCommunityInfo } from 'lib/ops/community-store-ops.js';
+import type { ClientDBDMOperation } from 'lib/ops/dm-operations-store-ops.js';
 import type { ClientDBEntryInfo } from 'lib/ops/entries-store-ops.js';
 import type { ClientDBIntegrityThreadHash } from 'lib/ops/integrity-store-ops.js';
 import type { ClientDBKeyserverInfo } from 'lib/ops/keyserver-store-ops.js';
@@ -160,6 +161,12 @@
   removeAllMessageStoreLocalMessageInfos(): void;
   getAllMessageStoreLocalMessageInfos(): ClientDBLocalMessageInfo[];
 
+  replaceDMOperation(operation: ClientDBDMOperation): void;
+  removeAllDMOperations(): void;
+  removeDMOperations(ids: $ReadOnlyArray<string>): void;
+  getAllDMOperations(): $ReadOnlyArray<ClientDBDMOperation>;
+  getDMOperationsByType(type: string): $ReadOnlyArray<ClientDBDMOperation>;
+
   beginTransaction(): void;
   commitTransaction(): void;
   rollbackTransaction(): void;
diff --git a/web/shared-worker/worker/process-operations.js b/web/shared-worker/worker/process-operations.js
--- a/web/shared-worker/worker/process-operations.js
+++ b/web/shared-worker/worker/process-operations.js
@@ -645,6 +645,7 @@
     entries: sqliteQueryExecutor.getAllEntries(),
     messageStoreLocalMessageInfos:
       sqliteQueryExecutor.getAllMessageStoreLocalMessageInfos(),
+    dmOperations: sqliteQueryExecutor.getAllDMOperations(),
   };
 }