diff --git a/indexedDb/impl/dm/implementation.go b/indexedDb/impl/dm/implementation.go
index f40791ece46d05b397dadd6766ec455045168452..09303bcfa7747ef203d262c4da8e36b62c3daabe 100644
--- a/indexedDb/impl/dm/implementation.go
+++ b/indexedDb/impl/dm/implementation.go
@@ -179,13 +179,7 @@ func (w *wasmModel) UpdateSentStatus(uuid uint64, messageID message.ID,
 	}
 
 	// Extract the existing Message and update the Status
-	newMessage := &Message{}
-	err = json.Unmarshal([]byte(utils.JsToJson(currentMsg)), newMessage)
-	if err != nil {
-		jww.ERROR.Printf("%+v", errors.WithMessagef(parentErr,
-			"Could not JSON unmarshal message: %+v", err))
-		return
-	}
+	newMessage, err := valueToMessage(currentMsg)
 
 	newMessage.Status = uint8(status)
 	if !messageID.Equals(message.ID{}) {
@@ -365,6 +359,45 @@ func (w *wasmModel) setBlocked(senderPubKey ed25519.PublicKey, isBlocked bool) e
 		resultConvo.Token, resultConvo.CodesetVersion, timeBlocked)
 }
 
+// DeleteMessage deletes the message with the given message.ID belonging to
+// the sender. If the message exists and belongs to the sender, then it is
+// deleted and DeleteMessage returns true. If it does not exist, it returns
+// false.
+func (w *wasmModel) DeleteMessage(messageID message.ID, senderPubKey ed25519.PublicKey) bool {
+	parentErr := "failed to DeleteMessage"
+	msgId := impl.EncodeBytes(messageID.Marshal())
+
+	// Use the key to get the existing Message
+	currentMsg, err := impl.GetIndex(w.db, messageStoreName,
+		messageStoreMessageIndex, msgId)
+	if err != nil {
+		jww.ERROR.Printf("%s: %+v", parentErr, err)
+		return false
+	}
+
+	// Convert the js.Value to a proper object
+	msgObj, err := valueToMessage(currentMsg)
+	if err != nil {
+		jww.ERROR.Printf("%s: %+v", parentErr, err)
+		return false
+	}
+
+	// Ensure the public keys match
+	if !bytes.Equal(msgObj.SenderPubKey, senderPubKey) {
+		jww.ERROR.Printf("%s: %s", parentErr, "Public keys do not match")
+		return false
+	}
+
+	// Perform the delete
+	err = impl.DeleteIndex(w.db, messageStoreName, messageStoreMessageIndex,
+		msgPkeyName, msgId)
+	if err != nil {
+		jww.ERROR.Printf("%s: %+v", parentErr, err)
+		return false
+	}
+	return true
+}
+
 // GetConversation returns the conversation held by the model (receiver).
 func (w *wasmModel) GetConversation(senderPubKey ed25519.PublicKey) *dm.ModelConversation {
 	parentErr := "failed to GetConversation"
@@ -426,3 +459,9 @@ func (w *wasmModel) GetConversations() []dm.ModelConversation {
 	}
 	return conversations
 }
+
+// valueToMessage is a helper for converting js.Value to Message.
+func valueToMessage(msgObj js.Value) (*Message, error) {
+	resultMsg := &Message{}
+	return resultMsg, json.Unmarshal([]byte(utils.JsToJson(msgObj)), resultMsg)
+}
diff --git a/indexedDb/impl/dm/implementation_test.go b/indexedDb/impl/dm/implementation_test.go
index c8f42c3871bcfc841683e93b57e2ed4105ab000b..39ca0036a078382ca232a2a725ff7a5ff412dddf 100644
--- a/indexedDb/impl/dm/implementation_test.go
+++ b/indexedDb/impl/dm/implementation_test.go
@@ -14,6 +14,7 @@ import (
 	"crypto/ed25519"
 	"encoding/json"
 	"fmt"
+	"github.com/stretchr/testify/require"
 	"gitlab.com/elixxir/client/v4/cmix/rounds"
 	"gitlab.com/elixxir/client/v4/dm"
 	"gitlab.com/elixxir/crypto/message"
@@ -158,3 +159,36 @@ func TestWasmModel_BlockSender(t *testing.T) {
 		t.Fatal("Expected blocked to be false")
 	}
 }
+
+// Test failed and successful deletes
+func TestWasmModel_DeleteMessage(t *testing.T) {
+	m, err := newWASMModel("TestWasmModel_DeleteMessage", nil, dummyReceivedMessageCB)
+	if err != nil {
+		t.Fatal(err.Error())
+	}
+
+	// Insert test message
+	testBytes := []byte("test")
+	testBadBytes := []byte("uwu")
+	testMsgId := message.DeriveChannelMessageID(&id.ID{1}, 0, testBytes)
+	testMsg := &Message{
+		MessageID:          testMsgId.Marshal(),
+		ConversationPubKey: testBytes,
+		ParentMessageID:    nil,
+		Timestamp:          time.Now(),
+		SenderPubKey:       testBytes,
+		CodesetVersion:     5,
+		Status:             5,
+		Text:               "",
+		Type:               5,
+		Round:              5,
+	}
+	_, err = m.upsertMessage(testMsg)
+	require.NoError(t, err)
+
+	// Non-matching pub key, should fail to delete
+	require.False(t, m.DeleteMessage(testMsgId, testBadBytes))
+
+	// Correct pub key, should have deleted
+	require.True(t, m.DeleteMessage(testMsgId, testBytes))
+}