diff --git a/.cspell.json b/.cspell.json index a6c0a9724..4d79829a4 100644 --- a/.cspell.json +++ b/.cspell.json @@ -4,6 +4,7 @@ "language": "en", "words": [ "abortable", + "Addrs", "ahadns", "Alives", "asym", @@ -96,6 +97,7 @@ "secp", "sharded", "sscanf", + "Startable", "staticnode", "statusim", "statusteam", @@ -125,7 +127,15 @@ "Привет", "مرحبا" ], - "flagWords": ["pubSub: pubsub", "pubSubTopics: pubsubTopics", "pubSubTopic: pubsubTopic", "PubSub: Pubsub", "PubSubTopics: PubsubTopics", "PubSubTopic: PubsubTopic", "DefaultPubSubTopic: DefaultPubsubTopic"], + "flagWords": [ + "pubSub: pubsub", + "pubSubTopics: pubsubTopics", + "pubSubTopic: pubsubTopic", + "PubSub: Pubsub", + "PubSubTopics: PubsubTopics", + "PubSubTopic: PubsubTopic", + "DefaultPubSubTopic: DefaultPubsubTopic" + ], "ignorePaths": [ "package.json", "package-lock.json", diff --git a/.gitignore b/.gitignore index f178fc996..1a3c2625c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ test-results playwright-report example allure-results +packages/local-discovery/mock_local_storage \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index ac502abef..aa3c64909 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "packages/relay", "packages/peer-exchange", "packages/dns-discovery", + "packages/local-discovery", "packages/message-encryption", "packages/sdk", "packages/tests", @@ -4787,6 +4788,15 @@ "version": "20.6.3", "license": "MIT" }, + "node_modules/@types/node-localstorage": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/node-localstorage/-/node-localstorage-1.3.3.tgz", + "integrity": "sha512-Wkn5g4eM5x10UNV9Xvl9K6y6m0zorocuJy4WjB5muUdyMZuPbZpSJG3hlhjGHe1HGxbOQO7RcB+jlHcNwkh+Jw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -5469,6 +5479,10 @@ "resolved": "packages/interfaces", "link": true }, + "node_modules/@waku/local-discovery": { + "resolved": "packages/local-discovery", + "link": true + }, "node_modules/@waku/message-encryption": { "resolved": "packages/message-encryption", "link": true @@ -7390,7 +7404,8 @@ }, "node_modules/chai-as-promised": { "version": "7.1.1", - "license": "WTFPL", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", "dependencies": { "check-error": "^1.0.2" }, @@ -8262,6 +8277,21 @@ "node": ">= 0.10" } }, + "node_modules/cosmiconfig": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz", + "integrity": "sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==", + "dev": true, + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, "node_modules/cpu-features": { "version": "0.0.9", "hasInstallScript": true, @@ -11784,15 +11814,16 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "license": "MIT", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dependencies": { - "flatted": "^3.2.7", + "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -17017,6 +17048,43 @@ "node": ">= 6.13.0" } }, + "node_modules/node-localstorage": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/node-localstorage/-/node-localstorage-3.0.5.tgz", + "integrity": "sha512-GCwtK33iwVXboZWYcqQHu3aRvXEBwmPkAMRBLeaX86ufhqslyUkLGsi4aW3INEfdQYpUB5M9qtYf3eHvAk2VBg==", + "dev": true, + "dependencies": { + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/node-localstorage/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-localstorage/node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", @@ -27849,6 +27917,485 @@ "node": ">=18" } }, + "packages/local-discovery": { + "name": "@waku/local-discovery", + "version": "0.0.1", + "license": "MIT OR Apache-2.0", + "dependencies": { + "@libp2p/interface": "^1.1.2", + "@waku/interfaces": "^0.0.21", + "@waku/utils": "^0.0.14" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@types/chai": "^4.3.11", + "@types/node-localstorage": "^1.3.3", + "@waku/build-utils": "*", + "chai": "^4.3.10", + "chai-as-promised": "^7.1.1", + "cspell": "^7.3.2", + "mocha": "^10.2.0", + "node-localstorage": "^3.0.5", + "npm-run-all": "^4.1.5", + "rollup": "^4.9.5", + "sinon": "^17.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "packages/local-discovery/node_modules/@cspell/cspell-bundled-dicts": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-7.3.9.tgz", + "integrity": "sha512-ebfrf5Zaw33bcqT80Qrkv7IGT7GI/CDp15bSk2EUmdORzk1SCKZl6L4vUo3NLMmxVwYioS+OQmsW8E88sJNyGg==", + "dev": true, + "dependencies": { + "@cspell/dict-ada": "^4.0.2", + "@cspell/dict-aws": "^4.0.0", + "@cspell/dict-bash": "^4.1.2", + "@cspell/dict-companies": "^3.0.27", + "@cspell/dict-cpp": "^5.0.9", + "@cspell/dict-cryptocurrencies": "^4.0.0", + "@cspell/dict-csharp": "^4.0.2", + "@cspell/dict-css": "^4.0.12", + "@cspell/dict-dart": "^2.0.3", + "@cspell/dict-django": "^4.1.0", + "@cspell/dict-docker": "^1.1.7", + "@cspell/dict-dotnet": "^5.0.0", + "@cspell/dict-elixir": "^4.0.3", + "@cspell/dict-en_us": "^4.3.11", + "@cspell/dict-en-common-misspellings": "^1.0.2", + "@cspell/dict-en-gb": "1.1.33", + "@cspell/dict-filetypes": "^3.0.2", + "@cspell/dict-fonts": "^4.0.0", + "@cspell/dict-fsharp": "^1.0.1", + "@cspell/dict-fullstack": "^3.1.5", + "@cspell/dict-gaming-terms": "^1.0.4", + "@cspell/dict-git": "^2.0.0", + "@cspell/dict-golang": "^6.0.4", + "@cspell/dict-haskell": "^4.0.1", + "@cspell/dict-html": "^4.0.5", + "@cspell/dict-html-symbol-entities": "^4.0.0", + "@cspell/dict-java": "^5.0.6", + "@cspell/dict-k8s": "^1.0.2", + "@cspell/dict-latex": "^4.0.0", + "@cspell/dict-lorem-ipsum": "^4.0.0", + "@cspell/dict-lua": "^4.0.2", + "@cspell/dict-makefile": "^1.0.0", + "@cspell/dict-node": "^4.0.3", + "@cspell/dict-npm": "^5.0.12", + "@cspell/dict-php": "^4.0.4", + "@cspell/dict-powershell": "^5.0.2", + "@cspell/dict-public-licenses": "^2.0.5", + "@cspell/dict-python": "^4.1.10", + "@cspell/dict-r": "^2.0.1", + "@cspell/dict-ruby": "^5.0.1", + "@cspell/dict-rust": "^4.0.1", + "@cspell/dict-scala": "^5.0.0", + "@cspell/dict-software-terms": "^3.3.9", + "@cspell/dict-sql": "^2.1.2", + "@cspell/dict-svelte": "^1.0.2", + "@cspell/dict-swift": "^2.0.1", + "@cspell/dict-typescript": "^3.1.2", + "@cspell/dict-vue": "^3.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/@cspell/cspell-json-reporter": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-7.3.9.tgz", + "integrity": "sha512-QHsem5OZXshFX+Wdlx3VpdPi9WS7KgoBMGGJ4zQZ3lp81Rb1tRj0Ij/98whq882QOmAVQfr+uOHANHLnyPr0LQ==", + "dev": true, + "dependencies": { + "@cspell/cspell-types": "7.3.9" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/@cspell/cspell-pipe": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-7.3.9.tgz", + "integrity": "sha512-gKYTHcryKOaTmr6t+M5h1sZnQ42eHeumBJejovphipXfdivedUnuYyQrrQGFAlUKzfEOWcOPME1nm17xsaX5Ww==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/@cspell/cspell-resolver": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-7.3.9.tgz", + "integrity": "sha512-2slYAGvi7EFLKyJ5hrYBNaFT2iyOEQM1pEIzm+PDuhNJE/9wuBY5pBVqIgFSPz53vsQvW9GJThNY8h1/2EH3ZA==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.1" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/@cspell/cspell-service-bus": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-7.3.9.tgz", + "integrity": "sha512-VyfK3qWtJZag4Fe/x1Oh/tqCNVGKGlQ2ArX1fVdmTVGQtZcbXuMKdZI80t4b8SGtzGINHufAdakpu3xucX/FrQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/@cspell/cspell-types": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-7.3.9.tgz", + "integrity": "sha512-p7s8yEV6ASz0HjiArH11yjNj3vXzK2Ep94GrpdtYJxSxFC2w1mXAVUaJB/5+jC4+1YeYsmcBFTXmZ1rGMyTv3g==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/@cspell/dict-cryptocurrencies": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-4.0.0.tgz", + "integrity": "sha512-EiZp91ATyRxTmauIQfOX9adLYCunKjHEh092rrM7o2eMXP9n7zpXAL9BK7LviL+LbB8VDOm21q+s83cKrrRrsg==", + "dev": true + }, + "packages/local-discovery/node_modules/@cspell/dict-en-common-misspellings": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-1.0.2.tgz", + "integrity": "sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==", + "dev": true + }, + "packages/local-discovery/node_modules/@cspell/dict-git": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-2.0.0.tgz", + "integrity": "sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==", + "dev": true + }, + "packages/local-discovery/node_modules/@cspell/dynamic-import": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-7.3.9.tgz", + "integrity": "sha512-P6tAmDVhrW03hmhetxhBKlNTYwL2lk8ZehYQwSpXaLnaFrS3xrQvfUaJ3Mj9W2CIMzSYXlLmPO2FLRhXK2dnEw==", + "dev": true, + "dependencies": { + "import-meta-resolve": "^3.1.1" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/@cspell/strong-weak-map": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-7.3.9.tgz", + "integrity": "sha512-XKpw/p3+EN+PWiFAWc45RJPI9zQRkPSVdUFeZb0YLseWF/CkogScgIe4CLfMLITiVbP0X/FKk90+aTPfAU38kg==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/cspell": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-7.3.9.tgz", + "integrity": "sha512-QzunjO9CmV5+98UfG4ONhvPtrcAC6Y2pEKeOrp5oPeyAI7HwgxmfsR3ybHRlMPAGcwKtDOurBKxM7jqXNwkzmA==", + "dev": true, + "dependencies": { + "@cspell/cspell-json-reporter": "7.3.9", + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-types": "7.3.9", + "@cspell/dynamic-import": "7.3.9", + "chalk": "^5.3.0", + "chalk-template": "^1.1.0", + "commander": "^11.1.0", + "cspell-gitignore": "7.3.9", + "cspell-glob": "7.3.9", + "cspell-io": "7.3.9", + "cspell-lib": "7.3.9", + "fast-glob": "^3.3.2", + "fast-json-stable-stringify": "^2.1.0", + "file-entry-cache": "^7.0.1", + "get-stdin": "^9.0.0", + "semver": "^7.5.4", + "strip-ansi": "^7.1.0", + "vscode-uri": "^3.0.8" + }, + "bin": { + "cspell": "bin.mjs", + "cspell-esm": "bin.mjs" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" + } + }, + "packages/local-discovery/node_modules/cspell-dictionary": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-7.3.9.tgz", + "integrity": "sha512-lkWfX5QNbs4yKqD9wa+G+NHRWmLgFdyposgJOyd/ojDbx99CDPMhMhg9pyMKdYl6Yt8kjMow58/i12EYvD8wnA==", + "dev": true, + "dependencies": { + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-types": "7.3.9", + "cspell-trie-lib": "7.3.9", + "fast-equals": "^4.0.3", + "gensequence": "^6.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/cspell-dictionary/node_modules/fast-equals": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", + "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==", + "dev": true + }, + "packages/local-discovery/node_modules/cspell-gitignore": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-7.3.9.tgz", + "integrity": "sha512-DLuu+K2q4xYNL4DpLyysUeiGU/NYYoObzfOYiISzOKYpi3aFLiUaiyfF6xWGsahmlijif+8bwSsIMmcvGa5dgA==", + "dev": true, + "dependencies": { + "cspell-glob": "7.3.9", + "find-up": "^5.0.0" + }, + "bin": { + "cspell-gitignore": "bin.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/cspell-glob": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-7.3.9.tgz", + "integrity": "sha512-7PaTkCzJWjQex3men857v3ExF7Q10jbQkfD+wdln2te9iNFd+HEkstA173vb828D9yeib1q1of8oONr2SeGycg==", + "dev": true, + "dependencies": { + "micromatch": "^4.0.5" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/cspell-grammar": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-7.3.9.tgz", + "integrity": "sha512-s1QOPg4AxWE8XBewDQLe14j0uDyWGjREfm4dZFTrslAZUrQ8/df5s152M5LtgOEza33FrkKKE2axbGvgS9O7sQ==", + "dev": true, + "dependencies": { + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-types": "7.3.9" + }, + "bin": { + "cspell-grammar": "bin.mjs" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/cspell-io": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-7.3.9.tgz", + "integrity": "sha512-IbXOYaDxLg94uijv13kqb+6PQjEwGboQYtABuZs2+HuUVW89K2tE+fQcEhkAsrZ11sDj5lUqgEQj9omvknZSuA==", + "dev": true, + "dependencies": { + "@cspell/cspell-service-bus": "7.3.9", + "node-fetch": "^2.7.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/cspell-lib": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-7.3.9.tgz", + "integrity": "sha512-eFYYs8XoYmdu78UxrPisD+hAoXOLaLzcevKf9+oDPDgJmHpkGoFgbIBnHMRIsAM1e+QDS6OlWG/rybhZTqanCQ==", + "dev": true, + "dependencies": { + "@cspell/cspell-bundled-dicts": "7.3.9", + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-resolver": "7.3.9", + "@cspell/cspell-types": "7.3.9", + "@cspell/dynamic-import": "7.3.9", + "@cspell/strong-weak-map": "7.3.9", + "clear-module": "^4.1.2", + "comment-json": "^4.2.3", + "configstore": "^6.0.0", + "cosmiconfig": "8.0.0", + "cspell-dictionary": "7.3.9", + "cspell-glob": "7.3.9", + "cspell-grammar": "7.3.9", + "cspell-io": "7.3.9", + "cspell-trie-lib": "7.3.9", + "fast-equals": "^5.0.1", + "find-up": "^6.3.0", + "gensequence": "^6.0.0", + "import-fresh": "^3.3.0", + "resolve-from": "^5.0.0", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/cspell-lib/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/local-discovery/node_modules/cspell-trie-lib": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-7.3.9.tgz", + "integrity": "sha512-aTWm2KYXjQ+MlM6kB37wmTV9RU8+fgZYkiFfMc48M0MhBc6XkHUibMGrFAS29gp+B70kWPxe+VHLmFIk9pRPyg==", + "dev": true, + "dependencies": { + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-types": "7.3.9", + "gensequence": "^6.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "packages/local-discovery/node_modules/file-entry-cache": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.2.tgz", + "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==", + "dev": true, + "dependencies": { + "flat-cache": "^3.2.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "packages/local-discovery/node_modules/import-meta-resolve": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-3.1.1.tgz", + "integrity": "sha512-qeywsE/KC3w9Fd2ORrRDUw6nS/nLwZpXgfrOc2IILvZYnCaEMd+D56Vfg9k4G29gIeVi3XKql1RQatME8iYsiw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "packages/local-discovery/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/local-discovery/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/local-discovery/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/local-discovery/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "packages/local-discovery/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/local-storage-discovery": { + "name": "@waku/local-discovery", + "version": "0.0.1", + "extraneous": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@libp2p/interface": "^1.1.2", + "@waku/interfaces": "^0.0.21", + "@waku/utils": "^0.0.14" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@types/chai": "^4.3.11", + "@waku/build-utils": "*", + "chai": "^4.3.10", + "cspell": "^7.3.2", + "mocha": "^10.2.0", + "npm-run-all": "^4.1.5", + "rollup": "^4.9.5" + }, + "engines": { + "node": ">=18" + } + }, "packages/message-encryption": { "name": "@waku/message-encryption", "version": "0.0.24", @@ -28005,6 +28552,7 @@ "@waku/core": "0.0.26", "@waku/dns-discovery": "0.0.20", "@waku/interfaces": "0.0.21", + "@waku/local-discovery": "^0.0.1", "@waku/peer-exchange": "^0.0.19", "@waku/relay": "0.0.9", "@waku/utils": "0.0.14", @@ -31473,6 +32021,15 @@ "@types/node": { "version": "20.6.3" }, + "@types/node-localstorage": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/node-localstorage/-/node-localstorage-1.3.3.tgz", + "integrity": "sha512-Wkn5g4eM5x10UNV9Xvl9K6y6m0zorocuJy4WjB5muUdyMZuPbZpSJG3hlhjGHe1HGxbOQO7RcB+jlHcNwkh+Jw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -32025,6 +32582,354 @@ "npm-run-all": "^4.1.5" } }, + "@waku/local-discovery": { + "version": "file:packages/local-discovery", + "requires": { + "@libp2p/interface": "^1.1.2", + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@types/chai": "^4.3.11", + "@types/node-localstorage": "^1.3.3", + "@waku/build-utils": "*", + "@waku/interfaces": "^0.0.21", + "@waku/utils": "^0.0.14", + "chai": "^4.3.10", + "chai-as-promised": "^7.1.1", + "cspell": "^7.3.2", + "mocha": "^10.2.0", + "node-localstorage": "^3.0.5", + "npm-run-all": "^4.1.5", + "rollup": "^4.9.5", + "sinon": "^17.0.1" + }, + "dependencies": { + "@cspell/cspell-bundled-dicts": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-7.3.9.tgz", + "integrity": "sha512-ebfrf5Zaw33bcqT80Qrkv7IGT7GI/CDp15bSk2EUmdORzk1SCKZl6L4vUo3NLMmxVwYioS+OQmsW8E88sJNyGg==", + "dev": true, + "requires": { + "@cspell/dict-ada": "^4.0.2", + "@cspell/dict-aws": "^4.0.0", + "@cspell/dict-bash": "^4.1.2", + "@cspell/dict-companies": "^3.0.27", + "@cspell/dict-cpp": "^5.0.9", + "@cspell/dict-cryptocurrencies": "^4.0.0", + "@cspell/dict-csharp": "^4.0.2", + "@cspell/dict-css": "^4.0.12", + "@cspell/dict-dart": "^2.0.3", + "@cspell/dict-django": "^4.1.0", + "@cspell/dict-docker": "^1.1.7", + "@cspell/dict-dotnet": "^5.0.0", + "@cspell/dict-elixir": "^4.0.3", + "@cspell/dict-en_us": "^4.3.11", + "@cspell/dict-en-common-misspellings": "^1.0.2", + "@cspell/dict-en-gb": "1.1.33", + "@cspell/dict-filetypes": "^3.0.2", + "@cspell/dict-fonts": "^4.0.0", + "@cspell/dict-fsharp": "^1.0.1", + "@cspell/dict-fullstack": "^3.1.5", + "@cspell/dict-gaming-terms": "^1.0.4", + "@cspell/dict-git": "^2.0.0", + "@cspell/dict-golang": "^6.0.4", + "@cspell/dict-haskell": "^4.0.1", + "@cspell/dict-html": "^4.0.5", + "@cspell/dict-html-symbol-entities": "^4.0.0", + "@cspell/dict-java": "^5.0.6", + "@cspell/dict-k8s": "^1.0.2", + "@cspell/dict-latex": "^4.0.0", + "@cspell/dict-lorem-ipsum": "^4.0.0", + "@cspell/dict-lua": "^4.0.2", + "@cspell/dict-makefile": "^1.0.0", + "@cspell/dict-node": "^4.0.3", + "@cspell/dict-npm": "^5.0.12", + "@cspell/dict-php": "^4.0.4", + "@cspell/dict-powershell": "^5.0.2", + "@cspell/dict-public-licenses": "^2.0.5", + "@cspell/dict-python": "^4.1.10", + "@cspell/dict-r": "^2.0.1", + "@cspell/dict-ruby": "^5.0.1", + "@cspell/dict-rust": "^4.0.1", + "@cspell/dict-scala": "^5.0.0", + "@cspell/dict-software-terms": "^3.3.9", + "@cspell/dict-sql": "^2.1.2", + "@cspell/dict-svelte": "^1.0.2", + "@cspell/dict-swift": "^2.0.1", + "@cspell/dict-typescript": "^3.1.2", + "@cspell/dict-vue": "^3.0.0" + } + }, + "@cspell/cspell-json-reporter": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-7.3.9.tgz", + "integrity": "sha512-QHsem5OZXshFX+Wdlx3VpdPi9WS7KgoBMGGJ4zQZ3lp81Rb1tRj0Ij/98whq882QOmAVQfr+uOHANHLnyPr0LQ==", + "dev": true, + "requires": { + "@cspell/cspell-types": "7.3.9" + } + }, + "@cspell/cspell-pipe": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-7.3.9.tgz", + "integrity": "sha512-gKYTHcryKOaTmr6t+M5h1sZnQ42eHeumBJejovphipXfdivedUnuYyQrrQGFAlUKzfEOWcOPME1nm17xsaX5Ww==", + "dev": true + }, + "@cspell/cspell-resolver": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-7.3.9.tgz", + "integrity": "sha512-2slYAGvi7EFLKyJ5hrYBNaFT2iyOEQM1pEIzm+PDuhNJE/9wuBY5pBVqIgFSPz53vsQvW9GJThNY8h1/2EH3ZA==", + "dev": true, + "requires": { + "global-dirs": "^3.0.1" + } + }, + "@cspell/cspell-service-bus": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-7.3.9.tgz", + "integrity": "sha512-VyfK3qWtJZag4Fe/x1Oh/tqCNVGKGlQ2ArX1fVdmTVGQtZcbXuMKdZI80t4b8SGtzGINHufAdakpu3xucX/FrQ==", + "dev": true + }, + "@cspell/cspell-types": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-7.3.9.tgz", + "integrity": "sha512-p7s8yEV6ASz0HjiArH11yjNj3vXzK2Ep94GrpdtYJxSxFC2w1mXAVUaJB/5+jC4+1YeYsmcBFTXmZ1rGMyTv3g==", + "dev": true + }, + "@cspell/dict-cryptocurrencies": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-4.0.0.tgz", + "integrity": "sha512-EiZp91ATyRxTmauIQfOX9adLYCunKjHEh092rrM7o2eMXP9n7zpXAL9BK7LviL+LbB8VDOm21q+s83cKrrRrsg==", + "dev": true + }, + "@cspell/dict-en-common-misspellings": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-1.0.2.tgz", + "integrity": "sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==", + "dev": true + }, + "@cspell/dict-git": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-2.0.0.tgz", + "integrity": "sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==", + "dev": true + }, + "@cspell/dynamic-import": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-7.3.9.tgz", + "integrity": "sha512-P6tAmDVhrW03hmhetxhBKlNTYwL2lk8ZehYQwSpXaLnaFrS3xrQvfUaJ3Mj9W2CIMzSYXlLmPO2FLRhXK2dnEw==", + "dev": true, + "requires": { + "import-meta-resolve": "^3.1.1" + } + }, + "@cspell/strong-weak-map": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-7.3.9.tgz", + "integrity": "sha512-XKpw/p3+EN+PWiFAWc45RJPI9zQRkPSVdUFeZb0YLseWF/CkogScgIe4CLfMLITiVbP0X/FKk90+aTPfAU38kg==", + "dev": true + }, + "commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true + }, + "cspell": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-7.3.9.tgz", + "integrity": "sha512-QzunjO9CmV5+98UfG4ONhvPtrcAC6Y2pEKeOrp5oPeyAI7HwgxmfsR3ybHRlMPAGcwKtDOurBKxM7jqXNwkzmA==", + "dev": true, + "requires": { + "@cspell/cspell-json-reporter": "7.3.9", + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-types": "7.3.9", + "@cspell/dynamic-import": "7.3.9", + "chalk": "^5.3.0", + "chalk-template": "^1.1.0", + "commander": "^11.1.0", + "cspell-gitignore": "7.3.9", + "cspell-glob": "7.3.9", + "cspell-io": "7.3.9", + "cspell-lib": "7.3.9", + "fast-glob": "^3.3.2", + "fast-json-stable-stringify": "^2.1.0", + "file-entry-cache": "^7.0.1", + "get-stdin": "^9.0.0", + "semver": "^7.5.4", + "strip-ansi": "^7.1.0", + "vscode-uri": "^3.0.8" + } + }, + "cspell-dictionary": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-7.3.9.tgz", + "integrity": "sha512-lkWfX5QNbs4yKqD9wa+G+NHRWmLgFdyposgJOyd/ojDbx99CDPMhMhg9pyMKdYl6Yt8kjMow58/i12EYvD8wnA==", + "dev": true, + "requires": { + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-types": "7.3.9", + "cspell-trie-lib": "7.3.9", + "fast-equals": "^4.0.3", + "gensequence": "^6.0.0" + }, + "dependencies": { + "fast-equals": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", + "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==", + "dev": true + } + } + }, + "cspell-gitignore": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-7.3.9.tgz", + "integrity": "sha512-DLuu+K2q4xYNL4DpLyysUeiGU/NYYoObzfOYiISzOKYpi3aFLiUaiyfF6xWGsahmlijif+8bwSsIMmcvGa5dgA==", + "dev": true, + "requires": { + "cspell-glob": "7.3.9", + "find-up": "^5.0.0" + } + }, + "cspell-glob": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-7.3.9.tgz", + "integrity": "sha512-7PaTkCzJWjQex3men857v3ExF7Q10jbQkfD+wdln2te9iNFd+HEkstA173vb828D9yeib1q1of8oONr2SeGycg==", + "dev": true, + "requires": { + "micromatch": "^4.0.5" + } + }, + "cspell-grammar": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-7.3.9.tgz", + "integrity": "sha512-s1QOPg4AxWE8XBewDQLe14j0uDyWGjREfm4dZFTrslAZUrQ8/df5s152M5LtgOEza33FrkKKE2axbGvgS9O7sQ==", + "dev": true, + "requires": { + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-types": "7.3.9" + } + }, + "cspell-io": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-7.3.9.tgz", + "integrity": "sha512-IbXOYaDxLg94uijv13kqb+6PQjEwGboQYtABuZs2+HuUVW89K2tE+fQcEhkAsrZ11sDj5lUqgEQj9omvknZSuA==", + "dev": true, + "requires": { + "@cspell/cspell-service-bus": "7.3.9", + "node-fetch": "^2.7.0" + } + }, + "cspell-lib": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-7.3.9.tgz", + "integrity": "sha512-eFYYs8XoYmdu78UxrPisD+hAoXOLaLzcevKf9+oDPDgJmHpkGoFgbIBnHMRIsAM1e+QDS6OlWG/rybhZTqanCQ==", + "dev": true, + "requires": { + "@cspell/cspell-bundled-dicts": "7.3.9", + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-resolver": "7.3.9", + "@cspell/cspell-types": "7.3.9", + "@cspell/dynamic-import": "7.3.9", + "@cspell/strong-weak-map": "7.3.9", + "clear-module": "^4.1.2", + "comment-json": "^4.2.3", + "configstore": "^6.0.0", + "cosmiconfig": "8.0.0", + "cspell-dictionary": "7.3.9", + "cspell-glob": "7.3.9", + "cspell-grammar": "7.3.9", + "cspell-io": "7.3.9", + "cspell-trie-lib": "7.3.9", + "fast-equals": "^5.0.1", + "find-up": "^6.3.0", + "gensequence": "^6.0.0", + "import-fresh": "^3.3.0", + "resolve-from": "^5.0.0", + "vscode-languageserver-textdocument": "^1.0.11", + "vscode-uri": "^3.0.8" + }, + "dependencies": { + "find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "requires": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + } + } + } + }, + "cspell-trie-lib": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-7.3.9.tgz", + "integrity": "sha512-aTWm2KYXjQ+MlM6kB37wmTV9RU8+fgZYkiFfMc48M0MhBc6XkHUibMGrFAS29gp+B70kWPxe+VHLmFIk9pRPyg==", + "dev": true, + "requires": { + "@cspell/cspell-pipe": "7.3.9", + "@cspell/cspell-types": "7.3.9", + "gensequence": "^6.0.0" + } + }, + "file-entry-cache": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-7.0.2.tgz", + "integrity": "sha512-TfW7/1iI4Cy7Y8L6iqNdZQVvdXn0f8B4QcIXmkIbtTIe/Okm/nSlHb4IwGzRVOd3WfSieCgvf5cMzEfySAIl0g==", + "dev": true, + "requires": { + "flat-cache": "^3.2.0" + } + }, + "import-meta-resolve": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-3.1.1.tgz", + "integrity": "sha512-qeywsE/KC3w9Fd2ORrRDUw6nS/nLwZpXgfrOc2IILvZYnCaEMd+D56Vfg9k4G29gIeVi3XKql1RQatME8iYsiw==", + "dev": true + }, + "locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "requires": { + "p-locate": "^6.0.0" + } + }, + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "requires": { + "p-limit": "^4.0.0" + } + }, + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true + } + } + }, "@waku/message-encryption": { "version": "file:packages/message-encryption", "requires": { @@ -32149,6 +33054,7 @@ "@waku/core": "0.0.26", "@waku/dns-discovery": "0.0.20", "@waku/interfaces": "0.0.21", + "@waku/local-discovery": "^0.0.1", "@waku/peer-exchange": "^0.0.19", "@waku/relay": "0.0.9", "@waku/utils": "0.0.14", @@ -33455,6 +34361,8 @@ }, "chai-as-promised": { "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", "requires": { "check-error": "^1.0.2" } @@ -34040,6 +34948,18 @@ "vary": "^1" } }, + "cosmiconfig": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz", + "integrity": "sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==", + "dev": true, + "requires": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + } + }, "cpu-features": { "version": "0.0.9", "optional": true, @@ -36381,9 +37301,11 @@ "version": "5.0.2" }, "flat-cache": { - "version": "3.1.0", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "requires": { - "flatted": "^3.2.7", + "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" } @@ -39845,6 +40767,33 @@ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" }, + "node-localstorage": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/node-localstorage/-/node-localstorage-3.0.5.tgz", + "integrity": "sha512-GCwtK33iwVXboZWYcqQHu3aRvXEBwmPkAMRBLeaX86ufhqslyUkLGsi4aW3INEfdQYpUB5M9qtYf3eHvAk2VBg==", + "dev": true, + "requires": { + "write-file-atomic": "^5.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + } + } + } + }, "node-preload": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", diff --git a/package.json b/package.json index 2a7161d9c..7d8eba4b4 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "packages/relay", "packages/peer-exchange", "packages/dns-discovery", + "packages/local-discovery", "packages/message-encryption", "packages/sdk", "packages/tests", diff --git a/packages/core/src/lib/connection_manager.ts b/packages/core/src/lib/connection_manager.ts index 8a0ef17a2..1692154f5 100644 --- a/packages/core/src/lib/connection_manager.ts +++ b/packages/core/src/lib/connection_manager.ts @@ -97,8 +97,11 @@ export class ConnectionManager const peersDiscoveredByBootstrap: Peer[] = []; const peersDiscoveredByPeerExchange: Peer[] = []; + const peersDiscoveredByLocal: Peer[] = []; + const peersConnectedByBootstrap: Peer[] = []; const peersConnectedByPeerExchange: Peer[] = []; + const peersConnectedByLocal: Peer[] = []; for (const peer of peersDiscovered) { const tags = await this.getTagNamesForPeer(peer.id); @@ -107,6 +110,8 @@ export class ConnectionManager peersDiscoveredByBootstrap.push(peer); } else if (tags.includes(Tags.PEER_EXCHANGE)) { peersDiscoveredByPeerExchange.push(peer); + } else if (tags.includes(Tags.LOCAL)) { + peersDiscoveredByLocal.push(peer); } } @@ -118,17 +123,21 @@ export class ConnectionManager peersConnectedByBootstrap.push(peer); } else if (tags.includes(Tags.PEER_EXCHANGE)) { peersConnectedByPeerExchange.push(peer); + } else if (tags.includes(Tags.LOCAL)) { + peersConnectedByLocal.push(peer); } } return { DISCOVERED: { [Tags.BOOTSTRAP]: peersDiscoveredByBootstrap, - [Tags.PEER_EXCHANGE]: peersDiscoveredByPeerExchange + [Tags.PEER_EXCHANGE]: peersDiscoveredByPeerExchange, + [Tags.LOCAL]: peersDiscoveredByLocal }, CONNECTED: { [Tags.BOOTSTRAP]: peersConnectedByBootstrap, - [Tags.PEER_EXCHANGE]: peersConnectedByPeerExchange + [Tags.PEER_EXCHANGE]: peersConnectedByPeerExchange, + [Tags.LOCAL]: peersConnectedByLocal } }; } diff --git a/packages/interfaces/src/connection_manager.ts b/packages/interfaces/src/connection_manager.ts index 46a3c4224..486a48d3d 100644 --- a/packages/interfaces/src/connection_manager.ts +++ b/packages/interfaces/src/connection_manager.ts @@ -2,7 +2,8 @@ import type { Peer, PeerId, TypedEventEmitter } from "@libp2p/interface"; export enum Tags { BOOTSTRAP = "bootstrap", - PEER_EXCHANGE = "peer-exchange" + PEER_EXCHANGE = "peer-exchange", + LOCAL = "local" } export interface ConnectionManagerOptions { @@ -40,10 +41,12 @@ export interface PeersByDiscoveryResult { DISCOVERED: { [Tags.BOOTSTRAP]: Peer[]; [Tags.PEER_EXCHANGE]: Peer[]; + [Tags.LOCAL]: Peer[]; }; CONNECTED: { [Tags.BOOTSTRAP]: Peer[]; [Tags.PEER_EXCHANGE]: Peer[]; + [Tags.LOCAL]: Peer[]; }; } diff --git a/packages/interfaces/src/index.ts b/packages/interfaces/src/index.ts index 03ff627af..1d98ed24d 100644 --- a/packages/interfaces/src/index.ts +++ b/packages/interfaces/src/index.ts @@ -16,3 +16,4 @@ export * from "./keep_alive_manager.js"; export * from "./dns_discovery.js"; export * from "./metadata.js"; export * from "./constants.js"; +export * from "./local_storage.js"; diff --git a/packages/interfaces/src/local_storage.ts b/packages/interfaces/src/local_storage.ts new file mode 100644 index 000000000..7790d917e --- /dev/null +++ b/packages/interfaces/src/local_storage.ts @@ -0,0 +1,4 @@ +export type LocalStoragePeerInfo = { + id: string; + address: string; +}; diff --git a/packages/local-discovery/.eslintrc.cjs b/packages/local-discovery/.eslintrc.cjs new file mode 100644 index 000000000..2299ed822 --- /dev/null +++ b/packages/local-discovery/.eslintrc.cjs @@ -0,0 +1,6 @@ +module.exports = { + parserOptions: { + tsconfigRootDir: __dirname, + project: "./tsconfig.dev.json" + } +}; diff --git a/packages/local-discovery/.mocha.reporters.json b/packages/local-discovery/.mocha.reporters.json new file mode 100644 index 000000000..8c00e441f --- /dev/null +++ b/packages/local-discovery/.mocha.reporters.json @@ -0,0 +1,6 @@ +{ + "reporterEnabled": "spec, allure-mocha", + "allureMochaReporter": { + "outputDir": "allure-results" + } +} diff --git a/packages/local-discovery/.mocharc.cjs b/packages/local-discovery/.mocharc.cjs new file mode 100644 index 000000000..423c0517b --- /dev/null +++ b/packages/local-discovery/.mocharc.cjs @@ -0,0 +1,26 @@ +const config = { + extension: ['ts'], + spec: 'src/**/*.spec.ts', + require: ['ts-node/register', 'isomorphic-fetch'], + loader: 'ts-node/esm', + 'node-option': [ + 'experimental-specifier-resolution=node', + 'loader=ts-node/esm' + ], + exit: true +}; + +if (process.env.CI) { + console.log("Running tests in parallel"); + config.parallel = true; + config.jobs = 6; + console.log("Activating allure reporting"); + config.reporter = 'mocha-multi-reporters'; + config.reporterOptions = { + configFile: '.mocha.reporters.json' + }; +} else { + console.log("Running tests serially. To enable parallel execution update mocha config"); +} + +module.exports = config; diff --git a/packages/local-discovery/CHANGELOG.md b/packages/local-discovery/CHANGELOG.md new file mode 100644 index 000000000..e69de29bb diff --git a/packages/local-discovery/karma.conf.cjs b/packages/local-discovery/karma.conf.cjs new file mode 100644 index 000000000..1acbc3dd2 --- /dev/null +++ b/packages/local-discovery/karma.conf.cjs @@ -0,0 +1,3 @@ +const config = require("../../karma.conf.cjs"); + +module.exports = config; diff --git a/packages/local-discovery/package.json b/packages/local-discovery/package.json new file mode 100644 index 000000000..5a45f72e2 --- /dev/null +++ b/packages/local-discovery/package.json @@ -0,0 +1,83 @@ +{ + "name": "@waku/local-discovery", + "version": "0.0.1", + "description": "Local Discovery keeps records of healthy peers in the browser's local storage for quicker bootstrapping.", + "types": "./dist/index.d.ts", + "module": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + } + }, + "type": "module", + "author": "Waku Team", + "homepage": "https://github.com/waku-org/js-waku/tree/master/packages/local-discovery#readme", + "repository": { + "type": "git", + "url": "https://github.com/waku-org/js-waku.git" + }, + "bugs": { + "url": "https://github.com/waku-org/js-waku/issues" + }, + "license": "MIT OR Apache-2.0", + "keywords": [ + "waku", + "decentralized", + "secure", + "communication", + "web3", + "ethereum", + "dapps", + "privacy" + ], + "scripts": { + "build": "run-s build:**", + "build:esm": "tsc", + "build:bundle": "rollup --config rollup.config.js", + "fix": "run-s fix:*", + "fix:lint": "eslint src *.js --fix", + "check": "run-s check:*", + "check:lint": "eslint src --ext .ts", + "check:spelling": "cspell \"{README.md,src/**/*.ts}\"", + "check:tsc": "tsc -p tsconfig.dev.json", + "prepublish": "npm run build", + "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build", + "test": "NODE_ENV=test run-s test:*", + "test:node": "NODE_ENV=test TS_NODE_PROJECT=./tsconfig.dev.json mocha" + }, + "engines": { + "node": ">=18" + }, + "dependencies": { + "@libp2p/interface": "^1.1.2", + "@waku/interfaces": "^0.0.21", + "@waku/utils": "^0.0.14" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^25.0.7", + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@types/chai": "^4.3.11", + "@types/node-localstorage": "^1.3.3", + "@waku/build-utils": "*", + "chai": "^4.3.10", + "chai-as-promised": "^7.1.1", + "cspell": "^7.3.2", + "mocha": "^10.2.0", + "node-localstorage": "^3.0.5", + "npm-run-all": "^4.1.5", + "rollup": "^4.9.5", + "sinon": "^17.0.1" + }, + "files": [ + "dist", + "bundle", + "src/**/*.ts", + "!**/*.spec.*", + "!**/*.json", + "CHANGELOG.md", + "LICENSE", + "README.md" + ] +} diff --git a/packages/local-discovery/rollup.config.js b/packages/local-discovery/rollup.config.js new file mode 100644 index 000000000..4d0757b1c --- /dev/null +++ b/packages/local-discovery/rollup.config.js @@ -0,0 +1,24 @@ +import commonjs from "@rollup/plugin-commonjs"; +import json from "@rollup/plugin-json"; +import { nodeResolve } from "@rollup/plugin-node-resolve"; +import { extractExports } from "@waku/build-utils"; + +import * as packageJson from "./package.json" assert { type: "json" }; + +const input = extractExports(packageJson); + +export default { + input, + output: { + dir: "bundle", + format: "esm" + }, + plugins: [ + commonjs(), + json(), + nodeResolve({ + browser: true, + preferBuiltins: false + }) + ] +}; diff --git a/packages/local-discovery/src/index.ts b/packages/local-discovery/src/index.ts new file mode 100644 index 000000000..28549ac75 --- /dev/null +++ b/packages/local-discovery/src/index.ts @@ -0,0 +1,160 @@ +import { TypedEventEmitter } from "@libp2p/interface"; +import { + CustomEvent, + IdentifyResult, + PeerDiscovery, + PeerDiscoveryEvents, + PeerInfo, + Startable +} from "@libp2p/interface"; +import { createFromJSON } from "@libp2p/peer-id-factory"; +import { multiaddr } from "@multiformats/multiaddr"; +import { + type Libp2pComponents, + type LocalStoragePeerInfo, + Tags +} from "@waku/interfaces"; +import { getWsMultiaddrFromMultiaddrs, Logger } from "@waku/utils"; + +const log = new Logger("peer-exchange-discovery"); + +type LocalStorageDiscoveryOptions = { + tagName?: string; + tagValue?: number; + tagTTL?: number; +}; + +export const DEFAULT_LOCAL_TAG_NAME = Tags.LOCAL; +const DEFAULT_LOCAL_TAG_VALUE = 50; +const DEFAULT_LOCAL_TAG_TTL = 100_000_000; + +export class LocalStorageDiscovery + extends TypedEventEmitter + implements PeerDiscovery, Startable +{ + private isStarted: boolean; + private peers: LocalStoragePeerInfo[] = []; + + constructor( + private readonly components: Libp2pComponents, + private readonly options?: LocalStorageDiscoveryOptions + ) { + super(); + this.isStarted = false; + this.peers = this.getPeersFromLocalStorage(); + } + + get [Symbol.toStringTag](): string { + return "@waku/local-discovery"; + } + + async start(): Promise { + if (this.isStarted) return; + + log.info("Starting Local Storage Discovery"); + this.components.events.addEventListener( + "peer:identify", + this.handleNewPeers + ); + + for (const { id: idStr, address } of this.peers) { + const peerId = await createFromJSON({ id: idStr }); + if (await this.components.peerStore.has(peerId)) continue; + + await this.components.peerStore.save(peerId, { + multiaddrs: [multiaddr(address)], + tags: { + [this.options?.tagName ?? DEFAULT_LOCAL_TAG_NAME]: { + value: this.options?.tagValue ?? DEFAULT_LOCAL_TAG_VALUE, + ttl: this.options?.tagTTL ?? DEFAULT_LOCAL_TAG_TTL + } + } + }); + + this.dispatchEvent( + new CustomEvent("peer", { + detail: { + id: peerId, + multiaddrs: [multiaddr(address)] + } + }) + ); + } + + log.info(`Discovered ${this.peers.length} peers`); + + this.isStarted = true; + } + + stop(): void | Promise { + if (!this.isStarted) return; + log.info("Stopping Local Storage Discovery"); + this.components.events.removeEventListener( + "peer:identify", + this.handleNewPeers + ); + this.isStarted = false; + + this.savePeersToLocalStorage(); + } + + handleNewPeers = (event: CustomEvent): void => { + const { peerId, listenAddrs } = event.detail; + + const websocketMultiaddr = getWsMultiaddrFromMultiaddrs(listenAddrs); + + const localStoragePeers = this.getPeersFromLocalStorage(); + + const existingPeerIndex = localStoragePeers.findIndex( + (_peer) => _peer.id === peerId.toString() + ); + + if (existingPeerIndex >= 0) { + localStoragePeers[existingPeerIndex].address = + websocketMultiaddr.toString(); + } else { + localStoragePeers.push({ + id: peerId.toString(), + address: websocketMultiaddr.toString() + }); + } + + this.peers = localStoragePeers; + this.savePeersToLocalStorage(); + }; + + private getPeersFromLocalStorage(): LocalStoragePeerInfo[] { + try { + const storedPeersData = localStorage.getItem("waku:peers"); + if (!storedPeersData) return []; + const peers = JSON.parse(storedPeersData); + return peers.filter(isValidStoredPeer); + } catch (error) { + log.error("Error parsing peers from local storage:", error); + return []; + } + } + + private savePeersToLocalStorage(): void { + localStorage.setItem("waku:peers", JSON.stringify(this.peers)); + } +} + +function isValidStoredPeer(peer: any): peer is LocalStoragePeerInfo { + return ( + peer && + typeof peer === "object" && + typeof peer.id === "string" && + typeof peer.address === "string" + ); +} + +export function wakuLocalStorageDiscovery(): ( + components: Libp2pComponents, + options?: LocalStorageDiscoveryOptions +) => LocalStorageDiscovery { + return ( + components: Libp2pComponents, + options?: LocalStorageDiscoveryOptions + ) => new LocalStorageDiscovery(components, options); +} diff --git a/packages/local-discovery/src/local_discovery.spec.ts b/packages/local-discovery/src/local_discovery.spec.ts new file mode 100644 index 000000000..23eba055c --- /dev/null +++ b/packages/local-discovery/src/local_discovery.spec.ts @@ -0,0 +1,147 @@ +import type { IdentifyResult } from "@libp2p/interface"; +import { TypedEventEmitter } from "@libp2p/interface"; +import tests from "@libp2p/interface-compliance-tests/peer-discovery"; +import { prefixLogger } from "@libp2p/logger"; +import { createSecp256k1PeerId } from "@libp2p/peer-id-factory"; +import { createFromJSON } from "@libp2p/peer-id-factory"; +import { PersistentPeerStore } from "@libp2p/peer-store"; +import { multiaddr } from "@multiformats/multiaddr"; +import { Libp2pComponents } from "@waku/interfaces"; +import { LocalStoragePeerInfo } from "@waku/interfaces"; +import chai, { expect } from "chai"; +import chaiAsPromised from "chai-as-promised"; +import { MemoryDatastore } from "datastore-core/memory"; +import { LocalStorage } from "node-localstorage"; +import sinon from "sinon"; + +import { LocalStorageDiscovery } from "./index.js"; + +chai.use(chaiAsPromised); + +global.localStorage = new LocalStorage("./mock_local_storage"); + +const mockPeers = [ + { + id: "16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD", + address: + "/ip4/127.0.0.1/tcp/8000/ws/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrD" + }, + { + id: "16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrE", + address: + "/ip4/127.0.0.1/tcp/8001/ws/p2p/16Uiu2HAm4v86W3bmT1BiH6oSPzcsSr24iDQpSN5Qa992BCjjwgrE" + } +]; + +async function setPeersInLocalStorage( + peers: LocalStoragePeerInfo[] +): Promise { + localStorage.setItem("waku:peers", JSON.stringify(peers)); +} + +describe("Local Storage Discovery", function () { + this.timeout(25_000); + let components: Libp2pComponents; + + beforeEach(async function () { + localStorage.clear(); + components = { + peerStore: new PersistentPeerStore({ + events: new TypedEventEmitter(), + peerId: await createSecp256k1PeerId(), + datastore: new MemoryDatastore(), + logger: prefixLogger("local_discovery.spec.ts") + }), + events: new TypedEventEmitter() + } as unknown as Libp2pComponents; + }); + + describe("Compliance Tests", function () { + beforeEach(async function () { + await setPeersInLocalStorage([mockPeers[0]]); + }); + + tests({ + async setup() { + return new LocalStorageDiscovery(components); + }, + async teardown() {} + }); + }); + + describe("Unit Tests", function () { + let discovery: LocalStorageDiscovery; + + beforeEach(async function () { + discovery = new LocalStorageDiscovery(components); + await setPeersInLocalStorage(mockPeers); + }); + + it("should load peers from local storage and dispatch events", async () => { + const dispatchEventSpy = sinon.spy(discovery, "dispatchEvent"); + + await discovery.start(); + + expect(dispatchEventSpy.calledWith(sinon.match.has("type", "peer"))).to.be + .true; + mockPeers.forEach((mockPeer) => { + expect( + dispatchEventSpy.calledWith( + sinon.match.hasNested("detail.id", mockPeer.id) + ) + ).to.be.true; + }); + }); + + it("should update peers in local storage on 'peer:identify' event", async () => { + const newPeerIdentifyEvent = { + detail: { + peerId: await createFromJSON({ + id: mockPeers[1].id + }), + listenAddrs: [multiaddr(mockPeers[1].address)] + } + } as CustomEvent; + + // Directly invoke handleNewPeers to simulate receiving an 'identify' event + discovery.handleNewPeers(newPeerIdentifyEvent); + + const updatedPeers = JSON.parse( + localStorage.getItem("waku:peers") || "[]" + ); + expect(updatedPeers).to.deep.include({ + id: newPeerIdentifyEvent.detail.peerId.toString(), + address: newPeerIdentifyEvent.detail.listenAddrs[0].toString() + }); + }); + + it("should handle corrupted local storage data gracefully", async () => { + localStorage.setItem("waku:peers", "not-a-valid-json"); + + try { + await discovery.start(); + } catch (error) { + expect.fail( + "start() should not have thrown an error for corrupted local storage data" + ); + } + }); + + it("should add and remove event listeners correctly", async () => { + const addEventListenerSpy = sinon.spy( + components.events, + "addEventListener" + ); + const removeEventListenerSpy = sinon.spy( + components.events, + "removeEventListener" + ); + + await discovery.start(); + expect(addEventListenerSpy.calledWith("peer:identify")).to.be.true; + + await discovery.stop(); + expect(removeEventListenerSpy.calledWith("peer:identify")).to.be.true; + }); + }); +}); diff --git a/packages/local-discovery/tsconfig.dev.json b/packages/local-discovery/tsconfig.dev.json new file mode 100644 index 000000000..4f7c34af3 --- /dev/null +++ b/packages/local-discovery/tsconfig.dev.json @@ -0,0 +1,3 @@ +{ + "extends": "../../tsconfig.dev" +} diff --git a/packages/local-discovery/tsconfig.json b/packages/local-discovery/tsconfig.json new file mode 100644 index 000000000..eebbc5158 --- /dev/null +++ b/packages/local-discovery/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig", + "compilerOptions": { + "outDir": "dist/", + "rootDir": "src", + "tsBuildInfoFile": "dist/.tsbuildinfo" + }, + "include": ["src"], + "exclude": ["src/**/*.spec.ts", "src/test_utils"] +} diff --git a/packages/local-discovery/typedoc.json b/packages/local-discovery/typedoc.json new file mode 100644 index 000000000..00aa3dc06 --- /dev/null +++ b/packages/local-discovery/typedoc.json @@ -0,0 +1,4 @@ +{ + "extends": ["../../typedoc.base.json"], + "entryPoints": ["src/index.ts"] +} \ No newline at end of file diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 690cd2f1b..c5fccaaa6 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -69,6 +69,7 @@ "@waku/core": "0.0.26", "@waku/dns-discovery": "0.0.20", "@waku/interfaces": "0.0.21", + "@waku/local-discovery": "^0.0.1", "@waku/peer-exchange": "^0.0.19", "@waku/relay": "0.0.9", "@waku/utils": "0.0.14", diff --git a/packages/sdk/src/create.ts b/packages/sdk/src/create.ts index 4abc43b53..c852890ca 100644 --- a/packages/sdk/src/create.ts +++ b/packages/sdk/src/create.ts @@ -28,6 +28,7 @@ import { PubsubTopic, type ShardInfo } from "@waku/interfaces"; +import { wakuLocalStorageDiscovery } from "@waku/local-discovery"; import { wakuPeerExchangeDiscovery } from "@waku/peer-exchange"; import { RelayCreateOptions, wakuGossipSub, wakuRelay } from "@waku/relay"; import { ensureShardingConfigured } from "@waku/utils"; @@ -193,6 +194,7 @@ export function defaultPeerDiscoveries( ): ((components: Libp2pComponents) => PeerDiscovery)[] { const discoveries = [ wakuDnsDiscovery([enrTree["PROD"]], DEFAULT_NODE_REQUIREMENTS), + wakuLocalStorageDiscovery(), wakuPeerExchangeDiscovery(pubsubTopics) ]; return discoveries; diff --git a/packages/utils/src/common/index.ts b/packages/utils/src/common/index.ts index 5fbc97681..906bfb948 100644 --- a/packages/utils/src/common/index.ts +++ b/packages/utils/src/common/index.ts @@ -1,3 +1,4 @@ +import type { Multiaddr } from "@multiformats/multiaddr"; export * from "./is_defined.js"; export * from "./random_subset.js"; export * from "./group_by.js"; @@ -14,3 +15,15 @@ export function removeItemFromArray(arr: unknown[], value: unknown): unknown[] { } return arr; } + +export function getWsMultiaddrFromMultiaddrs( + addresses: Multiaddr[] +): Multiaddr { + const wsMultiaddr = addresses.find( + (addr) => addr.toString().includes("ws") || addr.toString().includes("wss") + ); + if (!wsMultiaddr) { + throw new Error("No ws multiaddr found in the given addresses"); + } + return wsMultiaddr; +}