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
|
||||
/tsconfig.tsbuildinfo
|
||||
/tsconfig.dev.tsbuildinfo
|
||||
/bundle/
|
||||
|
|
|
@ -1,37 +1,40 @@
|
|||
module.exports = [
|
||||
{
|
||||
name: "Waku core",
|
||||
path: "dist/bundle.min.js",
|
||||
path: "bundle/index.js",
|
||||
import: "{ Waku }",
|
||||
},
|
||||
{
|
||||
name: "Waku default setup",
|
||||
path: "dist/bundle.min.js",
|
||||
import: "{ createWaku, waitForRemotePeer }",
|
||||
path: ["bundle/index.js", "bundle/lib/create_waku.js"],
|
||||
import: {
|
||||
"./bundle/lib/create_waku.js": "{ createWaku }",
|
||||
"./bundle/index.js": "{ waitForRemotePeer }",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Asymmetric, symmetric encryption and signature",
|
||||
path: "dist/bundle.min.js",
|
||||
import: "{ waku_message }",
|
||||
path: "bundle/index.js",
|
||||
import: "{ WakuMessage }",
|
||||
},
|
||||
{
|
||||
name: "DNS discovery",
|
||||
path: "dist/bundle.min.js",
|
||||
import: "{ discovery }",
|
||||
path: "bundle/lib/peer_discovery_dns.js",
|
||||
import: "{ PeerDiscoveryDns }",
|
||||
},
|
||||
{
|
||||
name: "Privacy preserving protocols",
|
||||
path: "dist/bundle.min.js",
|
||||
path: "bundle/index.js",
|
||||
import: "{ WakuRelay }",
|
||||
},
|
||||
{
|
||||
name: "Light protocols",
|
||||
path: "dist/bundle.min.js",
|
||||
path: "bundle/index.js",
|
||||
import: "{ WakuLightPush, WakuFilter }",
|
||||
},
|
||||
{
|
||||
name: "History retrieval protocols",
|
||||
path: "dist/bundle.min.js",
|
||||
path: "bundle/index.js",
|
||||
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.
|
||||
- Remove need to polyfill `buffer`.
|
||||
- **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.
|
||||
- `buffer` is not needed in the browser.
|
||||
|
||||
### Removed
|
||||
|
||||
- `terser` minification and `gzip` compressions have been removed.
|
||||
|
||||
## [0.24.0] - 2022-05-27
|
||||
|
||||
### Added
|
||||
|
|
|
@ -27,10 +27,12 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
createWaku,
|
||||
waitForRemotePeer,
|
||||
WakuMessage
|
||||
} from '../../dist/bundle.js';
|
||||
} from '../../bundle/index.js';
|
||||
import {
|
||||
createWaku,
|
||||
} from '../../bundle/lib/create_waku.js';
|
||||
|
||||
const statusDiv = document.getElementById('status');
|
||||
const messagesDiv = document.getElementById('messages');
|
||||
|
@ -56,7 +58,7 @@
|
|||
// We are currently working on migrating this method to DNS Discovery.
|
||||
//
|
||||
// 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();
|
||||
|
||||
// Had a hook to process all incoming messages on a specified content topic.
|
||||
|
|
|
@ -14,10 +14,12 @@
|
|||
|
||||
<script type='module'>
|
||||
import {
|
||||
createWaku,
|
||||
waitForRemotePeer,
|
||||
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
|
||||
|
@ -30,7 +32,7 @@
|
|||
|
||||
try {
|
||||
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>';
|
||||
await node.start();
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
"rollup": "^2.75.0",
|
||||
"size-limit": "^8.0.0",
|
||||
"tail": "^2.2.0",
|
||||
"terser": "^5.13.1",
|
||||
"ts-loader": "^9.2.6",
|
||||
"ts-node": "^10.4.0",
|
||||
"typedoc": "^0.22.10",
|
||||
|
@ -798,6 +797,64 @@
|
|||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||
"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": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/base64-codec/-/base64-codec-1.0.0.tgz",
|
||||
|
@ -7571,12 +7628,6 @@
|
|||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"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": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
||||
|
@ -10568,14 +10619,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.13.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz",
|
||||
"integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==",
|
||||
"version": "5.14.2",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
|
||||
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.2",
|
||||
"acorn": "^8.5.0",
|
||||
"commander": "^2.20.0",
|
||||
"source-map": "~0.8.0-beta.0",
|
||||
"source-map-support": "~0.5.20"
|
||||
},
|
||||
"bin": {
|
||||
|
@ -10664,44 +10715,6 @@
|
|||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"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": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
|
@ -12381,6 +12394,55 @@
|
|||
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
|
||||
"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": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@leichtgewicht/base64-codec/-/base64-codec-1.0.0.tgz",
|
||||
|
@ -17593,12 +17655,6 @@
|
|||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||
"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": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
|
||||
|
@ -19794,14 +19850,14 @@
|
|||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "5.13.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.13.1.tgz",
|
||||
"integrity": "sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==",
|
||||
"version": "5.14.2",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz",
|
||||
"integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/source-map": "^0.3.2",
|
||||
"acorn": "^8.5.0",
|
||||
"commander": "^2.20.0",
|
||||
"source-map": "~0.8.0-beta.0",
|
||||
"source-map-support": "~0.5.20"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -19810,41 +19866,6 @@
|
|||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"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",
|
||||
"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",
|
||||
|
@ -25,8 +33,7 @@
|
|||
"prepare": "husky install",
|
||||
"build": "run-s build:**",
|
||||
"build:esm": "tsc && node build-scripts/fix-imports.js",
|
||||
"build:bundle": "rollup --config rollup.config.js -- dist/index.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",
|
||||
"build:bundle": "rollup --config rollup.config.js",
|
||||
"size": "npm run build && size-limit",
|
||||
"fix": "run-s fix:*",
|
||||
"fix:prettier": "prettier \"src/**/*.ts\" \"./*.json\" \"*.*js\" \".github/**/*.yml\" --write",
|
||||
|
@ -137,7 +144,6 @@
|
|||
"rollup": "^2.75.0",
|
||||
"size-limit": "^8.0.0",
|
||||
"tail": "^2.2.0",
|
||||
"terser": "^5.13.1",
|
||||
"ts-loader": "^9.2.6",
|
||||
"ts-node": "^10.4.0",
|
||||
"typedoc": "^0.22.10",
|
||||
|
@ -146,6 +152,7 @@
|
|||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"bundle",
|
||||
"src/*.ts",
|
||||
"src/lib/**/*.ts",
|
||||
"src/proto/**/*.ts",
|
||||
|
|
|
@ -3,10 +3,14 @@ import commonjs from "@rollup/plugin-commonjs";
|
|||
import json from "@rollup/plugin-json";
|
||||
|
||||
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: {
|
||||
file: "dist/bundle.js",
|
||||
dir: "bundle",
|
||||
format: "esm",
|
||||
name: "waku",
|
||||
},
|
||||
plugins: [
|
||||
commonjs(),
|
||||
|
|
|
@ -6,9 +6,6 @@ export {
|
|||
getPublicKey,
|
||||
} from "./lib/crypto";
|
||||
|
||||
export { getPredefinedBootstrapNodes } from "./lib/discovery";
|
||||
export * as discovery from "./lib/discovery";
|
||||
|
||||
export * as enr from "./lib/enr";
|
||||
|
||||
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 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 { 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 { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
||||
import { createWaku } from "../create_waku";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { createWaku, Protocols, Waku } from "../waku";
|
||||
import { Protocols, Waku } from "../waku";
|
||||
|
||||
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 { ENRTree } from "./enrtree";
|
||||
import fetchNodesUntilCapabilitiesFulfilled from "./fetch_nodes";
|
||||
import {
|
||||
fetchNodesUntilCapabilitiesFulfilled,
|
||||
yieldNodesUntilCapabilitiesFulfilled,
|
||||
} from "./fetch_nodes";
|
||||
|
||||
const dbg = debug("waku:discovery:dns");
|
||||
|
||||
|
@ -70,6 +73,30 @@ export class DnsNodeDiscovery {
|
|||
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
|
||||
* 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 fetchNodesUntilCapabilitiesFulfilled from "./fetch_nodes";
|
||||
import { fetchNodesUntilCapabilitiesFulfilled } from "./fetch_nodes";
|
||||
|
||||
async function createEnr(waku2: Waku2): Promise<ENR> {
|
||||
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
|
||||
* [[wantedNodeCapabilityCount]] plus [[errorTolerance]].
|
||||
*/
|
||||
export default async function fetchNodesUntilCapabilitiesFulfilled(
|
||||
export async function fetchNodesUntilCapabilitiesFulfilled(
|
||||
wantedNodeCapabilityCount: Partial<NodeCapabilityCount>,
|
||||
errorTolerance: number,
|
||||
getNode: () => Promise<ENR | null>
|
||||
|
@ -57,6 +57,56 @@ export default async function fetchNodesUntilCapabilitiesFulfilled(
|
|||
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(
|
||||
wanted: NodeCapabilityCount,
|
||||
actual: NodeCapabilityCount
|
|
@ -1,6 +1,6 @@
|
|||
import { expect } from "chai";
|
||||
|
||||
import { getPseudoRandomSubset } from "./random_subset";
|
||||
import { getPseudoRandomSubset } from "../random_subset";
|
||||
|
||||
describe("Discovery", () => {
|
||||
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 { delay } from "../test_utils/delay";
|
||||
|
||||
import { createWaku } from "./create_waku";
|
||||
import { waitForRemotePeer } from "./wait_for_remote_peer";
|
||||
import { createWaku, Protocols, Waku } from "./waku";
|
||||
import { Protocols, Waku } from "./waku";
|
||||
|
||||
describe("Wait for remote peer", function () {
|
||||
let waku: Waku;
|
||||
|
|
|
@ -22,7 +22,8 @@ interface WakuGossipSubProtocol extends GossipSub {
|
|||
|
||||
/**
|
||||
* 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
|
||||
* a peer is in a mesh, to help ensure that other peers will send and receive
|
||||
|
|
|
@ -8,9 +8,11 @@ import {
|
|||
Nwaku,
|
||||
} from "../test_utils/";
|
||||
|
||||
import { createWaku } from "./create_waku";
|
||||
import { generateSymmetricKey } from "./crypto";
|
||||
import { PeerDiscoveryStaticPeers } from "./peer_discovery_static_list";
|
||||
import { waitForRemotePeer } from "./wait_for_remote_peer";
|
||||
import { createWaku, Protocols, Waku } from "./waku";
|
||||
import { Protocols, Waku } from "./waku";
|
||||
import { WakuMessage } from "./waku_message";
|
||||
|
||||
const TestContentTopic = "/test/1/waku/utf8";
|
||||
|
@ -60,7 +62,9 @@ describe("Waku Dial [node only]", function () {
|
|||
const multiAddrWithId = await nwaku.getMultiaddrWithId();
|
||||
waku = await createWaku({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
bootstrap: { peers: [multiAddrWithId] },
|
||||
libp2p: {
|
||||
peerDiscovery: [new PeerDiscoveryStaticPeers([multiAddrWithId])],
|
||||
},
|
||||
});
|
||||
await waku.start();
|
||||
|
||||
|
@ -76,7 +80,7 @@ describe("Waku Dial [node only]", function () {
|
|||
expect(connectedPeerID.toString()).to.eq(multiAddrWithId.getPeerId());
|
||||
});
|
||||
|
||||
it("Passing a function", async function () {
|
||||
it("Using a function", async function () {
|
||||
this.timeout(10_000);
|
||||
|
||||
nwaku = new Nwaku(makeLogFileName(this));
|
||||
|
@ -84,10 +88,10 @@ describe("Waku Dial [node only]", function () {
|
|||
|
||||
waku = await createWaku({
|
||||
staticNoiseKey: NOISE_KEY_1,
|
||||
bootstrap: {
|
||||
getPeers: async () => {
|
||||
return [await nwaku.getMultiaddrWithId()];
|
||||
},
|
||||
libp2p: {
|
||||
peerDiscovery: [
|
||||
new PeerDiscoveryStaticPeers([await nwaku.getMultiaddrWithId()]),
|
||||
],
|
||||
},
|
||||
});
|
||||
await waku.start();
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import type { PeerId } from "@libp2p/interface-peer-id";
|
||||
import { expect } from "chai";
|
||||
|
||||
import { createWaku, Waku } from "./waku";
|
||||
import { createWaku } from "./create_waku";
|
||||
import { Waku } from "./waku";
|
||||
|
||||
describe("Waku Dial", function () {
|
||||
describe("Bootstrap [live data]", function () {
|
||||
|
@ -23,7 +24,7 @@ describe("Waku Dial", function () {
|
|||
this.timeout(20_000);
|
||||
|
||||
waku = await createWaku({
|
||||
bootstrap: { default: true },
|
||||
defaultBootstrap: true,
|
||||
});
|
||||
await waku.start();
|
||||
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
import { Noise } from "@chainsafe/libp2p-noise";
|
||||
import type { Stream } from "@libp2p/interface-connection";
|
||||
import type { PeerId } from "@libp2p/interface-peer-id";
|
||||
import { Mplex } from "@libp2p/mplex";
|
||||
import { peerIdFromString } from "@libp2p/peer-id";
|
||||
import { WebSockets } from "@libp2p/websockets";
|
||||
import { all as filterAll } from "@libp2p/websockets/filters";
|
||||
import { Multiaddr, multiaddr } from "@multiformats/multiaddr";
|
||||
import type { Multiaddr } from "@multiformats/multiaddr";
|
||||
import { multiaddr } from "@multiformats/multiaddr";
|
||||
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 { LightPushCodec, WakuLightPush } from "./waku_light_push";
|
||||
import { DecryptionMethod, WakuMessage } from "./waku_message";
|
||||
|
@ -29,21 +25,7 @@ export enum Protocols {
|
|||
Filter = "filter",
|
||||
}
|
||||
|
||||
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;
|
||||
export interface WakuOptions {
|
||||
/**
|
||||
* 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.
|
||||
|
@ -58,58 +40,9 @@ export interface CreateOptions {
|
|||
* @default {@link DefaultRelayKeepAliveValueSecs}
|
||||
*/
|
||||
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>;
|
||||
}
|
||||
|
||||
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 {
|
||||
public libp2p: Libp2p;
|
||||
public relay: WakuRelay;
|
||||
|
@ -125,7 +58,7 @@ export class Waku {
|
|||
};
|
||||
|
||||
constructor(
|
||||
options: CreateOptions,
|
||||
options: WakuOptions,
|
||||
libp2p: Libp2p,
|
||||
store: WakuStore,
|
||||
lightPush: WakuLightPush,
|
||||
|
|
|
@ -3,8 +3,9 @@ import debug from "debug";
|
|||
|
||||
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { createWaku } from "../create_waku";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { createWaku, Protocols, Waku } from "../waku";
|
||||
import { Protocols, Waku } from "../waku";
|
||||
import { WakuMessage } from "../waku_message";
|
||||
|
||||
const log = debug("waku:test");
|
||||
|
|
|
@ -3,8 +3,9 @@ import debug from "debug";
|
|||
|
||||
import { makeLogFileName, NOISE_KEY_1, Nwaku } from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { createWaku } from "../create_waku";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { createWaku, Protocols, Waku } from "../waku";
|
||||
import { Protocols, Waku } from "../waku";
|
||||
import { WakuMessage } from "../waku_message";
|
||||
|
||||
const dbg = debug("waku:test:lightpush");
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
WakuRelayMessage,
|
||||
} from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { createWaku } from "../create_waku";
|
||||
import {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
|
@ -15,7 +16,7 @@ import {
|
|||
} from "../crypto";
|
||||
import { bytesToHex, bytesToUtf8, hexToBytes, utf8ToBytes } from "../utils";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { createWaku, Protocols, Waku } from "../waku";
|
||||
import { Protocols, Waku } from "../waku";
|
||||
|
||||
import { DecryptionMethod, WakuMessage } from "./index";
|
||||
|
||||
|
|
|
@ -11,13 +11,14 @@ import {
|
|||
} from "../../test_utils";
|
||||
import { delay } from "../../test_utils/delay";
|
||||
import { DefaultPubSubTopic } from "../constants";
|
||||
import { createWaku } from "../create_waku";
|
||||
import {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "../crypto";
|
||||
import { waitForRemotePeer } from "../wait_for_remote_peer";
|
||||
import { createWaku, Protocols, Waku } from "../waku";
|
||||
import { Protocols, Waku } from "../waku";
|
||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||
|
||||
const log = debug("waku:test");
|
||||
|
|
|
@ -12,13 +12,30 @@ import debug from "debug";
|
|||
|
||||
import { DefaultPubSubTopic } from "../constants";
|
||||
import { hexToBytes } from "../utils";
|
||||
import { CreateOptions } from "../waku";
|
||||
import { DecryptionMethod, WakuMessage } from "../waku_message";
|
||||
|
||||
import * as constants from "./constants";
|
||||
|
||||
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/}.
|
||||
* Must be passed as a `pubsub` module to a {Libp2p} instance.
|
||||
|
|
|
@ -7,13 +7,14 @@ import {
|
|||
NOISE_KEY_2,
|
||||
Nwaku,
|
||||
} from "../../test_utils";
|
||||
import { createWaku } from "../create_waku";
|
||||
import {
|
||||
generatePrivateKey,
|
||||
generateSymmetricKey,
|
||||
getPublicKey,
|
||||
} from "../crypto";
|
||||
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 { PageDirection } from "./history_rpc";
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"sourceMap": true,
|
||||
"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. */,
|
||||
|
||||
"tsBuildInfoFile": "dist/.tsbuildinfo",
|
||||
"strict": true /* Enable all 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",
|
||||
"exclude": "**/*.spec.ts",
|
||||
"excludeInternal": true,
|
||||
|
|
Loading…
Reference in New Issue