mirror of https://github.com/waku-org/js-waku.git
Merge pull request #860 from status-im/organize-modules
This commit is contained in:
commit
b4e0fb59e2
|
@ -8,3 +8,4 @@ coverage
|
||||||
*.log
|
*.log
|
||||||
/tsconfig.tsbuildinfo
|
/tsconfig.tsbuildinfo
|
||||||
/tsconfig.dev.tsbuildinfo
|
/tsconfig.dev.tsbuildinfo
|
||||||
|
/bundle/
|
||||||
|
|
|
@ -1,37 +1,40 @@
|
||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
{
|
||||||
name: "Waku core",
|
name: "Waku core",
|
||||||
path: "dist/bundle.min.js",
|
path: "bundle/index.js",
|
||||||
import: "{ Waku }",
|
import: "{ Waku }",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Waku default setup",
|
name: "Waku default setup",
|
||||||
path: "dist/bundle.min.js",
|
path: ["bundle/index.js", "bundle/lib/create_waku.js"],
|
||||||
import: "{ createWaku, waitForRemotePeer }",
|
import: {
|
||||||
|
"./bundle/lib/create_waku.js": "{ createWaku }",
|
||||||
|
"./bundle/index.js": "{ waitForRemotePeer }",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Asymmetric, symmetric encryption and signature",
|
name: "Asymmetric, symmetric encryption and signature",
|
||||||
path: "dist/bundle.min.js",
|
path: "bundle/index.js",
|
||||||
import: "{ waku_message }",
|
import: "{ WakuMessage }",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "DNS discovery",
|
name: "DNS discovery",
|
||||||
path: "dist/bundle.min.js",
|
path: "bundle/lib/peer_discovery_dns.js",
|
||||||
import: "{ discovery }",
|
import: "{ PeerDiscoveryDns }",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Privacy preserving protocols",
|
name: "Privacy preserving protocols",
|
||||||
path: "dist/bundle.min.js",
|
path: "bundle/index.js",
|
||||||
import: "{ WakuRelay }",
|
import: "{ WakuRelay }",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Light protocols",
|
name: "Light protocols",
|
||||||
path: "dist/bundle.min.js",
|
path: "bundle/index.js",
|
||||||
import: "{ WakuLightPush, WakuFilter }",
|
import: "{ WakuLightPush, WakuFilter }",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "History retrieval protocols",
|
name: "History retrieval protocols",
|
||||||
path: "dist/bundle.min.js",
|
path: "bundle/index.js",
|
||||||
import: "{ WakuStore }",
|
import: "{ WakuStore }",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -20,12 +20,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Examples: Updated store-js and relay-js to demonstrate usage of ESM bundle in `<script>` tag.
|
- Examples: Updated store-js and relay-js to demonstrate usage of ESM bundle in `<script>` tag.
|
||||||
- Remove need to polyfill `buffer`.
|
- Remove need to polyfill `buffer`.
|
||||||
- **breaking**: Various API changes. Refer to tests to check proper usage of the new API.
|
- **breaking**: Various API changes. Refer to tests to check proper usage of the new API.
|
||||||
|
- **breaking**: `createWaku` is in separate exports path.
|
||||||
|
- **breaking**: Bootstrap class split: dns discovery, static list.
|
||||||
|
- **breaking**: bundled files are now under `bundle/`.
|
||||||
|
|
||||||
### Fix
|
### Fixed
|
||||||
|
|
||||||
- size-limit config to test several usages of Waku.
|
- size-limit config to test several usages of Waku.
|
||||||
- `buffer` is not needed in the browser.
|
- `buffer` is not needed in the browser.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- `terser` minification and `gzip` compressions have been removed.
|
||||||
|
|
||||||
## [0.24.0] - 2022-05-27
|
## [0.24.0] - 2022-05-27
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -27,10 +27,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createWaku,
|
|
||||||
waitForRemotePeer,
|
waitForRemotePeer,
|
||||||
WakuMessage
|
WakuMessage
|
||||||
} from '../../dist/bundle.js';
|
} from '../../bundle/index.js';
|
||||||
|
import {
|
||||||
|
createWaku,
|
||||||
|
} from '../../bundle/lib/create_waku.js';
|
||||||
|
|
||||||
const statusDiv = document.getElementById('status');
|
const statusDiv = document.getElementById('status');
|
||||||
const messagesDiv = document.getElementById('messages');
|
const messagesDiv = document.getElementById('messages');
|
||||||
|
@ -56,7 +58,7 @@
|
||||||
// We are currently working on migrating this method to DNS Discovery.
|
// We are currently working on migrating this method to DNS Discovery.
|
||||||
//
|
//
|
||||||
// https://js-waku.wakuconnect.dev/classes/waku.Waku.html#create
|
// https://js-waku.wakuconnect.dev/classes/waku.Waku.html#create
|
||||||
const waku = await createWaku({ bootstrap: { default: true } });
|
const waku = await createWaku({ defaultBootstrap: true });
|
||||||
await waku.start();
|
await waku.start();
|
||||||
|
|
||||||
// Had a hook to process all incoming messages on a specified content topic.
|
// Had a hook to process all incoming messages on a specified content topic.
|
||||||
|
|
|
@ -14,10 +14,12 @@
|
||||||
|
|
||||||
<script type='module'>
|
<script type='module'>
|
||||||
import {
|
import {
|
||||||
createWaku,
|
|
||||||
waitForRemotePeer,
|
waitForRemotePeer,
|
||||||
Protocols
|
Protocols
|
||||||
} from '../../dist/bundle.min.js';
|
} from '../../bundle/index.js';
|
||||||
|
import {
|
||||||
|
createWaku,
|
||||||
|
} from '../../bundle/lib/create_waku.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This example demonstrates how to use the js-waku minified bundle
|
* This example demonstrates how to use the js-waku minified bundle
|
||||||
|
@ -30,7 +32,7 @@
|
||||||
|
|
||||||
try {
|
try {
|
||||||
timestampDiv.innerHTML = '<p>Creating waku.</p>';
|
timestampDiv.innerHTML = '<p>Creating waku.</p>';
|
||||||
const node = await createWaku({ bootstrap: { default: true } });
|
const node = await createWaku({ defaultBootstrap: true });
|
||||||
|
|
||||||
timestampDiv.innerHTML = '<p>Starting waku.</p>';
|
timestampDiv.innerHTML = '<p>Starting waku.</p>';
|
||||||
await node.start();
|
await node.start();
|
||||||
|
|
|
@ -83,7 +83,6 @@
|
||||||
"rollup": "^2.75.0",
|
"rollup": "^2.75.0",
|
||||||
"size-limit": "^8.0.0",
|
"size-limit": "^8.0.0",
|
||||||
"tail": "^2.2.0",
|
"tail": "^2.2.0",
|
||||||
"terser": "^5.13.1",
|
|
||||||
"ts-loader": "^9.2.6",
|
"ts-loader": "^9.2.6",
|
||||||
"ts-node": "^10.4.0",
|
"ts-node": "^10.4.0",
|
||||||
"typedoc": "^0.22.10",
|
"typedoc": "^0.22.10",
|
||||||
|
@ -798,6 +797,64 @@
|
||||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@jridgewell/gen-mapping": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/set-array": "^1.0.1",
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/resolve-uri": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/set-array": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/source-map": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/gen-mapping": "^0.3.0",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/sourcemap-codec": {
|
||||||
|
"version": "1.4.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
|
||||||
|
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/@jridgewell/trace-mapping": {
|
||||||
|
"version": "0.3.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
|
||||||
|
"integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@jridgewell/resolve-uri": "^3.0.3",
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@leichtgewicht/base64-codec": {
|
"node_modules/@leichtgewicht/base64-codec": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/base64-codec/-/base64-codec-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@leichtgewicht/base64-codec/-/base64-codec-1.0.0.tgz",
|
||||||
|
@ -7571,12 +7628,6 @@
|
||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/lodash.sortby": {
|
|
||||||
"version": "4.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
|
||||||
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/log-symbols": {
|
"node_modules/log-symbols": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
||||||
|
@ -10568,14 +10619,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/terser": {
|
"node_modules/terser": {
|
||||||
"version": "5.13.1",
|
"version": "5.14.2",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
|
||||||
"integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==",
|
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@jridgewell/source-map": "^0.3.2",
|
||||||
"acorn": "^8.5.0",
|
"acorn": "^8.5.0",
|
||||||
"commander": "^2.20.0",
|
"commander": "^2.20.0",
|
||||||
"source-map": "~0.8.0-beta.0",
|
|
||||||
"source-map-support": "~0.5.20"
|
"source-map-support": "~0.5.20"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -10664,44 +10715,6 @@
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/terser/node_modules/source-map": {
|
|
||||||
"version": "0.8.0-beta.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz",
|
|
||||||
"integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"whatwg-url": "^7.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/terser/node_modules/tr46": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"punycode": "^2.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/terser/node_modules/webidl-conversions": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/terser/node_modules/whatwg-url": {
|
|
||||||
"version": "7.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
|
|
||||||
"integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"lodash.sortby": "^4.7.0",
|
|
||||||
"tr46": "^1.0.1",
|
|
||||||
"webidl-conversions": "^4.0.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/text-table": {
|
"node_modules/text-table": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||||
|
@ -12381,6 +12394,55 @@
|
||||||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@jridgewell/gen-mapping": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@jridgewell/set-array": "^1.0.1",
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@jridgewell/resolve-uri": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@jridgewell/set-array": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@jridgewell/source-map": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@jridgewell/gen-mapping": "^0.3.0",
|
||||||
|
"@jridgewell/trace-mapping": "^0.3.9"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@jridgewell/sourcemap-codec": {
|
||||||
|
"version": "1.4.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
|
||||||
|
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@jridgewell/trace-mapping": {
|
||||||
|
"version": "0.3.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz",
|
||||||
|
"integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@jridgewell/resolve-uri": "^3.0.3",
|
||||||
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@leichtgewicht/base64-codec": {
|
"@leichtgewicht/base64-codec": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/base64-codec/-/base64-codec-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@leichtgewicht/base64-codec/-/base64-codec-1.0.0.tgz",
|
||||||
|
@ -17593,12 +17655,6 @@
|
||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lodash.sortby": {
|
|
||||||
"version": "4.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
|
||||||
"integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"log-symbols": {
|
"log-symbols": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
||||||
|
@ -19794,14 +19850,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"terser": {
|
"terser": {
|
||||||
"version": "5.13.1",
|
"version": "5.14.2",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
|
||||||
"integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==",
|
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"@jridgewell/source-map": "^0.3.2",
|
||||||
"acorn": "^8.5.0",
|
"acorn": "^8.5.0",
|
||||||
"commander": "^2.20.0",
|
"commander": "^2.20.0",
|
||||||
"source-map": "~0.8.0-beta.0",
|
|
||||||
"source-map-support": "~0.5.20"
|
"source-map-support": "~0.5.20"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -19810,41 +19866,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
|
||||||
"source-map": {
|
|
||||||
"version": "0.8.0-beta.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz",
|
|
||||||
"integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"whatwg-url": "^7.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tr46": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"punycode": "^2.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"webidl-conversions": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"whatwg-url": {
|
|
||||||
"version": "7.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
|
|
||||||
"integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"lodash.sortby": "^4.7.0",
|
|
||||||
"tr46": "^1.0.1",
|
|
||||||
"webidl-conversions": "^4.0.2"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
13
package.json
13
package.json
|
@ -8,6 +8,14 @@
|
||||||
".": {
|
".": {
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
"import": "./dist/index.js"
|
"import": "./dist/index.js"
|
||||||
|
},
|
||||||
|
"./lib/create_waku": {
|
||||||
|
"types": "./dist/lib/create_waku.d.ts",
|
||||||
|
"import": "./dist/lib/create_waku.js"
|
||||||
|
},
|
||||||
|
"./lib/peer_discovery_dns": {
|
||||||
|
"types": "./dist/lib/peer_discovery_dns/index.d.ts",
|
||||||
|
"import": "./dist/lib/peer_discovery_dns/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
@ -25,8 +33,7 @@
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
"build": "run-s build:**",
|
"build": "run-s build:**",
|
||||||
"build:esm": "tsc && node build-scripts/fix-imports.js",
|
"build:esm": "tsc && node build-scripts/fix-imports.js",
|
||||||
"build:bundle": "rollup --config rollup.config.js -- dist/index.js",
|
"build:bundle": "rollup --config rollup.config.js",
|
||||||
"build:bundle:min": "terser --ecma 11 --compress --mangle -o dist/bundle.min.js -- dist/bundle.js && gzip -9 -c dist/bundle.min.js > dist/bundle.min.js.gz",
|
|
||||||
"size": "npm run build && size-limit",
|
"size": "npm run build && size-limit",
|
||||||
"fix": "run-s fix:*",
|
"fix": "run-s fix:*",
|
||||||
"fix:prettier": "prettier \"src/**/*.ts\" \"./*.json\" \"*.*js\" \".github/**/*.yml\" --write",
|
"fix:prettier": "prettier \"src/**/*.ts\" \"./*.json\" \"*.*js\" \".github/**/*.yml\" --write",
|
||||||
|
@ -137,7 +144,6 @@
|
||||||
"rollup": "^2.75.0",
|
"rollup": "^2.75.0",
|
||||||
"size-limit": "^8.0.0",
|
"size-limit": "^8.0.0",
|
||||||
"tail": "^2.2.0",
|
"tail": "^2.2.0",
|
||||||
"terser": "^5.13.1",
|
|
||||||
"ts-loader": "^9.2.6",
|
"ts-loader": "^9.2.6",
|
||||||
"ts-node": "^10.4.0",
|
"ts-node": "^10.4.0",
|
||||||
"typedoc": "^0.22.10",
|
"typedoc": "^0.22.10",
|
||||||
|
@ -146,6 +152,7 @@
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
|
"bundle",
|
||||||
"src/*.ts",
|
"src/*.ts",
|
||||||
"src/lib/**/*.ts",
|
"src/lib/**/*.ts",
|
||||||
"src/proto/**/*.ts",
|
"src/proto/**/*.ts",
|
||||||
|
|
|
@ -3,10 +3,14 @@ import commonjs from "@rollup/plugin-commonjs";
|
||||||
import json from "@rollup/plugin-json";
|
import json from "@rollup/plugin-json";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
input: {
|
||||||
|
index: "dist/index.js",
|
||||||
|
"lib/create_waku": "dist/lib/create_waku.js",
|
||||||
|
"lib/peer_discovery_dns": "dist/lib/peer_discovery_dns/index.js",
|
||||||
|
},
|
||||||
output: {
|
output: {
|
||||||
file: "dist/bundle.js",
|
dir: "bundle",
|
||||||
format: "esm",
|
format: "esm",
|
||||||
name: "waku",
|
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
commonjs(),
|
commonjs(),
|
||||||
|
|
|
@ -6,9 +6,6 @@ export {
|
||||||
getPublicKey,
|
getPublicKey,
|
||||||
} from "./lib/crypto";
|
} from "./lib/crypto";
|
||||||
|
|
||||||
export { getPredefinedBootstrapNodes } from "./lib/discovery";
|
|
||||||
export * as discovery from "./lib/discovery";
|
|
||||||
|
|
||||||
export * as enr from "./lib/enr";
|
export * as enr from "./lib/enr";
|
||||||
|
|
||||||
export * as utils from "./lib/utils";
|
export * as utils from "./lib/utils";
|
||||||
|
@ -18,7 +15,7 @@ export { waitForRemotePeer } from "./lib/wait_for_remote_peer";
|
||||||
export * as proto_message from "./proto/message";
|
export * as proto_message from "./proto/message";
|
||||||
|
|
||||||
export * as waku from "./lib/waku";
|
export * as waku from "./lib/waku";
|
||||||
export { createWaku, Waku, Protocols } from "./lib/waku";
|
export { Waku, Protocols } from "./lib/waku";
|
||||||
|
|
||||||
export * as waku_message from "./lib/waku_message";
|
export * as waku_message from "./lib/waku_message";
|
||||||
export { WakuMessage } from "./lib/waku_message";
|
export { WakuMessage } from "./lib/waku_message";
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
import { Noise } from "@chainsafe/libp2p-noise";
|
||||||
|
import type { PeerDiscovery } from "@libp2p/interface-peer-discovery";
|
||||||
|
import { Mplex } from "@libp2p/mplex";
|
||||||
|
import { WebSockets } from "@libp2p/websockets";
|
||||||
|
import { all as filterAll } from "@libp2p/websockets/filters";
|
||||||
|
import { createLibp2p, Libp2pOptions } from "libp2p";
|
||||||
|
import type { Libp2p } from "libp2p";
|
||||||
|
|
||||||
|
import { PeerDiscoveryStaticPeers } from "./peer_discovery_static_list";
|
||||||
|
import { getPredefinedBootstrapNodes } from "./predefined_bootstrap_nodes";
|
||||||
|
import { Waku, WakuOptions } from "./waku";
|
||||||
|
import { WakuFilter } from "./waku_filter";
|
||||||
|
import { WakuLightPush } from "./waku_light_push";
|
||||||
|
import { WakuRelay } from "./waku_relay";
|
||||||
|
import { WakuStore } from "./waku_store";
|
||||||
|
|
||||||
|
export interface CreateOptions {
|
||||||
|
/**
|
||||||
|
* The PubSub Topic to use. Defaults to {@link DefaultPubSubTopic}.
|
||||||
|
*
|
||||||
|
* One and only one pubsub topic is used by Waku. This is used by:
|
||||||
|
* - WakuRelay to receive, route and send messages,
|
||||||
|
* - WakuLightPush to send messages,
|
||||||
|
* - WakuStore to retrieve messages.
|
||||||
|
*
|
||||||
|
* The usage of the default pubsub topic is recommended.
|
||||||
|
* See [Waku v2 Topic Usage Recommendations](https://rfc.vac.dev/spec/23/) for details.
|
||||||
|
*
|
||||||
|
* @default {@link DefaultPubSubTopic}
|
||||||
|
*/
|
||||||
|
pubSubTopic?: string;
|
||||||
|
/**
|
||||||
|
* You can pass options to the `Libp2p` instance used by {@link Waku} using the {@link CreateOptions.libp2p} property.
|
||||||
|
* This property is the same type than the one passed to [`Libp2p.create`](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#create)
|
||||||
|
* apart that we made the `modules` property optional and partial,
|
||||||
|
* allowing its omission and letting Waku set good defaults.
|
||||||
|
* Notes that some values are overridden by {@link Waku} to ensure it implements the Waku protocol.
|
||||||
|
*/
|
||||||
|
libp2p?: Partial<Libp2pOptions>;
|
||||||
|
/**
|
||||||
|
* Byte array used as key for the noise protocol used for connection encryption
|
||||||
|
* by [`Libp2p.create`](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#create)
|
||||||
|
* This is only used for test purposes to not run out of entropy during CI runs.
|
||||||
|
*/
|
||||||
|
staticNoiseKey?: Uint8Array;
|
||||||
|
/**
|
||||||
|
* Use recommended bootstrap method to discovery and connect to new nodes.
|
||||||
|
*/
|
||||||
|
defaultBootstrap?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createWaku(
|
||||||
|
options?: CreateOptions & WakuOptions
|
||||||
|
): Promise<Waku> {
|
||||||
|
const libp2pOptions = options?.libp2p ?? {};
|
||||||
|
const peerDiscovery = libp2pOptions.peerDiscovery ?? [];
|
||||||
|
if (options?.defaultBootstrap) {
|
||||||
|
peerDiscovery.push(defaultPeerDiscovery());
|
||||||
|
Object.assign(libp2pOptions, { peerDiscovery });
|
||||||
|
}
|
||||||
|
|
||||||
|
const libp2p = await defaultLibp2p(new WakuRelay(options), libp2pOptions);
|
||||||
|
|
||||||
|
const wakuStore = new WakuStore(libp2p, options);
|
||||||
|
const wakuLightPush = new WakuLightPush(libp2p, options);
|
||||||
|
const wakuFilter = new WakuFilter(libp2p, options);
|
||||||
|
|
||||||
|
return new Waku(options ?? {}, libp2p, wakuStore, wakuLightPush, wakuFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function defaultPeerDiscovery(): PeerDiscovery {
|
||||||
|
return new PeerDiscoveryStaticPeers(getPredefinedBootstrapNodes());
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function defaultLibp2p(
|
||||||
|
wakuRelay: WakuRelay,
|
||||||
|
options?: Partial<Libp2pOptions>
|
||||||
|
): Promise<Libp2p> {
|
||||||
|
const libp2pOpts = Object.assign(
|
||||||
|
{
|
||||||
|
transports: [new WebSockets({ filter: filterAll })],
|
||||||
|
streamMuxers: [new Mplex()],
|
||||||
|
connectionEncryption: [new Noise()],
|
||||||
|
},
|
||||||
|
{ pubsub: wakuRelay },
|
||||||
|
options ?? {}
|
||||||
|
);
|
||||||
|
|
||||||
|
return createLibp2p(libp2pOpts);
|
||||||
|
}
|
|
@ -1,244 +0,0 @@
|
||||||
import type {
|
|
||||||
PeerDiscovery,
|
|
||||||
PeerDiscoveryEvents,
|
|
||||||
} from "@libp2p/interface-peer-discovery";
|
|
||||||
import { symbol } from "@libp2p/interface-peer-discovery";
|
|
||||||
import type { PeerInfo } from "@libp2p/interface-peer-info";
|
|
||||||
import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events";
|
|
||||||
import { peerIdFromString } from "@libp2p/peer-id";
|
|
||||||
import { Multiaddr } from "@multiformats/multiaddr";
|
|
||||||
import debug from "debug";
|
|
||||||
|
|
||||||
import { DnsNodeDiscovery, NodeCapabilityCount } from "./dns";
|
|
||||||
import { getPredefinedBootstrapNodes } from "./predefined";
|
|
||||||
import { getPseudoRandomSubset } from "./random_subset";
|
|
||||||
|
|
||||||
const log = debug("waku:discovery:bootstrap");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup discovery method used to bootstrap.
|
|
||||||
*
|
|
||||||
* Only one method is used. [[default]], [[peers]], [[getPeers]] and [[enrUrl]] options are mutually exclusive.
|
|
||||||
*/
|
|
||||||
export interface BootstrapOptions {
|
|
||||||
/**
|
|
||||||
* The maximum of peers to connect to as part of the bootstrap process.
|
|
||||||
* This only applies if [[peers]] or [[getPeers]] is used.
|
|
||||||
*
|
|
||||||
* @default [[Bootstrap.DefaultMaxPeers]]
|
|
||||||
*/
|
|
||||||
maxPeers?: number;
|
|
||||||
/**
|
|
||||||
* Use the default discovery method. Overrides all other options but `maxPeers`
|
|
||||||
*
|
|
||||||
* The default discovery method is likely to change overtime as new discovery
|
|
||||||
* methods are implemented.
|
|
||||||
*
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
default?: boolean;
|
|
||||||
/**
|
|
||||||
* Multiaddrs of peers to connect to.
|
|
||||||
*/
|
|
||||||
peers?: string[] | Multiaddr[];
|
|
||||||
/**
|
|
||||||
* Getter that retrieve multiaddrs of peers to connect to.
|
|
||||||
* will be called once.
|
|
||||||
*/
|
|
||||||
getPeers?: () => Promise<string[] | Multiaddr[]>;
|
|
||||||
/**
|
|
||||||
* The interval between emitting addresses in milliseconds.
|
|
||||||
* Used if [[peers]] is passed or a sync function is passed for [[getPeers]]
|
|
||||||
*/
|
|
||||||
interval?: number;
|
|
||||||
/**
|
|
||||||
* An EIP-1459 ENR Tree URL. For example:
|
|
||||||
* "enrtree://AOFTICU2XWDULNLZGRMQS4RIZPAZEHYMV4FYHAPW563HNRAOERP7C@test.nodes.vac.dev"
|
|
||||||
*
|
|
||||||
* [[wantedNodeCapabilityCount]] MUST be passed when using this option.
|
|
||||||
*/
|
|
||||||
enrUrl?: string;
|
|
||||||
/**
|
|
||||||
* Specifies what node capabilities (protocol) must be returned.
|
|
||||||
* This only applies when [[enrUrl]] is passed (EIP-1459 DNS Discovery).
|
|
||||||
*/
|
|
||||||
wantedNodeCapabilityCount?: Partial<NodeCapabilityCount>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse options and expose function to return bootstrap peer addresses.
|
|
||||||
*
|
|
||||||
* @throws if an invalid combination of options is passed, see [[BootstrapOptions]] for details.
|
|
||||||
*/
|
|
||||||
export class Bootstrap
|
|
||||||
extends EventEmitter<PeerDiscoveryEvents>
|
|
||||||
implements PeerDiscovery
|
|
||||||
{
|
|
||||||
static DefaultMaxPeers = 1;
|
|
||||||
|
|
||||||
private readonly asyncGetBootstrapPeers:
|
|
||||||
| (() => Promise<Multiaddr[]>)
|
|
||||||
| undefined;
|
|
||||||
private peers: PeerInfo[];
|
|
||||||
private timer?: ReturnType<typeof setInterval>;
|
|
||||||
private readonly interval: number;
|
|
||||||
|
|
||||||
constructor(opts?: BootstrapOptions) {
|
|
||||||
super();
|
|
||||||
opts = opts ?? {};
|
|
||||||
|
|
||||||
const methods = [
|
|
||||||
!!opts.default,
|
|
||||||
!!opts.peers,
|
|
||||||
!!opts.getPeers,
|
|
||||||
!!opts.enrUrl,
|
|
||||||
].filter((x) => x);
|
|
||||||
if (methods.length > 1) {
|
|
||||||
throw new Error(
|
|
||||||
"Bootstrap does not support several discovery methods (yet)"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.interval = opts.interval ?? 10000;
|
|
||||||
opts.default =
|
|
||||||
opts.default ?? (!opts.peers && !opts.getPeers && !opts.enrUrl);
|
|
||||||
const maxPeers = opts.maxPeers ?? Bootstrap.DefaultMaxPeers;
|
|
||||||
this.peers = [];
|
|
||||||
|
|
||||||
if (opts.default) {
|
|
||||||
log("Use hosted list of peers.");
|
|
||||||
|
|
||||||
this.peers = multiaddrsToPeerInfo(
|
|
||||||
getPredefinedBootstrapNodes(undefined, maxPeers)
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!opts.peers && opts.peers.length > 0) {
|
|
||||||
const allPeers: Multiaddr[] = opts.peers.map(
|
|
||||||
(node: string | Multiaddr) => {
|
|
||||||
if (typeof node === "string") {
|
|
||||||
return new Multiaddr(node);
|
|
||||||
} else {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
this.peers = multiaddrsToPeerInfo(
|
|
||||||
getPseudoRandomSubset(allPeers, maxPeers)
|
|
||||||
);
|
|
||||||
log(
|
|
||||||
"Use provided list of peers (reduced to maxPeers)",
|
|
||||||
this.peers.map((ma) => ma.toString())
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof opts.getPeers === "function") {
|
|
||||||
log("Bootstrap: Use provided getPeers function.");
|
|
||||||
const getPeers = opts.getPeers;
|
|
||||||
|
|
||||||
this.asyncGetBootstrapPeers = async () => {
|
|
||||||
const allPeers = await getPeers();
|
|
||||||
return getPseudoRandomSubset<string | Multiaddr>(
|
|
||||||
allPeers,
|
|
||||||
maxPeers
|
|
||||||
).map((node) => new Multiaddr(node));
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.enrUrl) {
|
|
||||||
const wantedNodeCapabilityCount = opts.wantedNodeCapabilityCount;
|
|
||||||
if (!wantedNodeCapabilityCount)
|
|
||||||
throw "`wantedNodeCapabilityCount` must be defined when using `enrUrl`";
|
|
||||||
const enrUrl = opts.enrUrl;
|
|
||||||
log("Use provided EIP-1459 ENR Tree URL.");
|
|
||||||
|
|
||||||
const dns = DnsNodeDiscovery.dnsOverHttp();
|
|
||||||
|
|
||||||
this.asyncGetBootstrapPeers = async () => {
|
|
||||||
const enrs = await dns.getPeers([enrUrl], wantedNodeCapabilityCount);
|
|
||||||
log(`Found ${enrs.length} peers`);
|
|
||||||
return enrs.map((enr) => enr.getFullMultiaddrs()).flat();
|
|
||||||
};
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start discovery process
|
|
||||||
*/
|
|
||||||
start(): void {
|
|
||||||
if (this.asyncGetBootstrapPeers) {
|
|
||||||
// TODO: This should emit the peer as they are discovered instead of having
|
|
||||||
// to wait for the full DNS discovery process to be done first.
|
|
||||||
// TODO: PeerInfo should be returned by discovery
|
|
||||||
this.asyncGetBootstrapPeers().then((peers) => {
|
|
||||||
this.peers = multiaddrsToPeerInfo(peers);
|
|
||||||
this._startTimer();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this._startTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _startTimer(): void {
|
|
||||||
if (this.peers) {
|
|
||||||
log("Starting bootstrap node discovery");
|
|
||||||
if (this.timer != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.timer = setInterval(() => this._returnPeers(), this.interval);
|
|
||||||
|
|
||||||
this._returnPeers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_returnPeers(): void {
|
|
||||||
if (this.timer == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.peers.forEach((peerData) => {
|
|
||||||
this.dispatchEvent(
|
|
||||||
new CustomEvent<PeerInfo>("peer", { detail: peerData })
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop emitting events
|
|
||||||
*/
|
|
||||||
stop(): void {
|
|
||||||
if (this.timer != null) {
|
|
||||||
clearInterval(this.timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.timer = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
get [symbol](): true {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get [Symbol.toStringTag](): string {
|
|
||||||
return "@waku/bootstrap";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function multiaddrsToPeerInfo(mas: Multiaddr[]): PeerInfo[] {
|
|
||||||
return mas
|
|
||||||
.map((ma) => {
|
|
||||||
const peerIdStr = ma.getPeerId();
|
|
||||||
const protocols: string[] = [];
|
|
||||||
return {
|
|
||||||
id: peerIdStr ? peerIdFromString(peerIdStr) : null,
|
|
||||||
multiaddrs: [ma.decapsulateCode(421)],
|
|
||||||
protocols,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.filter((peerInfo): peerInfo is PeerInfo => peerInfo.id !== null);
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
export { getPredefinedBootstrapNodes } from "./predefined";
|
|
||||||
export * as predefined from "./predefined";
|
|
||||||
export { Bootstrap, BootstrapOptions } from "./bootstrap";
|
|
||||||
export * as dns from "./dns";
|
|
||||||
export { DnsOverHttps } from "./dns_over_https";
|
|
||||||
export { ENRTree, ENRTreeValues, ENRRootValues } from "./enrtree";
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
||||||
|
import { createWaku } from "../create_waku";
|
||||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||||
import { createWaku, Protocols, Waku } from "../waku";
|
import { Protocols, Waku } from "../waku";
|
||||||
|
|
||||||
import { ENR } from "./enr";
|
import { ENR } from "./enr";
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { PeerInfo } from "@libp2p/interface-peer-info";
|
||||||
|
import { peerIdFromString } from "@libp2p/peer-id";
|
||||||
|
import { Multiaddr } from "@multiformats/multiaddr";
|
||||||
|
|
||||||
|
export function multiaddrsToPeerInfo(mas: Multiaddr[]): PeerInfo[] {
|
||||||
|
return mas
|
||||||
|
.map((ma) => {
|
||||||
|
const peerIdStr = ma.getPeerId();
|
||||||
|
const protocols: string[] = [];
|
||||||
|
return {
|
||||||
|
id: peerIdStr ? peerIdFromString(peerIdStr) : null,
|
||||||
|
multiaddrs: [ma.decapsulateCode(421)],
|
||||||
|
protocols,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter((peerInfo): peerInfo is PeerInfo => peerInfo.id !== null);
|
||||||
|
}
|
|
@ -4,7 +4,10 @@ import { ENR } from "../enr";
|
||||||
|
|
||||||
import { DnsOverHttps } from "./dns_over_https";
|
import { DnsOverHttps } from "./dns_over_https";
|
||||||
import { ENRTree } from "./enrtree";
|
import { ENRTree } from "./enrtree";
|
||||||
import fetchNodesUntilCapabilitiesFulfilled from "./fetch_nodes";
|
import {
|
||||||
|
fetchNodesUntilCapabilitiesFulfilled,
|
||||||
|
yieldNodesUntilCapabilitiesFulfilled,
|
||||||
|
} from "./fetch_nodes";
|
||||||
|
|
||||||
const dbg = debug("waku:discovery:dns");
|
const dbg = debug("waku:discovery:dns");
|
||||||
|
|
||||||
|
@ -70,6 +73,30 @@ export class DnsNodeDiscovery {
|
||||||
this.dns = dns;
|
this.dns = dns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@docInherit getPeers}
|
||||||
|
*/
|
||||||
|
async *getNextPeer(
|
||||||
|
enrTreeUrls: string[],
|
||||||
|
wantedNodeCapabilityCount: Partial<NodeCapabilityCount>
|
||||||
|
): AsyncGenerator<ENR> {
|
||||||
|
const networkIndex = Math.floor(Math.random() * enrTreeUrls.length);
|
||||||
|
const { publicKey, domain } = ENRTree.parseTree(enrTreeUrls[networkIndex]);
|
||||||
|
const context: SearchContext = {
|
||||||
|
domain,
|
||||||
|
publicKey,
|
||||||
|
visits: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
for await (const peer of yieldNodesUntilCapabilitiesFulfilled(
|
||||||
|
wantedNodeCapabilityCount,
|
||||||
|
this._errorTolerance,
|
||||||
|
() => this._search(domain, context)
|
||||||
|
)) {
|
||||||
|
yield peer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a recursive, randomized descent of the DNS tree to retrieve a single
|
* Runs a recursive, randomized descent of the DNS tree to retrieve a single
|
||||||
* ENR record as an ENR. Returns null if parsing or DNS resolution fails.
|
* ENR record as an ENR. Returns null if parsing or DNS resolution fails.
|
|
@ -4,7 +4,7 @@ import { expect } from "chai";
|
||||||
|
|
||||||
import { ENR, Waku2 } from "../enr";
|
import { ENR, Waku2 } from "../enr";
|
||||||
|
|
||||||
import fetchNodesUntilCapabilitiesFulfilled from "./fetch_nodes";
|
import { fetchNodesUntilCapabilitiesFulfilled } from "./fetch_nodes";
|
||||||
|
|
||||||
async function createEnr(waku2: Waku2): Promise<ENR> {
|
async function createEnr(waku2: Waku2): Promise<ENR> {
|
||||||
const peerId = await createSecp256k1PeerId();
|
const peerId = await createSecp256k1PeerId();
|
|
@ -11,7 +11,7 @@ const dbg = debug("waku:discovery:fetch_nodes");
|
||||||
* fulfilled or the number of [[getNode]] call exceeds the sum of
|
* fulfilled or the number of [[getNode]] call exceeds the sum of
|
||||||
* [[wantedNodeCapabilityCount]] plus [[errorTolerance]].
|
* [[wantedNodeCapabilityCount]] plus [[errorTolerance]].
|
||||||
*/
|
*/
|
||||||
export default async function fetchNodesUntilCapabilitiesFulfilled(
|
export async function fetchNodesUntilCapabilitiesFulfilled(
|
||||||
wantedNodeCapabilityCount: Partial<NodeCapabilityCount>,
|
wantedNodeCapabilityCount: Partial<NodeCapabilityCount>,
|
||||||
errorTolerance: number,
|
errorTolerance: number,
|
||||||
getNode: () => Promise<ENR | null>
|
getNode: () => Promise<ENR | null>
|
||||||
|
@ -57,6 +57,56 @@ export default async function fetchNodesUntilCapabilitiesFulfilled(
|
||||||
return peers;
|
return peers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch nodes using passed [[getNode]] until all wanted capabilities are
|
||||||
|
* fulfilled or the number of [[getNode]] call exceeds the sum of
|
||||||
|
* [[wantedNodeCapabilityCount]] plus [[errorTolerance]].
|
||||||
|
*/
|
||||||
|
export async function* yieldNodesUntilCapabilitiesFulfilled(
|
||||||
|
wantedNodeCapabilityCount: Partial<NodeCapabilityCount>,
|
||||||
|
errorTolerance: number,
|
||||||
|
getNode: () => Promise<ENR | null>
|
||||||
|
): AsyncGenerator<ENR> {
|
||||||
|
const wanted = {
|
||||||
|
relay: wantedNodeCapabilityCount.relay ?? 0,
|
||||||
|
store: wantedNodeCapabilityCount.store ?? 0,
|
||||||
|
filter: wantedNodeCapabilityCount.filter ?? 0,
|
||||||
|
lightPush: wantedNodeCapabilityCount.lightPush ?? 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const maxSearches =
|
||||||
|
wanted.relay + wanted.store + wanted.filter + wanted.lightPush;
|
||||||
|
|
||||||
|
const actual = {
|
||||||
|
relay: 0,
|
||||||
|
store: 0,
|
||||||
|
filter: 0,
|
||||||
|
lightPush: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let totalSearches = 0;
|
||||||
|
const peerNodeIds = new Set();
|
||||||
|
|
||||||
|
while (
|
||||||
|
!isSatisfied(wanted, actual) &&
|
||||||
|
totalSearches < maxSearches + errorTolerance
|
||||||
|
) {
|
||||||
|
const peer = await getNode();
|
||||||
|
if (peer && peer.nodeId && !peerNodeIds.has(peer.nodeId)) {
|
||||||
|
peerNodeIds.add(peer.nodeId);
|
||||||
|
// ENRs without a waku2 key are ignored.
|
||||||
|
if (peer.waku2) {
|
||||||
|
if (helpsSatisfyCapabilities(peer.waku2, wanted, actual)) {
|
||||||
|
addCapabilities(peer.waku2, actual);
|
||||||
|
yield peer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbg(`got new peer candidate from DNS address=${peer.nodeId}@${peer.ip}`);
|
||||||
|
}
|
||||||
|
totalSearches++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function isSatisfied(
|
function isSatisfied(
|
||||||
wanted: NodeCapabilityCount,
|
wanted: NodeCapabilityCount,
|
||||||
actual: NodeCapabilityCount
|
actual: NodeCapabilityCount
|
|
@ -1,6 +1,6 @@
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { getPseudoRandomSubset } from "./random_subset";
|
import { getPseudoRandomSubset } from "../random_subset";
|
||||||
|
|
||||||
describe("Discovery", () => {
|
describe("Discovery", () => {
|
||||||
it("returns all values when wanted number matches available values", function () {
|
it("returns all values when wanted number matches available values", function () {
|
|
@ -0,0 +1,84 @@
|
||||||
|
import type {
|
||||||
|
PeerDiscovery,
|
||||||
|
PeerDiscoveryEvents,
|
||||||
|
} from "@libp2p/interface-peer-discovery";
|
||||||
|
import { symbol } from "@libp2p/interface-peer-discovery";
|
||||||
|
import type { PeerInfo } from "@libp2p/interface-peer-info";
|
||||||
|
import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events";
|
||||||
|
import debug from "debug";
|
||||||
|
|
||||||
|
import { ENR } from "../enr";
|
||||||
|
import { multiaddrsToPeerInfo } from "../multiaddr_to_peer_info";
|
||||||
|
|
||||||
|
import { DnsNodeDiscovery, NodeCapabilityCount } from "./dns";
|
||||||
|
|
||||||
|
const log = debug("waku:peer-discovery-dns");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse options and expose function to return bootstrap peer addresses.
|
||||||
|
*
|
||||||
|
* @throws if an invalid combination of options is passed, see [[BootstrapOptions]] for details.
|
||||||
|
*/
|
||||||
|
export class PeerDiscoveryDns
|
||||||
|
extends EventEmitter<PeerDiscoveryEvents>
|
||||||
|
implements PeerDiscovery
|
||||||
|
{
|
||||||
|
private readonly nextPeer: () => AsyncGenerator<ENR>;
|
||||||
|
private _started: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param enrUrl An EIP-1459 ENR Tree URL. For example:
|
||||||
|
* "enrtree://AOFTICU2XWDULNLZGRMQS4RIZPAZEHYMV4FYHAPW563HNRAOERP7C@test.nodes.vac.dev"
|
||||||
|
* @param wantedNodeCapabilityCount Specifies what node capabilities
|
||||||
|
* (protocol) must be returned.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
enrUrl: string,
|
||||||
|
wantedNodeCapabilityCount: Partial<NodeCapabilityCount>
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
this._started = false;
|
||||||
|
log("Use following EIP-1459 ENR Tree URL: ", enrUrl);
|
||||||
|
|
||||||
|
const dns = DnsNodeDiscovery.dnsOverHttp();
|
||||||
|
|
||||||
|
this.nextPeer = dns.getNextPeer.bind(
|
||||||
|
{},
|
||||||
|
[enrUrl],
|
||||||
|
wantedNodeCapabilityCount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start discovery process
|
||||||
|
*/
|
||||||
|
async start(): Promise<void> {
|
||||||
|
log("Starting peer discovery via dns");
|
||||||
|
|
||||||
|
this._started = true;
|
||||||
|
for await (const peer of this.nextPeer()) {
|
||||||
|
if (!this._started) return;
|
||||||
|
const peerInfos = multiaddrsToPeerInfo(peer.getFullMultiaddrs());
|
||||||
|
peerInfos.forEach((peerInfo) => {
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent<PeerInfo>("peer", { detail: peerInfo })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop emitting events
|
||||||
|
*/
|
||||||
|
stop(): void {
|
||||||
|
this._started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
get [symbol](): true {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get [Symbol.toStringTag](): string {
|
||||||
|
return "@waku/bootstrap";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
import type {
|
||||||
|
PeerDiscovery,
|
||||||
|
PeerDiscoveryEvents,
|
||||||
|
} from "@libp2p/interface-peer-discovery";
|
||||||
|
import { symbol } from "@libp2p/interface-peer-discovery";
|
||||||
|
import type { PeerInfo } from "@libp2p/interface-peer-info";
|
||||||
|
import { CustomEvent, EventEmitter } from "@libp2p/interfaces/events";
|
||||||
|
import { Multiaddr } from "@multiformats/multiaddr";
|
||||||
|
import debug from "debug";
|
||||||
|
|
||||||
|
import { multiaddrsToPeerInfo } from "./multiaddr_to_peer_info";
|
||||||
|
import { getPseudoRandomSubset } from "./random_subset";
|
||||||
|
|
||||||
|
const log = debug("waku:peer-discovery-static-list");
|
||||||
|
|
||||||
|
export interface Options {
|
||||||
|
/**
|
||||||
|
* The maximum of peers to connect to as part of the bootstrap process.
|
||||||
|
*
|
||||||
|
* @default The length of the passed `peers` array.
|
||||||
|
*/
|
||||||
|
maxPeers?: number;
|
||||||
|
/**
|
||||||
|
* The interval between emitting addresses in milliseconds.
|
||||||
|
*
|
||||||
|
* @default {@link PeerDiscoveryEvents.DefaultInterval}
|
||||||
|
*/
|
||||||
|
interval?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse options and expose function to return bootstrap peer addresses.
|
||||||
|
*
|
||||||
|
* @throws if an invalid combination of options is passed, see [[BootstrapOptions]] for details.
|
||||||
|
*/
|
||||||
|
export class PeerDiscoveryStaticPeers
|
||||||
|
extends EventEmitter<PeerDiscoveryEvents>
|
||||||
|
implements PeerDiscovery
|
||||||
|
{
|
||||||
|
static DefaultInterval = 200;
|
||||||
|
private readonly peers: PeerInfo[];
|
||||||
|
private timer?: ReturnType<typeof setInterval>;
|
||||||
|
private readonly interval: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param peers Multiaddrs of peers to connect to.
|
||||||
|
* @param opts
|
||||||
|
*/
|
||||||
|
constructor(peers: string[] | Multiaddr[], opts?: Options) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.interval = opts?.interval ?? PeerDiscoveryStaticPeers.DefaultInterval;
|
||||||
|
const maxPeers = opts?.maxPeers ?? peers?.length;
|
||||||
|
|
||||||
|
const peerMas = peers.map((peer: string | Multiaddr) => {
|
||||||
|
if (typeof peer === "string") {
|
||||||
|
return new Multiaddr(peer);
|
||||||
|
} else {
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.peers = multiaddrsToPeerInfo(getPseudoRandomSubset(peerMas, maxPeers));
|
||||||
|
log(
|
||||||
|
"Use provided list of peers (reduced to maxPeers)",
|
||||||
|
this.peers.map((ma) => ma.toString())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start emitting static peers.
|
||||||
|
*/
|
||||||
|
start(): void {
|
||||||
|
this._startTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _startTimer(): void {
|
||||||
|
if (this.peers) {
|
||||||
|
log("Starting to emit static peers.");
|
||||||
|
if (this.timer != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timer = setInterval(() => this._returnPeers(), this.interval);
|
||||||
|
|
||||||
|
this._returnPeers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_returnPeers(): void {
|
||||||
|
if (this.timer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.peers.forEach((peerData) => {
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent<PeerInfo>("peer", { detail: peerData })
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop emitting peers.
|
||||||
|
*/
|
||||||
|
stop(): void {
|
||||||
|
if (this.timer != null) {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timer = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
get [symbol](): true {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
get [Symbol.toStringTag](): string {
|
||||||
|
return "@waku/peer-discovery-static-list";
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,8 +3,9 @@ import { expect } from "chai";
|
||||||
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../test_utils";
|
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../test_utils";
|
||||||
import { delay } from "../test_utils/delay";
|
import { delay } from "../test_utils/delay";
|
||||||
|
|
||||||
|
import { createWaku } from "./create_waku";
|
||||||
import { waitForRemotePeer } from "./wait_for_remote_peer";
|
import { waitForRemotePeer } from "./wait_for_remote_peer";
|
||||||
import { createWaku, Protocols, Waku } from "./waku";
|
import { Protocols, Waku } from "./waku";
|
||||||
|
|
||||||
describe("Wait for remote peer", function () {
|
describe("Wait for remote peer", function () {
|
||||||
let waku: Waku;
|
let waku: Waku;
|
||||||
|
|
|
@ -22,7 +22,8 @@ interface WakuGossipSubProtocol extends GossipSub {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for a remote peer to be ready given the passed protocols.
|
* Wait for a remote peer to be ready given the passed protocols.
|
||||||
* Useful when using the [[CreateOptions.bootstrap]] with [[createWaku]].
|
* Must be used after attempting to connect to nodes, using {@link Waku.dial} or
|
||||||
|
* a bootstrap method with {@link Waku.constructor}.
|
||||||
*
|
*
|
||||||
* If the passed protocols is a GossipSub protocol, then it resolves only once
|
* If the passed protocols is a GossipSub protocol, then it resolves only once
|
||||||
* a peer is in a mesh, to help ensure that other peers will send and receive
|
* a peer is in a mesh, to help ensure that other peers will send and receive
|
||||||
|
|
|
@ -8,9 +8,11 @@ import {
|
||||||
Nwaku,
|
Nwaku,
|
||||||
} from "../test_utils/";
|
} from "../test_utils/";
|
||||||
|
|
||||||
|
import { createWaku } from "./create_waku";
|
||||||
import { generateSymmetricKey } from "./crypto";
|
import { generateSymmetricKey } from "./crypto";
|
||||||
|
import { PeerDiscoveryStaticPeers } from "./peer_discovery_static_list";
|
||||||
import { waitForRemotePeer } from "./wait_for_remote_peer";
|
import { waitForRemotePeer } from "./wait_for_remote_peer";
|
||||||
import { createWaku, Protocols, Waku } from "./waku";
|
import { Protocols, Waku } from "./waku";
|
||||||
import { WakuMessage } from "./waku_message";
|
import { WakuMessage } from "./waku_message";
|
||||||
|
|
||||||
const TestContentTopic = "/test/1/waku/utf8";
|
const TestContentTopic = "/test/1/waku/utf8";
|
||||||
|
@ -60,7 +62,9 @@ describe("Waku Dial [node only]", function () {
|
||||||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||||
waku = await createWaku({
|
waku = await createWaku({
|
||||||
staticNoiseKey: NOISE_KEY_1,
|
staticNoiseKey: NOISE_KEY_1,
|
||||||
bootstrap: { peers: [multiAddrWithId] },
|
libp2p: {
|
||||||
|
peerDiscovery: [new PeerDiscoveryStaticPeers([multiAddrWithId])],
|
||||||
|
},
|
||||||
});
|
});
|
||||||
await waku.start();
|
await waku.start();
|
||||||
|
|
||||||
|
@ -76,7 +80,7 @@ describe("Waku Dial [node only]", function () {
|
||||||
expect(connectedPeerID.toString()).to.eq(multiAddrWithId.getPeerId());
|
expect(connectedPeerID.toString()).to.eq(multiAddrWithId.getPeerId());
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Passing a function", async function () {
|
it("Using a function", async function () {
|
||||||
this.timeout(10_000);
|
this.timeout(10_000);
|
||||||
|
|
||||||
nwaku = new Nwaku(makeLogFileName(this));
|
nwaku = new Nwaku(makeLogFileName(this));
|
||||||
|
@ -84,10 +88,10 @@ describe("Waku Dial [node only]", function () {
|
||||||
|
|
||||||
waku = await createWaku({
|
waku = await createWaku({
|
||||||
staticNoiseKey: NOISE_KEY_1,
|
staticNoiseKey: NOISE_KEY_1,
|
||||||
bootstrap: {
|
libp2p: {
|
||||||
getPeers: async () => {
|
peerDiscovery: [
|
||||||
return [await nwaku.getMultiaddrWithId()];
|
new PeerDiscoveryStaticPeers([await nwaku.getMultiaddrWithId()]),
|
||||||
},
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await waku.start();
|
await waku.start();
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import type { PeerId } from "@libp2p/interface-peer-id";
|
import type { PeerId } from "@libp2p/interface-peer-id";
|
||||||
import { expect } from "chai";
|
import { expect } from "chai";
|
||||||
|
|
||||||
import { createWaku, Waku } from "./waku";
|
import { createWaku } from "./create_waku";
|
||||||
|
import { Waku } from "./waku";
|
||||||
|
|
||||||
describe("Waku Dial", function () {
|
describe("Waku Dial", function () {
|
||||||
describe("Bootstrap [live data]", function () {
|
describe("Bootstrap [live data]", function () {
|
||||||
|
@ -23,7 +24,7 @@ describe("Waku Dial", function () {
|
||||||
this.timeout(20_000);
|
this.timeout(20_000);
|
||||||
|
|
||||||
waku = await createWaku({
|
waku = await createWaku({
|
||||||
bootstrap: { default: true },
|
defaultBootstrap: true,
|
||||||
});
|
});
|
||||||
await waku.start();
|
await waku.start();
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import { Noise } from "@chainsafe/libp2p-noise";
|
|
||||||
import type { Stream } from "@libp2p/interface-connection";
|
import type { Stream } from "@libp2p/interface-connection";
|
||||||
import type { PeerId } from "@libp2p/interface-peer-id";
|
import type { PeerId } from "@libp2p/interface-peer-id";
|
||||||
import { Mplex } from "@libp2p/mplex";
|
|
||||||
import { peerIdFromString } from "@libp2p/peer-id";
|
import { peerIdFromString } from "@libp2p/peer-id";
|
||||||
import { WebSockets } from "@libp2p/websockets";
|
import type { Multiaddr } from "@multiformats/multiaddr";
|
||||||
import { all as filterAll } from "@libp2p/websockets/filters";
|
import { multiaddr } from "@multiformats/multiaddr";
|
||||||
import { Multiaddr, multiaddr } from "@multiformats/multiaddr";
|
|
||||||
import debug from "debug";
|
import debug from "debug";
|
||||||
import { createLibp2p, Libp2p, Libp2pOptions } from "libp2p";
|
import type { Libp2p } from "libp2p";
|
||||||
|
|
||||||
import { Bootstrap, BootstrapOptions } from "./discovery";
|
|
||||||
import { FilterCodec, WakuFilter } from "./waku_filter";
|
import { FilterCodec, WakuFilter } from "./waku_filter";
|
||||||
import { LightPushCodec, WakuLightPush } from "./waku_light_push";
|
import { LightPushCodec, WakuLightPush } from "./waku_light_push";
|
||||||
import { DecryptionMethod, WakuMessage } from "./waku_message";
|
import { DecryptionMethod, WakuMessage } from "./waku_message";
|
||||||
|
@ -29,21 +25,7 @@ export enum Protocols {
|
||||||
Filter = "filter",
|
Filter = "filter",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CreateOptions {
|
export interface WakuOptions {
|
||||||
/**
|
|
||||||
* The PubSub Topic to use. Defaults to {@link DefaultPubSubTopic}.
|
|
||||||
*
|
|
||||||
* One and only one pubsub topic is used by Waku. This is used by:
|
|
||||||
* - WakuRelay to receive, route and send messages,
|
|
||||||
* - WakuLightPush to send messages,
|
|
||||||
* - WakuStore to retrieve messages.
|
|
||||||
*
|
|
||||||
* The usage of the default pubsub topic is recommended.
|
|
||||||
* See [Waku v2 Topic Usage Recommendations](https://rfc.vac.dev/spec/23/) for details.
|
|
||||||
*
|
|
||||||
* @default {@link DefaultPubSubTopic}
|
|
||||||
*/
|
|
||||||
pubSubTopic?: string;
|
|
||||||
/**
|
/**
|
||||||
* Set keep alive frequency in seconds: Waku will send a `/ipfs/ping/1.0.0`
|
* Set keep alive frequency in seconds: Waku will send a `/ipfs/ping/1.0.0`
|
||||||
* request to each peer after the set number of seconds. Set to 0 to disable.
|
* request to each peer after the set number of seconds. Set to 0 to disable.
|
||||||
|
@ -58,58 +40,9 @@ export interface CreateOptions {
|
||||||
* @default {@link DefaultRelayKeepAliveValueSecs}
|
* @default {@link DefaultRelayKeepAliveValueSecs}
|
||||||
*/
|
*/
|
||||||
relayKeepAlive?: number;
|
relayKeepAlive?: number;
|
||||||
/**
|
|
||||||
* You can pass options to the `Libp2p` instance used by {@link Waku} using the {@link CreateOptions.libp2p} property.
|
|
||||||
* This property is the same type than the one passed to [`Libp2p.create`](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#create)
|
|
||||||
* apart that we made the `modules` property optional and partial,
|
|
||||||
* allowing its omission and letting Waku set good defaults.
|
|
||||||
* Notes that some values are overridden by {@link Waku} to ensure it implements the Waku protocol.
|
|
||||||
*/
|
|
||||||
libp2p?: Partial<Libp2pOptions>;
|
|
||||||
/**
|
|
||||||
* Byte array used as key for the noise protocol used for connection encryption
|
|
||||||
* by [`Libp2p.create`](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md#create)
|
|
||||||
* This is only used for test purposes to not run out of entropy during CI runs.
|
|
||||||
*/
|
|
||||||
staticNoiseKey?: Uint8Array;
|
|
||||||
/**
|
|
||||||
* Use libp2p-bootstrap to discover and connect to new nodes.
|
|
||||||
*
|
|
||||||
* See [[BootstrapOptions]] for available parameters.
|
|
||||||
*
|
|
||||||
* Note: It overrides any other peerDiscovery modules that may have been set via
|
|
||||||
* {@link CreateOptions.libp2p}.
|
|
||||||
*/
|
|
||||||
bootstrap?: BootstrapOptions;
|
|
||||||
decryptionKeys?: Array<Uint8Array | string>;
|
decryptionKeys?: Array<Uint8Array | string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createWaku(options?: CreateOptions): Promise<Waku> {
|
|
||||||
const peerDiscovery = [];
|
|
||||||
if (options?.bootstrap) {
|
|
||||||
peerDiscovery.push(new Bootstrap(options?.bootstrap));
|
|
||||||
}
|
|
||||||
|
|
||||||
const libp2pOpts = Object.assign(
|
|
||||||
{
|
|
||||||
transports: [new WebSockets({ filter: filterAll })],
|
|
||||||
streamMuxers: [new Mplex()],
|
|
||||||
pubsub: new WakuRelay(options),
|
|
||||||
connectionEncryption: [new Noise()],
|
|
||||||
peerDiscovery: peerDiscovery,
|
|
||||||
},
|
|
||||||
options?.libp2p ?? {}
|
|
||||||
);
|
|
||||||
|
|
||||||
const libp2p = await createLibp2p(libp2pOpts);
|
|
||||||
|
|
||||||
const wakuStore = new WakuStore(libp2p, options);
|
|
||||||
const wakuLightPush = new WakuLightPush(libp2p, options);
|
|
||||||
const wakuFilter = new WakuFilter(libp2p, options);
|
|
||||||
|
|
||||||
return new Waku(options ?? {}, libp2p, wakuStore, wakuLightPush, wakuFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Waku {
|
export class Waku {
|
||||||
public libp2p: Libp2p;
|
public libp2p: Libp2p;
|
||||||
public relay: WakuRelay;
|
public relay: WakuRelay;
|
||||||
|
@ -125,7 +58,7 @@ export class Waku {
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
options: CreateOptions,
|
options: WakuOptions,
|
||||||
libp2p: Libp2p,
|
libp2p: Libp2p,
|
||||||
store: WakuStore,
|
store: WakuStore,
|
||||||
lightPush: WakuLightPush,
|
lightPush: WakuLightPush,
|
||||||
|
|
|
@ -3,8 +3,9 @@ import debug from "debug";
|
||||||
|
|
||||||
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
||||||
import { delay } from "../../test_utils/delay";
|
import { delay } from "../../test_utils/delay";
|
||||||
|
import { createWaku } from "../create_waku";
|
||||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||||
import { createWaku, Protocols, Waku } from "../waku";
|
import { Protocols, Waku } from "../waku";
|
||||||
import { WakuMessage } from "../waku_message";
|
import { WakuMessage } from "../waku_message";
|
||||||
|
|
||||||
const log = debug("waku:test");
|
const log = debug("waku:test");
|
||||||
|
|
|
@ -3,8 +3,9 @@ import debug from "debug";
|
||||||
|
|
||||||
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
||||||
import { delay } from "../../test_utils/delay";
|
import { delay } from "../../test_utils/delay";
|
||||||
|
import { createWaku } from "../create_waku";
|
||||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||||
import { createWaku, Protocols, Waku } from "../waku";
|
import { Protocols, Waku } from "../waku";
|
||||||
import { WakuMessage } from "../waku_message";
|
import { WakuMessage } from "../waku_message";
|
||||||
|
|
||||||
const dbg = debug("waku:test:lightpush");
|
const dbg = debug("waku:test:lightpush");
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
WakuRelayMessage,
|
WakuRelayMessage,
|
||||||
} from "../../test_utils";
|
} from "../../test_utils";
|
||||||
import { delay } from "../../test_utils/delay";
|
import { delay } from "../../test_utils/delay";
|
||||||
|
import { createWaku } from "../create_waku";
|
||||||
import {
|
import {
|
||||||
generatePrivateKey,
|
generatePrivateKey,
|
||||||
generateSymmetricKey,
|
generateSymmetricKey,
|
||||||
|
@ -15,7 +16,7 @@ import {
|
||||||
} from "../crypto";
|
} from "../crypto";
|
||||||
import { bytesToHex, bytesToUtf8, hexToBytes, utf8ToBytes } from "../utils";
|
import { bytesToHex, bytesToUtf8, hexToBytes, utf8ToBytes } from "../utils";
|
||||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||||
import { createWaku, Protocols, Waku } from "../waku";
|
import { Protocols, Waku } from "../waku";
|
||||||
|
|
||||||
import { DecryptionMethod, WakuMessage } from "./index";
|
import { DecryptionMethod, WakuMessage } from "./index";
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,14 @@ import {
|
||||||
} from "../../test_utils";
|
} from "../../test_utils";
|
||||||
import { delay } from "../../test_utils/delay";
|
import { delay } from "../../test_utils/delay";
|
||||||
import { DefaultPubSubTopic } from "../constants";
|
import { DefaultPubSubTopic } from "../constants";
|
||||||
|
import { createWaku } from "../create_waku";
|
||||||
import {
|
import {
|
||||||
generatePrivateKey,
|
generatePrivateKey,
|
||||||
generateSymmetricKey,
|
generateSymmetricKey,
|
||||||
getPublicKey,
|
getPublicKey,
|
||||||
} from "../crypto";
|
} from "../crypto";
|
||||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||||
import { createWaku, Protocols, Waku } from "../waku";
|
import { Protocols, Waku } from "../waku";
|
||||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||||
|
|
||||||
const log = debug("waku:test");
|
const log = debug("waku:test");
|
||||||
|
|
|
@ -12,13 +12,30 @@ import debug from "debug";
|
||||||
|
|
||||||
import { DefaultPubSubTopic } from "../constants";
|
import { DefaultPubSubTopic } from "../constants";
|
||||||
import { hexToBytes } from "../utils";
|
import { hexToBytes } from "../utils";
|
||||||
import { CreateOptions } from "../waku";
|
|
||||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||||
|
|
||||||
import * as constants from "./constants";
|
import * as constants from "./constants";
|
||||||
|
|
||||||
const dbg = debug("waku:relay");
|
const dbg = debug("waku:relay");
|
||||||
|
|
||||||
|
export interface CreateOptions {
|
||||||
|
/**
|
||||||
|
* The PubSub Topic to use. Defaults to {@link DefaultPubSubTopic}.
|
||||||
|
*
|
||||||
|
* One and only one pubsub topic is used by Waku. This is used by:
|
||||||
|
* - WakuRelay to receive, route and send messages,
|
||||||
|
* - WakuLightPush to send messages,
|
||||||
|
* - WakuStore to retrieve messages.
|
||||||
|
*
|
||||||
|
* The usage of the default pubsub topic is recommended.
|
||||||
|
* See [Waku v2 Topic Usage Recommendations](https://rfc.vac.dev/spec/23/) for details.
|
||||||
|
*
|
||||||
|
* @default {@link DefaultPubSubTopic}
|
||||||
|
*/
|
||||||
|
pubSubTopic?: string;
|
||||||
|
decryptionKeys?: Array<Uint8Array | string>;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the [Waku v2 Relay protocol]{@link https://rfc.vac.dev/spec/11/}.
|
* Implements the [Waku v2 Relay protocol]{@link https://rfc.vac.dev/spec/11/}.
|
||||||
* Must be passed as a `pubsub` module to a {Libp2p} instance.
|
* Must be passed as a `pubsub` module to a {Libp2p} instance.
|
||||||
|
|
|
@ -7,13 +7,14 @@ import {
|
||||||
NOISE_KEY_2,
|
NOISE_KEY_2,
|
||||||
Nwaku,
|
Nwaku,
|
||||||
} from "../../test_utils";
|
} from "../../test_utils";
|
||||||
|
import { createWaku } from "../create_waku";
|
||||||
import {
|
import {
|
||||||
generatePrivateKey,
|
generatePrivateKey,
|
||||||
generateSymmetricKey,
|
generateSymmetricKey,
|
||||||
getPublicKey,
|
getPublicKey,
|
||||||
} from "../crypto";
|
} from "../crypto";
|
||||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||||
import { createWaku, Protocols, Waku } from "../waku";
|
import { Protocols, Waku } from "../waku";
|
||||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||||
|
|
||||||
import { PageDirection } from "./history_rpc";
|
import { PageDirection } from "./history_rpc";
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||||
"resolveJsonModule": true /* Include modules imported with .json extension. */,
|
"resolveJsonModule": true /* Include modules imported with .json extension. */,
|
||||||
|
"tsBuildInfoFile": "dist/.tsbuildinfo",
|
||||||
"strict": true /* Enable all strict type-checking options. */,
|
"strict": true /* Enable all strict type-checking options. */,
|
||||||
|
|
||||||
/* Strict Type-Checking Options */
|
/* Strict Type-Checking Options */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"entryPoints": ["./src/index.ts"],
|
"entryPoints": ["./src/index.ts", "./src/lib/create_waku.ts"],
|
||||||
"out": "build/docs",
|
"out": "build/docs",
|
||||||
"exclude": "**/*.spec.ts",
|
"exclude": "**/*.spec.ts",
|
||||||
"excludeInternal": true,
|
"excludeInternal": true,
|
||||||
|
|
Loading…
Reference in New Issue