diff --git a/packages/backend/package.json b/packages/backend/package.json index 745b7c9af..b9f1bf339 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-backend", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "types": "dist/index.d.ts", "dependencies": { diff --git a/packages/backend/src/persistence/storage/postgres/addMessageBatch.ts b/packages/backend/src/persistence/storage/postgres/addMessageBatch.ts index 608383fae..7db15fc43 100644 --- a/packages/backend/src/persistence/storage/postgres/addMessageBatch.ts +++ b/packages/backend/src/persistence/storage/postgres/addMessageBatch.ts @@ -19,8 +19,15 @@ export const addMessageBatch = account.id, encryptedContactName, ); + + const uniqueMessageBatch = messageBatch.filter( + (message, index, self) => + index === + self.findIndex((m) => m.messageId === message.messageId), + ); + //store each message in the db - const createMessagePromises = messageBatch.map( + const createMessagePromises = uniqueMessageBatch.map( ({ messageId, createdAt, diff --git a/packages/backend/src/storage.test.ts b/packages/backend/src/storage.test.ts index f8beaf672..a4cbe7a9a 100644 --- a/packages/backend/src/storage.test.ts +++ b/packages/backend/src/storage.test.ts @@ -1007,7 +1007,7 @@ describe('Storage', () => { .send({ encryptedEnvelopContainer: JSON.stringify(envelop1), encryptedContactName: sha256(receiver.account.ensName), - messageId: envelop1.metadata.encryptedMessageHash, + messageId: envelop1.metadata.messageHash, createdAt: 1, isHalted: true, }); @@ -1146,6 +1146,75 @@ describe('Storage', () => { expect(body[0].contact).toEqual(sha256(receiver.account.ensName)); expect(body.length).toBe(1); + const { status: getMessagesStatus, body: messages } = await request( + app, + ) + .get( + `/new/bob.eth/getMessages/${sha256( + receiver.account.ensName, + )}`, + ) + .set({ + authorization: 'Bearer ' + token, + }) + .send(); + + expect(getMessagesStatus).toBe(200); + expect(messages.length).toBe(2); + expect( + JSON.parse(JSON.parse(messages[0]).encryptedEnvelopContainer), + ).toStrictEqual(envelop); + }); + it('if batch contains duplicates it only creates the message once', async () => { + const messageFactory = MockMessageFactory( + sender, + receiver, + deliveryService, + ); + const envelop = await messageFactory.createEncryptedEnvelop( + 'Hello1', + ); + const { status } = await request(app) + .post(`/new/bob.eth/addMessageBatch`) + .set({ + authorization: 'Bearer ' + token, + }) + .send({ + encryptedContactName: sha256(receiver.account.ensName), + messageBatch: [ + { + encryptedEnvelopContainer: JSON.stringify(envelop), + messageId: '123', + createdAt: 1, + isHalted: false, + }, + { + encryptedEnvelopContainer: JSON.stringify(envelop), + messageId: '123', + createdAt: 1, + isHalted: false, + }, + { + encryptedEnvelopContainer: JSON.stringify(envelop), + messageId: '456', + createdAt: 2, + isHalted: false, + }, + ], + }); + expect(status).toBe(200); + + const { body } = await request(app) + .get(`/new/bob.eth/getConversations`) + .set({ + authorization: 'Bearer ' + token, + }) + .send(); + + expect(status).toBe(200); + expect(body[0].contact).toEqual(sha256(receiver.account.ensName)); + expect(body.length).toBe(1); + const { status: getMessagesStatus, body: messages } = await request( app, ) diff --git a/packages/billboard-client/package.json b/packages/billboard-client/package.json index f494cef00..d27cbb865 100644 --- a/packages/billboard-client/package.json +++ b/packages/billboard-client/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-billboard-client", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "private": true, "main": "dist/index.js", "types": "dist/ined.d.ts", diff --git a/packages/billboard-widget/package.json b/packages/billboard-widget/package.json index 9a491d9ac..625597ff6 100644 --- a/packages/billboard-widget/package.json +++ b/packages/billboard-widget/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-billboard-widget", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "files": [ "dist" ], diff --git a/packages/delivery-service/package.json b/packages/delivery-service/package.json index 1d784e2d0..8d66852f2 100644 --- a/packages/delivery-service/package.json +++ b/packages/delivery-service/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/delivery-service", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "types": "dist/index.d.ts", "dependencies": { diff --git a/packages/delivery-service/src/persistence/messages/createMessage.test.ts b/packages/delivery-service/src/persistence/messages/createMessage.test.ts index 3c9d43556..997fe2ee6 100644 --- a/packages/delivery-service/src/persistence/messages/createMessage.test.ts +++ b/packages/delivery-service/src/persistence/messages/createMessage.test.ts @@ -36,7 +36,7 @@ describe('Create Message', () => { metadata: { deliveryInformation: '', signature: '', - encryptedMessageHash: '', + messageHash: '', version: '', encryptionScheme: 'x25519-chacha20-poly1305', }, @@ -64,7 +64,7 @@ describe('Create Message', () => { deliveryInstruction: '', }, signature: '', - encryptedMessageHash: '', + messageHash: '', version: '', encryptionScheme: 'x25519-chacha20-poly1305', }, diff --git a/packages/delivery-service/src/persistence/messages/deleteExpiredMessages.test.ts b/packages/delivery-service/src/persistence/messages/deleteExpiredMessages.test.ts index 71371ea7f..3b72bd2d9 100644 --- a/packages/delivery-service/src/persistence/messages/deleteExpiredMessages.test.ts +++ b/packages/delivery-service/src/persistence/messages/deleteExpiredMessages.test.ts @@ -29,7 +29,7 @@ describe('Delete Expired messages', () => { metadata: { deliveryInformation: '', signature: '', - encryptedMessageHash: '', + messageHash: '', version: '', encryptionScheme: 'x25519-chacha20-poly1305', }, @@ -44,7 +44,7 @@ describe('Delete Expired messages', () => { metadata: { deliveryInformation: '', signature: '', - encryptedMessageHash: '', + messageHash: '', version: '', encryptionScheme: 'x25519-chacha20-poly1305', }, @@ -60,7 +60,7 @@ describe('Delete Expired messages', () => { metadata: { deliveryInformation: '', signature: '', - encryptedMessageHash: '', + messageHash: '', version: '', encryptionScheme: 'x25519-chacha20-poly1305', }, diff --git a/packages/delivery-service/src/persistence/messages/syncAcknowledge.test.ts b/packages/delivery-service/src/persistence/messages/syncAcknowledge.test.ts index d317d9ff8..55699d00e 100644 --- a/packages/delivery-service/src/persistence/messages/syncAcknowledge.test.ts +++ b/packages/delivery-service/src/persistence/messages/syncAcknowledge.test.ts @@ -36,7 +36,7 @@ describe('Sync Acknowledge', () => { from: SENDER_ADDRESS, }, signature: '', - encryptedMessageHash: '0x123', + messageHash: '0x123', version: '', encryptionScheme: 'x25519-chacha20-poly1305', }, @@ -49,7 +49,7 @@ describe('Sync Acknowledge', () => { from: SENDER_ADDRESS, }, signature: '', - encryptedMessageHash: '0x456', + messageHash: '0x456', version: '', encryptionScheme: 'x25519-chacha20-poly1305', }, @@ -84,9 +84,7 @@ describe('Sync Acknowledge', () => { ); expect(afterSyncAcknowledge.length).toBe(1); - expect(afterSyncAcknowledge[0].metadata.encryptedMessageHash).toBe( - '0x456', - ); + expect(afterSyncAcknowledge[0].metadata.messageHash).toBe('0x456'); }); it('returns false if message is not found', async () => { const envelop1: EncryptionEnvelop = { @@ -97,7 +95,7 @@ describe('Sync Acknowledge', () => { from: SENDER_ADDRESS, }, signature: '', - encryptedMessageHash: '0x123', + messageHash: '0x123', version: '', encryptionScheme: 'x25519-chacha20-poly1305', }, diff --git a/packages/delivery-service/src/persistence/messages/syncAcknowledge.ts b/packages/delivery-service/src/persistence/messages/syncAcknowledge.ts index be740eb2b..2df6648d1 100644 --- a/packages/delivery-service/src/persistence/messages/syncAcknowledge.ts +++ b/packages/delivery-service/src/persistence/messages/syncAcknowledge.ts @@ -22,7 +22,7 @@ export function syncAcknowledge(redis: Redis) { //find the message with the given hash const message = messages.find( - (m) => m.metadata.encryptedMessageHash === messageHash, + (m) => m.metadata.messageHash === messageHash, ); //return if the message is not found diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index b130e7283..ea4bd0179 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-integration-tests", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "dependencies": { "@dm3-org/dm3-lib-delivery": "workspace:^", "@dm3-org/dm3-lib-messaging": "workspace:^", diff --git a/packages/lib/billboard-api/package.json b/packages/lib/billboard-api/package.json index 521426ec1..0c29b4222 100644 --- a/packages/lib/billboard-api/package.json +++ b/packages/lib/billboard-api/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-lib-billboard-client-api", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "types": "dist/index.d.ts", "exports": { diff --git a/packages/lib/crypto/package.json b/packages/lib/crypto/package.json index 23c70ac1f..ecc4a3490 100644 --- a/packages/lib/crypto/package.json +++ b/packages/lib/crypto/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-lib-crypto", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "module": "dist-backend/index.js", "types": "dist/index.d.ts", diff --git a/packages/lib/delivery-api/package.json b/packages/lib/delivery-api/package.json index a8c22be60..6109a2a11 100644 --- a/packages/lib/delivery-api/package.json +++ b/packages/lib/delivery-api/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-lib-delivery-api", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "types": "dist/index.d.ts", "exports": { diff --git a/packages/lib/delivery/package.json b/packages/lib/delivery/package.json index e7f884a69..666703064 100644 --- a/packages/lib/delivery/package.json +++ b/packages/lib/delivery/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-lib-delivery", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "module": "dist-backend/index.js", "types": "dist/index.d.ts", diff --git a/packages/lib/messaging/package.json b/packages/lib/messaging/package.json index 9cf9b3008..d9c355fc9 100644 --- a/packages/lib/messaging/package.json +++ b/packages/lib/messaging/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-lib-messaging", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "module": "dist-backend/index.js", "types": "dist/index.d.ts", diff --git a/packages/lib/messaging/src/Envelop.test.ts b/packages/lib/messaging/src/Envelop.test.ts index b5f48d3c9..67132fb39 100644 --- a/packages/lib/messaging/src/Envelop.test.ts +++ b/packages/lib/messaging/src/Envelop.test.ts @@ -141,11 +141,11 @@ describe('Envelope', () => { from: '', to: '', }, - encryptedMessageHash: - '0xc3428898a18e2cdb914e7eec870e45348c7f401d094968408524b787b43451d0', + messageHash: + '0xf2f8e4e1301481b3d7f11127adc11f5f4cf5faa8261296501d7726206ba35a85', version: 'v1', signature: - 'kKfGVNdGuZf5TrWa6ctQAuHwZQ8fSH36D4Hz+pxYA2UPNMNVZvWPwRmDjKEHMf3iWm8v/yh3BW7fwwk8ns4+AA==', + 'sHQCkcuocwB7E9iy2hzyvl45020vFNgDfEV/dAKaMal98svGl7Gk8h0vcXxmhNwZt+rJ0j+Bc6sgpoeiIBjBCQ==', }, }); }); diff --git a/packages/lib/messaging/src/Envelop.ts b/packages/lib/messaging/src/Envelop.ts index 1818ef44a..46fc629f9 100644 --- a/packages/lib/messaging/src/Envelop.ts +++ b/packages/lib/messaging/src/Envelop.ts @@ -20,7 +20,7 @@ export interface EnvelopeMetadata { version: string; encryptionScheme?: string; deliveryInformation: string | DeliveryInformation; - encryptedMessageHash: string; + messageHash: string; signature: string; } @@ -141,7 +141,7 @@ export async function buildEnvelop( /** * Builds the {@see EnvelopMetadata} for the message * and encrypts the {@see DeliveryInformation} using the deliveryServiceEncryptionPubKey - * the encryptedMessageHash field is mendatory to establish a link between the message and metadata + * the messageHash field is mendatory to establish a link between the message and metadata */ const envelopeMetadata: Omit = { encryptionScheme: 'x25519-chacha20-poly1305', @@ -151,7 +151,9 @@ export async function buildEnvelop( stringify(deliveryInformation), ), ), - encryptedMessageHash: sha256(stringify(encryptedMessage)), + //Even though the fields name is messageHash we hash the message to be able to find message duplicates + //For examples messages comming from the same DS + messageHash: sha256(stringify(message)), version: 'v1', }; diff --git a/packages/lib/messaging/src/MessageProxy.test.ts b/packages/lib/messaging/src/MessageProxy.test.ts index 0e7ab9ad3..1a0446f89 100644 --- a/packages/lib/messaging/src/MessageProxy.test.ts +++ b/packages/lib/messaging/src/MessageProxy.test.ts @@ -17,7 +17,7 @@ const proxyEnvelop = { encryptionEnvelop: { metadata: { deliveryInformation: stringify(encryptedPayloadMock), - encryptedMessageHash: + messageHash: '0xdac53d80a308eb9a48caca48719aada24a32f1cede2f4368817aa63b1375a09f', encryptionScheme: 'x25519-chacha20-poly1305', signature: @@ -31,7 +31,7 @@ const proxyEnvelop = { encryptionEnvelop: { metadata: { deliveryInformation: stringify(encryptedPayloadMock), - encryptedMessageHash: + messageHash: '0xdac53d80a308eb9a48caca48719aada24a32f1cede2f4368817aa63b1375a09f', encryptionScheme: 'x25519-chacha20-poly1305', signature: diff --git a/packages/lib/messaging/src/ProxyEnvelop.test.ts b/packages/lib/messaging/src/ProxyEnvelop.test.ts index 8f6ac5db7..c39f4a0f3 100644 --- a/packages/lib/messaging/src/ProxyEnvelop.test.ts +++ b/packages/lib/messaging/src/ProxyEnvelop.test.ts @@ -118,13 +118,13 @@ describe('ProxyEnvelope', () => { delete proxyEnvelop.encryptionEnvelops[0].encryptionEnvelop.metadata .signature; delete proxyEnvelop.encryptionEnvelops[0].encryptionEnvelop.metadata - .encryptedMessageHash; + .messageHash; delete proxyEnvelop.encryptionEnvelops[1].encryptionEnvelop.metadata .deliveryInformation; delete proxyEnvelop.encryptionEnvelops[1].encryptionEnvelop.metadata .signature; delete proxyEnvelop.encryptionEnvelops[1].encryptionEnvelop.metadata - .encryptedMessageHash; + .messageHash; expect(proxyEnvelop).toStrictEqual({ encryptionEnvelops: [ diff --git a/packages/lib/offchain-resolver-api/package.json b/packages/lib/offchain-resolver-api/package.json index 965767c5f..73ff5498b 100644 --- a/packages/lib/offchain-resolver-api/package.json +++ b/packages/lib/offchain-resolver-api/package.json @@ -1,6 +1,6 @@ { "name": "@dm3-org/dm3-lib-offchain-resolver-api", - "version": "1.6.0", + "version": "1.6.1", "license": "MIT", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/lib/profile/package.json b/packages/lib/profile/package.json index 8f6ed2031..907158b67 100644 --- a/packages/lib/profile/package.json +++ b/packages/lib/profile/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-lib-profile", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "module": "dist-backend/index.js", "types": "dist/index.d.ts", diff --git a/packages/lib/server-side/package.json b/packages/lib/server-side/package.json index 4b360270b..ab2fda487 100644 --- a/packages/lib/server-side/package.json +++ b/packages/lib/server-side/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-lib-server-side", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "module": "dist-backend/index.js", "types": "dist/index.d.ts", diff --git a/packages/lib/shared/package.json b/packages/lib/shared/package.json index 93c2d4fcf..f040c5022 100644 --- a/packages/lib/shared/package.json +++ b/packages/lib/shared/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-lib-shared", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "module": "dist-backend/index.js", "types": "dist/index.d.ts", diff --git a/packages/lib/storage/package.json b/packages/lib/storage/package.json index f28c6853f..53d86a9b8 100644 --- a/packages/lib/storage/package.json +++ b/packages/lib/storage/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-lib-storage", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "module": "dist-backend/index.js", "types": "dist/index.d.ts", diff --git a/packages/lib/storage/src/new/chunkStorage/testHelper.ts b/packages/lib/storage/src/new/chunkStorage/testHelper.ts index 60a77ae98..1f988378e 100644 --- a/packages/lib/storage/src/new/chunkStorage/testHelper.ts +++ b/packages/lib/storage/src/new/chunkStorage/testHelper.ts @@ -33,7 +33,7 @@ export function makeEnvelop( to: '', deliveryInstruction: '', }, - encryptedMessageHash: '', + messageHash: '', version: '', encryptionScheme: '', signature: '', diff --git a/packages/lib/storage/src/new/cloudStorage/getCloudStorage.ts b/packages/lib/storage/src/new/cloudStorage/getCloudStorage.ts index ff7c0fde6..619d785e7 100644 --- a/packages/lib/storage/src/new/cloudStorage/getCloudStorage.ts +++ b/packages/lib/storage/src/new/cloudStorage/getCloudStorage.ts @@ -147,8 +147,7 @@ export const getCloudStorage = ( await backendConnector.addMessage( ensName, encryptedContactName, - envelop.envelop.metadata?.encryptedMessageHash! ?? - envelop.envelop.id, + envelop.envelop.metadata?.messageHash! ?? envelop.envelop.id, createdAt, encryptedEnvelopContainer, isHalted, @@ -178,7 +177,7 @@ export const getCloudStorage = ( createdAt, messageId: storageEnvelopContainer.envelop.metadata - ?.encryptedMessageHash! ?? + ?.messageHash! ?? storageEnvelopContainer.envelop.id, isHalted: false, }; @@ -215,7 +214,7 @@ export const getCloudStorage = ( encryptedEnvelopContainer, messageId: storageEnvelopContainer.envelop.metadata - ?.encryptedMessageHash!, + ?.messageHash!, createdAt, isHalted: false, }; diff --git a/packages/lib/test-helper/package.json b/packages/lib/test-helper/package.json index 64f0e46c3..210e0b073 100644 --- a/packages/lib/test-helper/package.json +++ b/packages/lib/test-helper/package.json @@ -1,6 +1,6 @@ { "name": "@dm3-org/dm3-lib-test-helper", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "module": "dist-backend/index.js", "types": "dist/index.d.ts", diff --git a/packages/messenger-demo/package.json b/packages/messenger-demo/package.json index f5c33bf0f..7f6bacb62 100644 --- a/packages/messenger-demo/package.json +++ b/packages/messenger-demo/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-messenger-demo", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "dependencies": { "@dm3-org/dm3-messenger-widget": "workspace:^", "@popperjs/core": "^2.11.8", diff --git a/packages/messenger-web/package.json b/packages/messenger-web/package.json index bebf87096..172c7887a 100644 --- a/packages/messenger-web/package.json +++ b/packages/messenger-web/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-messenger-web", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "dependencies": { "@dm3-org/dm3-messenger-widget": "workspace:^", "@popperjs/core": "^2.11.8", diff --git a/packages/messenger-widget/package.json b/packages/messenger-widget/package.json index e8c78a4ca..2b937f258 100644 --- a/packages/messenger-widget/package.json +++ b/packages/messenger-widget/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-messenger-widget", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "./lib/cjs/widget.js", "module": "./lib/esm/widget.js", "types": "./lib/esm/widget.d.ts", diff --git a/packages/messenger-widget/src/components/AddConversation/AddConversation.tsx b/packages/messenger-widget/src/components/AddConversation/AddConversation.tsx index 7d6c5ab47..e606aea0a 100644 --- a/packages/messenger-widget/src/components/AddConversation/AddConversation.tsx +++ b/packages/messenger-widget/src/components/AddConversation/AddConversation.tsx @@ -13,6 +13,7 @@ import { } from '../../utils/enum-type-utils'; import { closeLoader, startLoader } from '../Loader/Loader'; import './AddConversation.css'; +import { normalizeEnsName } from '@dm3-org/dm3-lib-profile'; // class for input field export const INPUT_FIELD_CLASS = @@ -56,7 +57,8 @@ export default function AddConversation() { return; } - const newContact = await addConversation(tldName); + const normalizedEnsName = normalizeEnsName(tldName); + const newContact = await addConversation(normalizedEnsName); const addConversationData = { active: true, diff --git a/packages/messenger-widget/src/components/Chat/Chat.css b/packages/messenger-widget/src/components/Chat/Chat.css index ea469323e..8bf240cbb 100644 --- a/packages/messenger-widget/src/components/Chat/Chat.css +++ b/packages/messenger-widget/src/components/Chat/Chat.css @@ -57,6 +57,10 @@ height: auto; } +.infinite-scroll-component{ + overflow: visible !important; +} + /* =================== Mobile Responsive CSS =================== */ @media only screen and (max-width: 800px) { diff --git a/packages/messenger-widget/src/components/DeleteMessage/DeleteMessage.tsx b/packages/messenger-widget/src/components/DeleteMessage/DeleteMessage.tsx index 8554153e5..e2854dd8c 100644 --- a/packages/messenger-widget/src/components/DeleteMessage/DeleteMessage.tsx +++ b/packages/messenger-widget/src/components/DeleteMessage/DeleteMessage.tsx @@ -32,7 +32,7 @@ export default function DeleteMessage() { } const messageHash = - messageView.messageData?.envelop.metadata?.encryptedMessageHash; + messageView.messageData?.envelop.metadata?.messageHash; setMessageView(resetMessageView); diff --git a/packages/messenger-widget/src/components/EmojiModal/EmojiModal.tsx b/packages/messenger-widget/src/components/EmojiModal/EmojiModal.tsx index 0bb216673..963e28df3 100644 --- a/packages/messenger-widget/src/components/EmojiModal/EmojiModal.tsx +++ b/packages/messenger-widget/src/components/EmojiModal/EmojiModal.tsx @@ -76,8 +76,7 @@ export function EmojiModal(props: EmojiProps) { messageData: undefined, }); - const referenceMessageHash = - props.envelop.metadata?.encryptedMessageHash; + const referenceMessageHash = props.envelop.metadata?.messageHash; // react to the message const messageData = await createReactionMessage( diff --git a/packages/messenger-widget/src/components/Message/Message.tsx b/packages/messenger-widget/src/components/Message/Message.tsx index 6481909fa..45d635daa 100644 --- a/packages/messenger-widget/src/components/Message/Message.tsx +++ b/packages/messenger-widget/src/components/Message/Message.tsx @@ -19,7 +19,7 @@ export function Message(props: MessageProps) { return ( scrollToMessage( - props.replyToMessageEnvelop?.metadata - ?.encryptedMessageHash!, + props.replyToMessageEnvelop?.metadata?.messageHash!, ) } > diff --git a/packages/messenger-widget/src/components/MessageAction/MessageAction.tsx b/packages/messenger-widget/src/components/MessageAction/MessageAction.tsx index 2a24d8ee8..3c62b4c7a 100644 --- a/packages/messenger-widget/src/components/MessageAction/MessageAction.tsx +++ b/packages/messenger-widget/src/components/MessageAction/MessageAction.tsx @@ -75,8 +75,7 @@ export function MessageAction(props: MessageProps) { messageData: undefined, }); - const referenceMessageHash = - props.envelop.metadata?.encryptedMessageHash; + const referenceMessageHash = props.envelop.metadata?.messageHash; // react to the message const messageData = await createReactionMessage( @@ -157,7 +156,7 @@ export function MessageAction(props: MessageProps) { (props.message || (props.envelop.message.attachments && props.envelop.message.attachments.length > 0)) && - props.envelop.metadata?.encryptedMessageHash && + props.envelop.metadata?.messageHash && (!props.hideFunction || !props.hideFunction.split(',').includes('edit')) && (
0)) && - props.envelop.metadata?.encryptedMessageHash && ( + props.envelop.metadata?.messageHash && (
(false); const resetMessageView = { actionType: MessageActionType.NONE, @@ -31,6 +32,10 @@ export function MessageInputField(props: MessageDataProps) { async function submit(event: React.FormEvent) { event.preventDefault(); + if (isSendBtnDisabled) { + return; + } + setIsSendBtnDisabled(true); await onSubmitMessage( messageView, setMessageView, @@ -41,6 +46,7 @@ export function MessageInputField(props: MessageDataProps) { account!, selectedContact!, ); + setIsSendBtnDisabled(false); } // Focus on input field when user selects a msg to EEDIT or REPLY diff --git a/packages/messenger-widget/src/components/SendMessage/SendMessage.tsx b/packages/messenger-widget/src/components/SendMessage/SendMessage.tsx index cd49f7eae..61d4ce27c 100644 --- a/packages/messenger-widget/src/components/SendMessage/SendMessage.tsx +++ b/packages/messenger-widget/src/components/SendMessage/SendMessage.tsx @@ -1,5 +1,5 @@ import './SendMessage.css'; -import { useContext } from 'react'; +import { useContext, useState } from 'react'; import sendBtnIcon from '../../assets/images/send-btn.svg'; import { AuthContext } from '../../context/AuthContext'; import { ConversationContext } from '../../context/ConversationContext'; @@ -15,8 +15,13 @@ export function SendMessage(props: MessageDataProps) { const { selectedContact } = useContext(ConversationContext); const { messageView, setMessageView } = useContext(UiViewContext); const { setLastMessageAction } = useContext(ModalContext); + const [isSendBtnDisabled, setIsSendBtnDisabled] = useState(false); async function submit() { + if (isSendBtnDisabled) { + return; + } + setIsSendBtnDisabled(true); await onSubmitMessage( messageView, setMessageView, @@ -27,6 +32,7 @@ export function SendMessage(props: MessageDataProps) { account!, selectedContact!, ); + setIsSendBtnDisabled(false); } return ( diff --git a/packages/messenger-widget/src/components/SendMessage/onSubmitMessage.ts b/packages/messenger-widget/src/components/SendMessage/onSubmitMessage.ts index 3d6f8d24e..1e801a63b 100644 --- a/packages/messenger-widget/src/components/SendMessage/onSubmitMessage.ts +++ b/packages/messenger-widget/src/components/SendMessage/onSubmitMessage.ts @@ -21,9 +21,17 @@ export const onSubmitMessage = async ( account: Account, selectedContact: ContactPreview, ) => { + // Message can't be empty if no files are selected & its not DELETE msg. + if ( + messageView.actionType !== MessageActionType.DELETE && + !props.filesSelected.length && + (!props.message || props.message.trim() === '') + ) { + return; + } if (messageView.actionType === MessageActionType.REPLY) { const referenceMessageHash = - messageView.messageData?.envelop.metadata?.encryptedMessageHash; + messageView.messageData?.envelop.metadata?.messageHash; const messageData = await createReplyMessage( selectedContact?.contactDetails.account.ensName!, @@ -59,7 +67,7 @@ export const onSubmitMessage = async ( } if (messageView.actionType === MessageActionType.EDIT) { const referenceMessageHash = - messageView.messageData?.envelop.metadata?.encryptedMessageHash; + messageView.messageData?.envelop.metadata?.messageHash; // reply to the original message const messageData = await createEditMessage( diff --git a/packages/messenger-widget/src/hooks/conversation/useConversation.tsx b/packages/messenger-widget/src/hooks/conversation/useConversation.tsx index 59c6eb2b8..20c96c393 100644 --- a/packages/messenger-widget/src/hooks/conversation/useConversation.tsx +++ b/packages/messenger-widget/src/hooks/conversation/useConversation.tsx @@ -16,6 +16,7 @@ import { DM3Configuration } from '../../interfaces/config'; import { ContactPreview, getEmptyContact } from '../../interfaces/utils'; import { useMainnetProvider } from '../mainnetprovider/useMainnetProvider'; import { hydrateContract } from './hydrateContact'; +import { ethers } from 'ethers'; const DEFAULT_CONVERSATION_PAGE_SIZE = 10; @@ -224,13 +225,21 @@ export const useConversation = (config: DM3Configuration) => { const contactTldName = normalizeEnsName(_ensName); //rrsolves the TLD name. That name becomes the identifier for the conversation const aliasName = await resolveTLDtoAlias(contactTldName); + + const defaultProfileLocation = ethers.utils.isAddress(contactTldName) + ? normalizeEnsName( + contactTldName + dm3Configuration.addressEnsSubdomain, + ) + : contactTldName; + const newConversation: Conversation = { contactEnsName: aliasName, - contactProfileLocation: [contactTldName], //(ID) + contactProfileLocation: [defaultProfileLocation], //(ID) isHidden: false, previewMessage: undefined, updatedAt: new Date().getTime(), }; + //Adds the conversation to the conversation state const conversationPreview = _addConversation(newConversation); //Add the contact to the storage in the background diff --git a/packages/messenger-widget/src/hooks/messages/receipt/ReceiptDispatcher.ts b/packages/messenger-widget/src/hooks/messages/receipt/ReceiptDispatcher.ts index 57081eeb4..bded908c2 100644 --- a/packages/messenger-widget/src/hooks/messages/receipt/ReceiptDispatcher.ts +++ b/packages/messenger-widget/src/hooks/messages/receipt/ReceiptDispatcher.ts @@ -31,7 +31,7 @@ export class ReceiptDispatcher { this.account!.ensName, 'READ_OPENED', this.profileKeys?.signingKeyPair.privateKey!, - messageModel.envelop.metadata?.encryptedMessageHash as string, + messageModel.envelop.metadata?.messageHash as string, ); //add the message to dispatch it via useMessage hook @@ -47,7 +47,7 @@ export class ReceiptDispatcher { this.account!.ensName, 'READ_RECEIVED', this.profileKeys?.signingKeyPair.privateKey!, - messageModel.envelop.metadata?.encryptedMessageHash as string, + messageModel.envelop.metadata?.messageHash as string, ); //add the message to dispatch it via useMessage hook @@ -71,8 +71,10 @@ export class ReceiptDispatcher { contactAliasName: string, messageModel: MessageModel, ) { - //We only want to acknowledge messages from type NEW. Every other message type can be neglected for now - const msgIsNew = messageModel.envelop.message.metadata.type === 'NEW'; + //We only want to acknowledge messages from type NEW or REPLY. Every other message type can be neglected for now + const shouldAcknowledgeMessage = + messageModel.envelop.message.metadata.type === 'NEW' || + messageModel.envelop.message.metadata.type === 'REPLY'; //Check if the selected contact is the sender of the message. // If that is the case we've to acknowledge the message and send a READ_OPENED acknowledgement to the sender const selectedContactIsSender = @@ -80,15 +82,15 @@ export class ReceiptDispatcher { contactAliasName; //We acknowledge that we've received the message by sending a READ_RECEIVED acknowledgement to the sender - if (msgIsNew) { + if (shouldAcknowledgeMessage) { await this.sendReceivedReceipte(contactAliasName, messageModel); console.log('sent received receipt to ', contactAliasName); } - if (msgIsNew && selectedContactIsSender) { + if (shouldAcknowledgeMessage && selectedContactIsSender) { // if contact is selected then send READ_OPENED acknowledgement to sender for new message received await this.sendOpendReceipt(contactAliasName, messageModel); - console.log('sent opend receipt to ', contactAliasName); + console.log('sent opened receipt to ', contactAliasName); } } } diff --git a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderDelete.ts b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderDelete.ts index 69f7db76b..e4c9d3267 100644 --- a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderDelete.ts +++ b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderDelete.ts @@ -24,7 +24,7 @@ export const renderDelete = (messages: MessageModel[]) => { .map((message) => { if ( toBeDeletedByMessageHash.includes( - message.envelop.metadata?.encryptedMessageHash, + message.envelop.metadata?.messageHash, ) ) { return { diff --git a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderDuplicates.ts b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderDuplicates.ts index 16179f645..769050c93 100644 --- a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderDuplicates.ts +++ b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderDuplicates.ts @@ -7,8 +7,8 @@ export const renderDuplicates = (messages: MessageModel[]) => { index === self.findIndex( (t) => - t.envelop.metadata?.encryptedMessageHash === - message.envelop.metadata?.encryptedMessageHash, + t.envelop.metadata?.messageHash === + message.envelop.metadata?.messageHash, ), ); }; diff --git a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderEdit.ts b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderEdit.ts index f96952f3c..4df174d69 100644 --- a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderEdit.ts +++ b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderEdit.ts @@ -1,6 +1,14 @@ import { MessageModel } from '../../useMessage'; -export const renderEdit = (messages: MessageModel[]) => { +export const renderEdit = (_messages: MessageModel[]) => { + //Copy messages object to not mutate the original object + const messages: MessageModel[] = [..._messages]; + //Before processing the messages have to be sorted ASC by timestamp + messages.sort( + (a, b) => + a.envelop.message.metadata.timestamp - + b.envelop.message.metadata.timestamp, + ); //To apply insertions we have to find every message that is an edit and find the original message //A message can be edited multiple times so we always have to find the original message //A path for a simple edit looks like [NEW, EDIT] @@ -24,7 +32,7 @@ export const renderEdit = (messages: MessageModel[]) => { while (currentMsg.envelop.message.metadata.type === 'EDIT') { const originalMsg = messages.find( (m, i) => - m.envelop.metadata?.encryptedMessageHash === + m.envelop.metadata?.messageHash === currentMsg.envelop.message.metadata.referenceMessageHash, ); if (!originalMsg) { diff --git a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReactions.ts b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReactions.ts index cb54f878c..d6f7c4646 100644 --- a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReactions.ts +++ b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReactions.ts @@ -16,7 +16,7 @@ export const renderReactions = (messages: MessageModel[]) => { .filter( (reaction) => reaction.message.metadata.referenceMessageHash === - message.envelop.metadata?.encryptedMessageHash, + message.envelop.metadata?.messageHash, ) //Filter duplicates, we only want to display a reaction once //I.e if there are ten messages from type ❤️ we only want to display one ❤️ diff --git a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReadOpened.ts b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReadOpened.ts index 7409a2cc0..c729c204e 100644 --- a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReadOpened.ts +++ b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReadOpened.ts @@ -15,7 +15,7 @@ export const renderReadOpened = (messages: MessageModel[]) => { const openedMsg = readOpenedMsgs.find( (m) => m.envelop.message.metadata.referenceMessageHash === - message.envelop.metadata?.encryptedMessageHash, + message.envelop.metadata?.messageHash, ); return { ...message, diff --git a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReadReceived.ts b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReadReceived.ts index 1a0b4c79c..9d9f81d4a 100644 --- a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReadReceived.ts +++ b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReadReceived.ts @@ -15,7 +15,7 @@ export const renderReadReceived = (messages: MessageModel[]) => { const receivedMsg = readReceivedMsgs.find( (m) => m.envelop.message.metadata.referenceMessageHash === - message.envelop.metadata?.encryptedMessageHash, + message.envelop.metadata?.messageHash, ); return { ...message, diff --git a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReply.ts b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReply.ts index 443b164a1..6ce8b3305 100644 --- a/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReply.ts +++ b/packages/messenger-widget/src/hooks/messages/renderer/messageTypes/renderReply.ts @@ -6,7 +6,7 @@ export const renderReply = (messages: MessageModel[]) => { //TODO we've to figure out how to get a message from a different chunk (Alex) const replyToMessageEnvelop = messages.find( (m) => - m.envelop.metadata?.encryptedMessageHash === + m.envelop.metadata?.messageHash === message.envelop.message.metadata.referenceMessageHash, ); return { diff --git a/packages/messenger-widget/src/hooks/messages/renderer/renderMessage.ts b/packages/messenger-widget/src/hooks/messages/renderer/renderMessage.ts index 47bc1c9bf..96b3966f3 100644 --- a/packages/messenger-widget/src/hooks/messages/renderer/renderMessage.ts +++ b/packages/messenger-widget/src/hooks/messages/renderer/renderMessage.ts @@ -20,19 +20,17 @@ export const renderMessage = (messages: MessageModel[]) => { const withReactions = renderReactions(withDeletes); const withReply = renderReply(withReactions); - //Its desirable to have all messages in a conversation sorted by their timestamp. However edited messages are an - //exception to this rule, since they should be displayed in the order they were edited. - // Therefore we sort the messages by their timestamp and then we eventually replace messages that have been edited - //Messages are sorted DESC, so the pagination adds old messages at the end of the array - withReply.sort( - (a, b) => - b.envelop.message.metadata.timestamp - - a.envelop.message.metadata.timestamp, - ); const withoutEdited = renderEdit(withReply); + //Sort the messages by timestamp DESC to show them in the right order + // withoutEdited.sort( + // (a, b) => + // b.envelop.message.metadata.timestamp - + // a.envelop.message.metadata.timestamp, + // ); //There a several ways a message can added to the client. I.e via Websocket, multiple DS or from the storage. //This leads occasionally to duplicates we don't want to display. const withoutDuplicates = renderDuplicates(withoutEdited); - return withoutDuplicates; + //We reverse the array to display the messages in the right order + return withoutDuplicates.reverse(); }; diff --git a/packages/messenger-widget/src/hooks/messages/sources/handleMessagesFromDeliveryService.ts b/packages/messenger-widget/src/hooks/messages/sources/handleMessagesFromDeliveryService.ts index 42d584398..1c9003f84 100644 --- a/packages/messenger-widget/src/hooks/messages/sources/handleMessagesFromDeliveryService.ts +++ b/packages/messenger-widget/src/hooks/messages/sources/handleMessagesFromDeliveryService.ts @@ -147,8 +147,7 @@ export const handleMessagesFromDeliveryService = async ( //Here we use the TLD name because the delivery service uses the TLD name to identify the contact //We cannot just use teh messageId because redis prevents us from finding messages by ID contactAddress: conversation.tldName, - messageHash: - message.envelop.metadata?.encryptedMessageHash!, + messageHash: message.envelop.metadata?.messageHash!, }), ); //sync acknowledgements with the delivery serviceƒƒ diff --git a/packages/messenger-widget/src/hooks/messages/sources/handleMessagesFromWebSocket.ts b/packages/messenger-widget/src/hooks/messages/sources/handleMessagesFromWebSocket.ts index 08070df27..0341f0fc2 100644 --- a/packages/messenger-widget/src/hooks/messages/sources/handleMessagesFromWebSocket.ts +++ b/packages/messenger-widget/src/hooks/messages/sources/handleMessagesFromWebSocket.ts @@ -4,7 +4,7 @@ import { Envelop, MessageState, } from '@dm3-org/dm3-lib-messaging'; -import { ProfileKeys } from '@dm3-org/dm3-lib-profile'; +import { normalizeEnsName, ProfileKeys } from '@dm3-org/dm3-lib-profile'; import { ContactPreview } from '../../../interfaces/utils'; import { StoreMessageAsync } from '../../storage/useStorage'; import { ReceiptDispatcher } from '../receipt/ReceiptDispatcher'; @@ -40,14 +40,12 @@ export const handleMessagesFromWebSocket = async ( //we wait for the contact to be added to resolve TLD to alias const contactPreview = await addConversation( - decryptedEnvelop.message.metadata.from, + normalizeEnsName(decryptedEnvelop.message.metadata.from), ); // Resolve TLD to alias const contact = contactPreview?.contactDetails.account.ensName!; - console.log('contactPreview MSGWS', contactPreview); - const messageState = selectedContact?.contactDetails.account.ensName === contact ? MessageState.Read @@ -65,8 +63,8 @@ export const handleMessagesFromWebSocket = async ( if ( prev[contact]?.find( (m) => - m.envelop.metadata?.encryptedMessageHash === - messageModel.envelop.metadata?.encryptedMessageHash, + m.envelop.metadata?.messageHash === + messageModel.envelop.metadata?.messageHash, ) ) { return prev; diff --git a/packages/messenger-widget/src/hooks/messages/useMessage.test.tsx b/packages/messenger-widget/src/hooks/messages/useMessage.test.tsx index 7ab13d86e..e97806b25 100644 --- a/packages/messenger-widget/src/hooks/messages/useMessage.test.tsx +++ b/packages/messenger-widget/src/hooks/messages/useMessage.test.tsx @@ -92,132 +92,6 @@ describe('useMessage hook test cases', () => { }); const config: DM3Configuration = configurationContext.dm3Configuration!; - it('should not add empty message', async () => { - const storageContext = getMockedStorageContext({ - editMessageBatchAsync: jest.fn(), - storeMessageBatch: jest.fn(), - storeMessage: jest.fn(), - }); - const conversationContext = getMockedConversationContext({ - selectedContact: getEmptyContact( - 'max.eth', - undefined, - false, - 0, - [], - ), - }); - const deliveryServiceContext = getMockedDeliveryServiceContext({ - //Add websocket mock - onNewMessage: (cb: Function) => { - console.log('on new message'); - }, - removeOnNewMessageListener: jest.fn(), - }); - const authContext = getMockedAuthContext({}); - const tldContext = getMockedTldContext({}); - - const wrapper = ({ children }: { children: any }) => ( - <> - - - - - - {children} - - - - - - - ); - - const { result } = renderHook(() => useMessage(), { - wrapper, - }); - await waitFor(() => - expect(result.current.contactIsLoading('max.eth')).toBe(false), - ); - - const messageFactory = MockMessageFactory(sender, receiver, ds1); - const message = await messageFactory.createMessage(''); - const addMessageResult = await waitFor(() => - result.current.addMessage('max.eth', message), - ); - - expect(addMessageResult).toEqual({ - isSuccess: false, - error: 'Message is empty', - }); - }); - it('should trim message', async () => { - const storageContext = getMockedStorageContext({ - editMessageBatchAsync: jest.fn(), - storeMessageBatch: jest.fn(), - storeMessage: jest.fn(), - }); - const conversationContext = getMockedConversationContext({ - selectedContact: getEmptyContact( - 'max.eth', - undefined, - false, - 0, - [], - ), - }); - const deliveryServiceContext = getMockedDeliveryServiceContext({ - //Add websocket mock - onNewMessage: (cb: Function) => { - console.log('on new message'); - }, - removeOnNewMessageListener: jest.fn(), - }); - const authContext = getMockedAuthContext({}); - const tldContext = getMockedTldContext({}); - - const wrapper = ({ children }: { children: any }) => ( - <> - - - - - - {children} - - - - - - - ); - - const { result } = renderHook(() => useMessage(), { - wrapper, - }); - await waitFor(() => - expect(result.current.contactIsLoading('max.eth')).toBe(false), - ); - - const messageFactory = MockMessageFactory(sender, receiver, ds1); - const message = await messageFactory.createMessage(' '); - const addMessageResult = await waitFor(() => - result.current.addMessage('max.eth', message), - ); - - expect(addMessageResult).toEqual({ - isSuccess: false, - error: 'Message is empty', - }); - }); it('should add message', async () => { const storageContext = getMockedStorageContext({ editMessageBatchAsync: jest.fn(), @@ -868,15 +742,15 @@ describe('useMessage hook test cases', () => { [ { contactAddress: sender.account.ensName, - messageHash: message1.metadata.encryptedMessageHash, + messageHash: message1.metadata.messageHash, }, { contactAddress: sender.account.ensName, - messageHash: message2.metadata.encryptedMessageHash, + messageHash: message2.metadata.messageHash, }, { contactAddress: sender.account.ensName, - messageHash: message3.metadata.encryptedMessageHash, + messageHash: message3.metadata.messageHash, }, ], ); diff --git a/packages/messenger-widget/src/hooks/messages/useMessage.tsx b/packages/messenger-widget/src/hooks/messages/useMessage.tsx index d41476487..63e007c93 100644 --- a/packages/messenger-widget/src/hooks/messages/useMessage.tsx +++ b/packages/messenger-widget/src/hooks/messages/useMessage.tsx @@ -276,12 +276,6 @@ export const useMessage = () => { message: Message, ): Promise<{ isSuccess: boolean; error?: string }> => { const contact = normalizeEnsName(_contactName); - //If a message is empty it should not be added - - if (!message.message || message.message.trim() === '') { - return { isSuccess: false, error: 'Message is empty' }; - } - //Find the recipient of the message in the contact list const recipient = contacts.find( (c) => c.contactDetails.account.ensName === contact, @@ -331,7 +325,7 @@ export const useMessage = () => { deliveryInformation: '', //Because storing a message is always an internal process we dont need to sign it. The signature is only needed for the delivery service signature: '', - encryptedMessageHash: sha256(stringify(message)), + messageHash: sha256(stringify(message)), version: 'v1', }, }, @@ -495,15 +489,15 @@ export const useMessage = () => { newMessages //filter duplicates .filter((message, index, self) => { - if (!message.envelop.metadata?.encryptedMessageHash) { + if (!message.envelop.metadata?.messageHash) { return true; } return ( index === self.findIndex( (m) => - m.envelop.metadata?.encryptedMessageHash === - message.envelop.metadata?.encryptedMessageHash, + m.envelop.metadata?.messageHash === + message.envelop.metadata?.messageHash, ) ); }); diff --git a/packages/messenger-widget/src/hooks/topLevelAlias/nameService/EthAddress.ts b/packages/messenger-widget/src/hooks/topLevelAlias/nameService/EthAddress.ts index 97348f30e..bca34c450 100644 --- a/packages/messenger-widget/src/hooks/topLevelAlias/nameService/EthAddress.ts +++ b/packages/messenger-widget/src/hooks/topLevelAlias/nameService/EthAddress.ts @@ -14,9 +14,11 @@ export class EthAddressResolver implements ITLDResolver { return ensName.endsWith(this.addrEnsSubdomain); } //The alias format is used to display in the UI - //e.g. 0x1234.user.dm3.eth -> 0x1234 + //Since that is the lowest tier there is no alias for such an tldName left. + //e.g. 0x1234.user.dm3.eth -> 0x1234.user.dm3.eth async resolveAliasToTLD(ensName: string): Promise { - return ensName.split('.')[0]; + //return ensName.split('.')[0]; + return ensName; } //The alias format is used to store the contact in the DB //e.g. 0x1234 -> 0x1234.user.dm3.eth diff --git a/packages/messenger-widget/src/hooks/topLevelAlias/useTopLevelAlias.ts b/packages/messenger-widget/src/hooks/topLevelAlias/useTopLevelAlias.ts index 46450129f..dc062fa3f 100644 --- a/packages/messenger-widget/src/hooks/topLevelAlias/useTopLevelAlias.ts +++ b/packages/messenger-widget/src/hooks/topLevelAlias/useTopLevelAlias.ts @@ -10,6 +10,7 @@ import { OptimismNames } from './nameService/OptimismNames'; import { DM3Configuration } from '../../interfaces/config'; import { ITLDResolver } from './nameService/ITLDResolver'; import { ForeignName } from './nameService/ForeignName'; +import { normalizeEnsName } from '@dm3-org/dm3-lib-profile'; const SUPPORTED_NAMESERVICES = ( provider: ethers.providers.JsonRpcProvider, @@ -63,9 +64,11 @@ export const useTopLevelAlias = () => { foreignTldName, ) ) { - const tldName = await nameservice.resolveAliasToTLD( - ensName, - foreignTldName, + const tldName = normalizeEnsName( + await nameservice.resolveAliasToTLD( + ensName, + foreignTldName, + ), ); setAliasTldCache((prev) => ({ ...prev, [ensName]: tldName })); return tldName; @@ -83,7 +86,9 @@ export const useTopLevelAlias = () => { dm3Configuration, )) { if (await nameservice.isResolverForTldName(ensName)) { - const aliasName = await nameservice.resolveTLDtoAlias(ensName); + const aliasName = normalizeEnsName( + await nameservice.resolveTLDtoAlias(ensName), + ); setTldAliasCache((prev) => ({ ...prev, [ensName]: aliasName })); return aliasName; } diff --git a/packages/offchain-resolver/package.json b/packages/offchain-resolver/package.json index 976c373ef..1b2fac0a9 100644 --- a/packages/offchain-resolver/package.json +++ b/packages/offchain-resolver/package.json @@ -1,7 +1,7 @@ { "name": "@dm3-org/dm3-offchain-resolver", "license": "BSD-2-Clause", - "version": "1.6.0", + "version": "1.6.1", "main": "dist/index.js", "types": "dist/index.d.ts", "dependencies": { diff --git a/packages/toplevel-alias/package-lock.json b/packages/toplevel-alias/package-lock.json index 8185de813..b077ec56b 100644 --- a/packages/toplevel-alias/package-lock.json +++ b/packages/toplevel-alias/package-lock.json @@ -103,7 +103,7 @@ } }, "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", "dev": true, @@ -1603,7 +1603,7 @@ } }, "node_modules/@scure/bip32": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", "dev": true, @@ -1631,7 +1631,7 @@ } }, "node_modules/@scure/bip32/node_modules/@noble/hashes": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", "dev": true, @@ -2400,7 +2400,7 @@ } }, "node_modules/browser-stdout": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true @@ -2750,7 +2750,7 @@ "dev": true }, "node_modules/colors": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true, @@ -4347,7 +4347,7 @@ "peer": true }, "node_modules/interpret": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, @@ -4532,7 +4532,7 @@ } }, "node_modules/jsonschema": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", "dev": true, @@ -4567,7 +4567,7 @@ } }, "node_modules/klaw": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", "dev": true, @@ -4842,7 +4842,7 @@ } }, "node_modules/merge2": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, @@ -5277,7 +5277,7 @@ "dev": true }, "node_modules/once": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, @@ -7108,7 +7108,7 @@ } }, "node_modules/web3-utils/node_modules/@noble/hashes": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", "dev": true, @@ -7134,7 +7134,7 @@ } }, "node_modules/which": { - "version": "1.6.0", + "version": "1.6.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, diff --git a/test-data/encrypted-envelops.test.ts b/test-data/encrypted-envelops.test.ts index 8c54f248a..e2b907d89 100644 --- a/test-data/encrypted-envelops.test.ts +++ b/test-data/encrypted-envelops.test.ts @@ -8,7 +8,7 @@ export const testData = { deliveryInformation: '{"ciphertext":"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","nonce":"0x5f564ab2e955e921e131621e","ephemPublicKey":"yhl5dtz+xbvMczZtysmFiQ5Mi30cJcitqiz33cIAPy4="}', signature: '', - encryptedMessageHash: '', + messageHash: '', version: '', encryptionScheme: 'x25519-chacha20-poly1305', }, @@ -19,7 +19,7 @@ export const testData = { deliveryInformation: '{"ciphertext":"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","nonce":"0x55d8d963b4712d3b74a1c3f7","ephemPublicKey":"JswCtQ84+mfSYSE8+MzzUsjYG4aSZIBZIvA0IIvUGn4="}', signature: '', - encryptedMessageHash: '', + messageHash: '', version: '', encryptionScheme: 'x25519-chacha20-poly1305', },