diff --git a/package-lock.json b/package-lock.json index d4d725de6..49612d1ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -129,17 +129,89 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.21.4", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", @@ -189,12 +261,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", - "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "dependencies": { - "@babel/types": "^7.21.4", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -247,34 +319,34 @@ "dev": true }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -333,30 +405,30 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" @@ -386,13 +458,13 @@ } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -471,9 +543,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -674,33 +746,33 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", - "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.4", - "@babel/types": "^7.21.4", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -718,13 +790,13 @@ } }, "node_modules/@babel/types": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", - "integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2042,6 +2114,14 @@ "@ethersproject/strings": "^5.5.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", + "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==", + "engines": { + "node": ">=14" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.11", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", @@ -4746,9 +4826,9 @@ "integrity": "sha512-SBxBxQCX0weIIHgrVxZ0QmAX7bqjhBsheXtmcgiciC/ZyAB7UC0KsNx2xqYrIDE0YQm6WXRg90qsX7a30SrLfQ==" }, "node_modules/@xmtp/proto": { - "version": "3.28.0-beta.1", - "resolved": "https://registry.npmjs.org/@xmtp/proto/-/proto-3.28.0-beta.1.tgz", - "integrity": "sha512-gbDQ1FXKZe0j9RZxBK0Ohyy8C4z5I+ko58xmHk+QGO4QYb+cGsJyDSe0Re3oUa1tlnNudV0fkTR4nxcq4D+oIw==", + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/@xmtp/proto/-/proto-3.29.0.tgz", + "integrity": "sha512-+ibo+u6NwdzfLN3QEDMiNrnXd7eT1/+F2j5WWz3b4mk91wgn8lJ66fxFPwLTQs6AbaBBUmhO2cdpgIL/g4kvZg==", "dependencies": { "long": "^5.2.0", "protobufjs": "^7.0.0", @@ -5470,17 +5550,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -17588,14 +17657,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -18536,11 +18597,11 @@ } }, "node_modules/undici": { - "version": "5.23.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.23.0.tgz", - "integrity": "sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg==", + "version": "5.26.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.26.3.tgz", + "integrity": "sha512-H7n2zmKEWgOllKkIUkLvFmsJQj062lSm3uA4EYApG8gLuiOM0/go9bIoC3HVaSnfg4xunowDE2i9p8drkXuvDw==", "dependencies": { - "busboy": "^1.6.0" + "@fastify/busboy": "^2.0.0" }, "engines": { "node": ">=14.0" diff --git a/package.json b/package.json index f416f35a6..dcf5a5e05 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "updateSnapVersion": "npm view @xmtp/snap --json | jq '{\"version\": .version, \"package\": .name}' > ./src/snapInfo.json", "test:setup": "./dev/up", "test:teardown": "./dev/down", - "test": "npm run test:node", + "test": "npm run test:node --", "test:node": "jest --no-cache --env='node' --testTimeout=30000", "test:jsdom": "jest --no-cache --env='./jest.jsdom.env.cjs' --testTimeout=30000", "test:cov": "jest --coverage --no-cache --runInBand", 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/PreparedMessage.ts b/src/PreparedMessage.ts index fcd1482c8..0a59313da 100644 --- a/src/PreparedMessage.ts +++ b/src/PreparedMessage.ts @@ -1,12 +1,16 @@ import { Envelope } from '@xmtp/proto/ts/dist/types/message_api/v1/message_api.pb' import { bytesToHex } from './crypto/utils' import { sha256 } from './crypto/encryption' +import { DecodedMessage } from './Message' export class PreparedMessage { messageEnvelope: Envelope - onSend: () => Promise + onSend: () => Promise - constructor(messageEnvelope: Envelope, onSend: () => Promise) { + constructor( + messageEnvelope: Envelope, + onSend: () => Promise + ) { this.messageEnvelope = messageEnvelope this.onSend = onSend } @@ -20,6 +24,6 @@ export class PreparedMessage { } async send() { - await this.onSend() + return this.onSend() } } diff --git a/src/conversations/Conversation.ts b/src/conversations/Conversation.ts index e8380411d..65fb7fccf 100644 --- a/src/conversations/Conversation.ts +++ b/src/conversations/Conversation.ts @@ -235,22 +235,25 @@ export class ConversationV1 recipient = recipient.toLegacyBundle() } + const topic = options?.ephemeral ? this.ephemeralTopic : this.topic + if (!this.client.contacts.has(this.peerAddress)) { topics = [ buildUserIntroTopic(this.peerAddress), buildUserIntroTopic(this.client.address), - this.topic, + topic, ] this.client.contacts.add(this.peerAddress) } else { - topics = [this.topic] + topics = [topic] } const payload = await this.client.encodeContent(content, options) const msg = await this.createMessage(payload, recipient, options?.timestamp) + const msgBytes = msg.toBytes() const env: messageApi.Envelope = { - contentTopic: this.topic, - message: msg.toBytes(), + contentTopic: topic, + message: msgBytes, timestampNs: toNanoString(msg.sent), } @@ -258,10 +261,19 @@ export class ConversationV1 await this.client.publishEnvelopes( topics.map((topic) => ({ contentTopic: topic, - message: msg.toBytes(), + message: msgBytes, timestamp: msg.sent, })) ) + + return DecodedMessage.fromV1Message( + msg, + content, + options?.contentType || ContentTypeText, + payload, + topic, + this + ) }) } @@ -341,7 +353,7 @@ export class ConversationV1 ] this.client.contacts.add(this.peerAddress) } else { - topics = [this.topic] + topics = [topic] } const contentType = options?.contentType || ContentTypeText const payload = await this.client.encodeContent(content, options) @@ -360,7 +372,7 @@ export class ConversationV1 content, contentType, payload, - topics[0], // Just use the first topic for the returned value + topic, this ) } @@ -529,12 +541,7 @@ export class ConversationV2 const payload = await this.client.encodeContent(content, options) const msg = await this.createMessage(payload, options?.timestamp) - let topic: string - if (options?.ephemeral) { - topic = this.ephemeralTopic - } else { - topic = this.topic - } + const topic = options?.ephemeral ? this.ephemeralTopic : this.topic await this.client.publishEnvelopes([ { @@ -549,7 +556,7 @@ export class ConversationV2 msg, content, contentType, - this.topic, + topic, payload, this, this.client.address @@ -703,23 +710,34 @@ export class ConversationV2 ): Promise { const payload = await this.client.encodeContent(content, options) const msg = await this.createMessage(payload, options?.timestamp) + const msgBytes = msg.toBytes() const topic = options?.ephemeral ? this.ephemeralTopic : this.topic const env: messageApi.Envelope = { contentTopic: topic, - message: msg.toBytes(), + message: msgBytes, timestampNs: toNanoString(msg.sent), } return new PreparedMessage(env, async () => { await this.client.publishEnvelopes([ { - contentTopic: this.topic, - message: msg.toBytes(), + contentTopic: topic, + message: msgBytes, timestamp: msg.sent, }, ]) + + return DecodedMessage.fromV2Message( + msg, + content, + options?.contentType || ContentTypeText, + topic, + payload, + this, + this.client.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 5f5c51668..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 () => { @@ -138,11 +141,13 @@ describe('conversation', () => { const preparedMessage = await aliceConversation.prepareMessage('1') const messageID = await preparedMessage.messageID() - await preparedMessage.send() + const sentMessage = await preparedMessage.send() const messages = await aliceConversation.messages() const message = messages[0] expect(message.id).toBe(messageID) + expect(sentMessage.id).toBe(messageID) + expect(sentMessage.messageVersion).toBe('v1') }) it('can send a prepared message v2', async () => { @@ -157,12 +162,14 @@ describe('conversation', () => { const preparedMessage = await aliceConversation.prepareMessage('sup') const messageID = await preparedMessage.messageID() - await preparedMessage.send() + const sentMessage = await preparedMessage.send() const messages = await aliceConversation.messages() const message = messages[0] expect(message.id).toBe(messageID) expect(message.content).toBe('sup') + expect(sentMessage.id).toBe(messageID) + expect(sentMessage.messageVersion).toBe('v2') }) it('can send and stream ephemeral topic 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')