diff --git a/src/Client.ts b/src/Client.ts index 217d9e5de..50b233abf 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -779,7 +779,7 @@ async function getUserContactFromNetwork( address = undefined } - if (address === peerAddress) { + if (address?.toLowerCase() === peerAddress.toLowerCase()) { return keyBundle } } @@ -815,7 +815,7 @@ async function getUserContactsFromNetwork( try { const keyBundle = decodeContactBundle(env.message) const signingAddress = await keyBundle?.walletSignatureAddress() - if (address === signingAddress) { + if (address.toLowerCase() === signingAddress.toLowerCase()) { return keyBundle } else { console.info('Received contact bundle with incorrect address') diff --git a/src/conversations/Conversations.ts b/src/conversations/Conversations.ts index 1423daf35..efabd1e86 100644 --- a/src/conversations/Conversations.ts +++ b/src/conversations/Conversations.ts @@ -360,7 +360,8 @@ export default class Conversations { if (msg instanceof DecodedMessage && msg.contentTopic === introTopic) { const convo = new ConversationV1( this.client, - msg.recipientAddress === this.client.address + msg.recipientAddress?.toLowerCase() === + this.client.address.toLowerCase() ? (msg.senderAddress as string) : (msg.recipientAddress as string), msg.sent @@ -474,7 +475,7 @@ export default class Conversations { throw new Error(`Recipient ${peerAddress} is not on the XMTP network`) } - if (peerAddress === this.client.address) { + if (peerAddress.toLowerCase() === this.client.address.toLowerCase()) { throw new Error('self messaging not supported') } @@ -487,7 +488,7 @@ export default class Conversations { if (!context?.conversationId) { const v1Convos = await this.listV1Conversations() const matchingConvo = v1Convos.find( - (convo) => convo.peerAddress === peerAddress + (convo) => convo.peerAddress.toLowerCase() === peerAddress.toLowerCase() ) // If intro already exists, return V1 conversation // if both peers have V1 compatible key bundles @@ -516,7 +517,7 @@ export default class Conversations { // Define a function for matching V2 conversations const matcherFn = (convo: Conversation) => - convo.peerAddress === peerAddress && + convo.peerAddress.toLowerCase() === peerAddress.toLowerCase() && isMatchingContext(context, convo.context ?? undefined) const existing = await this.getV2ConversationsFromKeystore() @@ -571,7 +572,8 @@ export default class Conversations { private getPeerAddress(message: MessageV1): string { const peerAddress = - message.recipientAddress === this.client.address + message.recipientAddress?.toLowerCase() === + this.client.address.toLowerCase() ? message.senderAddress : message.recipientAddress diff --git a/test/conversations/Conversation.test.ts b/test/conversations/Conversation.test.ts index 4bab7bf10..e7e354768 100644 --- a/test/conversations/Conversation.test.ts +++ b/test/conversations/Conversation.test.ts @@ -128,6 +128,9 @@ describe('conversation', () => { expect( alice.conversations.newConversation(alice.address) ).rejects.toThrow('self messaging not supported') + expect( + alice.conversations.newConversation(alice.address.toLowerCase()) + ).rejects.toThrow('self messaging not supported') }) it('can send a prepared message v1', async () => { diff --git a/test/conversations/Conversations.test.ts b/test/conversations/Conversations.test.ts index aff73b602..77aca19ff 100644 --- a/test/conversations/Conversations.test.ts +++ b/test/conversations/Conversations.test.ts @@ -261,6 +261,19 @@ describe('conversations', () => { expect(bobConvo instanceof ConversationV1).toBeTruthy() }) + it('does not create a duplicate conversation with an address case mismatch', async () => { + const convo1 = await alice.conversations.newConversation(bob.address) + await convo1.send('gm') + const convos = await alice.conversations.list() + expect(convos).toHaveLength(1) + const convo2 = await alice.conversations.newConversation( + bob.address.toLowerCase() + ) + await convo2.send('gm') + const convos2 = await alice.conversations.list() + expect(convos2).toHaveLength(1) + }) + it('continues to use v1 conversation even after upgrading bundle', async () => { const aliceConvo = await alice.conversations.newConversation(bob.address) await aliceConvo.send('gm')