diff --git a/CHANGELOG.md b/CHANGELOG.md index 60700660f5..e844c4308c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Breaking**: Auto select peer if none provided for store and light push protocols. - Upgrade to `libp2p@0.31.7` and `libp2p-gossipsub@0.10.0` to avoid `TextEncoder` errors in ReactJS tests. +### Fixed +- Disable `keepAlive` if set to `0`. + ## [0.7.0] - 2021-06-15 ### Changed diff --git a/examples/eth-dm/package-lock.json b/examples/eth-dm/package-lock.json index 18ca7dca48..7e42b0bdf3 100644 --- a/examples/eth-dm/package-lock.json +++ b/examples/eth-dm/package-lock.json @@ -19,6 +19,7 @@ "ethers": "^5.2.0", "fontsource-roboto": "^4.0.0", "js-waku": "../../build/main", + "protobufjs": "^6.11.2", "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "4.0.3", @@ -3705,6 +3706,60 @@ "node": ">= 8" } }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, "node_modules/@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -4204,6 +4259,11 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" }, + "node_modules/@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, "node_modules/@types/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", @@ -14838,6 +14898,11 @@ "url": "https://tidelift.com/funding/github/npm/loglevel" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -17973,6 +18038,31 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -26672,6 +26762,60 @@ } } }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" + }, "@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -27034,6 +27178,11 @@ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" }, + "@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, "@types/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", @@ -35215,6 +35364,11 @@ "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==" }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -37707,6 +37861,26 @@ } } }, + "protobufjs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", + "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", diff --git a/examples/eth-dm/package.json b/examples/eth-dm/package.json index 1c7cb88c86..e28a570b3f 100644 --- a/examples/eth-dm/package.json +++ b/examples/eth-dm/package.json @@ -16,6 +16,7 @@ "ethers": "^5.2.0", "fontsource-roboto": "^4.0.0", "js-waku": "../../build/main", + "protobufjs": "^6.11.2", "react": "^17.0.2", "react-dom": "^17.0.2", "react-scripts": "4.0.3", diff --git a/examples/eth-dm/src/App.tsx b/examples/eth-dm/src/App.tsx index b375f0cfbc..12590f370e 100644 --- a/examples/eth-dm/src/App.tsx +++ b/examples/eth-dm/src/App.tsx @@ -83,6 +83,11 @@ function App() { .then((address) => setAddress(address)); }); + let peers; + if (waku) { + peers = waku.libp2p.connectionManager.connections.size; + } + return (
@@ -99,6 +104,7 @@ function App() { style={waku ? { color: green[500] } : {}} /> + {peers} diff --git a/examples/eth-dm/src/BroadcastPublicKey.tsx b/examples/eth-dm/src/BroadcastPublicKey.tsx index f73e4cf9a4..8c4484276b 100644 --- a/examples/eth-dm/src/BroadcastPublicKey.tsx +++ b/examples/eth-dm/src/BroadcastPublicKey.tsx @@ -1,7 +1,7 @@ import { Button } from '@material-ui/core'; import React, { useState } from 'react'; import { createPublicKeyMessage, KeyPair } from './crypto'; -import { encode, PublicKeyMessage } from './messaging/wire'; +import { PublicKeyMessage } from './messaging/wire'; import { WakuMessage, Waku } from 'js-waku'; import { Signer } from '@ethersproject/abstract-signer'; import { PublicKeyContentTopic } from './InitWaku'; @@ -56,7 +56,9 @@ export default function BroadcastPublicKey({ ); } -function encodePublicKeyWakuMessage(ethDmMsg: PublicKeyMessage): WakuMessage { - const payload = encode(ethDmMsg); +function encodePublicKeyWakuMessage( + publicKeyMessage: PublicKeyMessage +): WakuMessage { + const payload = publicKeyMessage.encode(); return WakuMessage.fromBytes(payload, PublicKeyContentTopic); } diff --git a/examples/eth-dm/src/InitWaku.tsx b/examples/eth-dm/src/InitWaku.tsx index ad1a56b649..da105ff848 100644 --- a/examples/eth-dm/src/InitWaku.tsx +++ b/examples/eth-dm/src/InitWaku.tsx @@ -1,10 +1,15 @@ import { Dispatch, SetStateAction, useEffect } from 'react'; import { Environment, getStatusFleetNodes, Waku, WakuMessage } from 'js-waku'; -import { decode, DirectMessage, PublicKeyMessage } from './messaging/wire'; +import { + bytesToHexStr, + decode, + DirectMessage, + PublicKeyMessage, +} from './messaging/wire'; import { decryptMessage, KeyPair, validatePublicKeyMessage } from './crypto'; import { Message } from './messaging/Messages'; -export const PublicKeyContentTopic = '/eth-dm/1/public-key/json'; +export const PublicKeyContentTopic = '/eth-dm/1/public-key/proto'; export const DirectMessageContentTopic = '/eth-dm/1/direct-message/json'; interface Props { @@ -114,16 +119,22 @@ function handlePublicKeyMessage( setter: Dispatch>>, msg: WakuMessage ) { + console.log('Public Key Message received:', msg); if (!msg.payload) return; - const publicKeyMsg: PublicKeyMessage = decode(msg.payload); - if (publicKeyMsg.ethDmPublicKey === myPublicKey) return; - const res = validatePublicKeyMessage(publicKeyMsg); - console.log(`Public Key Message Received, valid: ${res}`, publicKeyMsg); + const publicKeyMsg = PublicKeyMessage.decode(msg.payload); + if (!publicKeyMsg) return; + const ethDmPublicKey = bytesToHexStr(publicKeyMsg.ethDmPublicKey); + if (ethDmPublicKey === myPublicKey) return; - setter((prevPks: Map) => { - prevPks.set(publicKeyMsg.ethAddress, publicKeyMsg.ethDmPublicKey); - return new Map(prevPks); - }); + const res = validatePublicKeyMessage(publicKeyMsg); + console.log('Is Public Key Message valid?', res); + + if (res) { + setter((prevPks: Map) => { + prevPks.set(bytesToHexStr(publicKeyMsg.ethAddress), ethDmPublicKey); + return new Map(prevPks); + }); + } } async function handleDirectMessage( @@ -132,10 +143,11 @@ async function handleDirectMessage( address: string, wakuMsg: WakuMessage ) { - console.log('Waku Message received:', wakuMsg); + console.log('Direct Message received:', wakuMsg); if (!wakuMsg.payload) return; const directMessage: DirectMessage = decode(wakuMsg.payload); - if (directMessage.toAddress !== address) return; + // Do not return our own messages + if (directMessage.toAddress === address) return; const text = await decryptMessage(privateKey, directMessage); diff --git a/examples/eth-dm/src/crypto.ts b/examples/eth-dm/src/crypto.ts index b357efcfef..0b72b88f69 100644 --- a/examples/eth-dm/src/crypto.ts +++ b/examples/eth-dm/src/crypto.ts @@ -3,7 +3,11 @@ import '@ethersproject/shims'; import * as EthCrypto from 'eth-crypto'; import { ethers } from 'ethers'; import { Signer } from '@ethersproject/abstract-signer'; -import { DirectMessage, PublicKeyMessage } from './messaging/wire'; +import { + bytesToHexStr, + DirectMessage, + PublicKeyMessage, +} from './messaging/wire'; export interface KeyPair { privateKey: string; @@ -29,23 +33,46 @@ export async function createPublicKeyMessage( ethDmPublicKey: string ): Promise { const ethAddress = await web3Signer.getAddress(); - const sig = await web3Signer.signMessage( - formatPublicKeyForSignature(ethDmPublicKey) + const bytesEthDmPublicKey = Buffer.from( + ethDmPublicKey.replace(/0x/, ''), + 'hex' ); - return { ethDmPublicKey, ethAddress, sig }; + const signature = await web3Signer.signMessage( + formatPublicKeyForSignature(bytesEthDmPublicKey) + ); + + const bytesEthAddress = Buffer.from(ethAddress.replace(/0x/, ''), 'hex'); + const bytesSignature = Buffer.from(signature.replace(/0x/, ''), 'hex'); + + return new PublicKeyMessage({ + ethDmPublicKey: bytesEthDmPublicKey, + ethAddress: bytesEthAddress, + signature: bytesSignature, + }); } /** * Validate that the EthDm Public Key was signed by the holder of the given Ethereum address. */ export function validatePublicKeyMessage(msg: PublicKeyMessage): boolean { + const formattedMsg = formatPublicKeyForSignature(msg.ethDmPublicKey); try { - const sigAddress = ethers.utils.verifyMessage( - formatPublicKeyForSignature(msg.ethDmPublicKey), - msg.sig + const sigAddress = ethers.utils.verifyMessage(formattedMsg, msg.signature); + const sigAddressBytes = Buffer.from(sigAddress.replace(/0x/, ''), 'hex'); + // Compare the actual byte arrays instead of strings that may differ in casing or prefixing. + const cmp = sigAddressBytes.compare(new Buffer(msg.ethAddress)); + console.log( + `Buffer comparison result: ${cmp} for (signature address, message address)`, + sigAddressBytes, + msg.ethAddress ); - return sigAddress === msg.ethAddress; + return cmp === 0; } catch (e) { + console.log( + 'Failed to verify signature for Public Key Message', + formattedMsg, + msg + ); return false; } } @@ -57,9 +84,9 @@ export function validatePublicKeyMessage(msg: PublicKeyMessage): boolean { * The usage of the object helps ensure the signature is only used in an Eth-DM * context. */ -function formatPublicKeyForSignature(ethDmPublicKey: string): string { +function formatPublicKeyForSignature(ethDmPublicKey: Uint8Array): string { return JSON.stringify({ - ethDmPublicKey, + ethDmPublicKey: bytesToHexStr(ethDmPublicKey), }); } diff --git a/examples/eth-dm/src/messaging/wire.ts b/examples/eth-dm/src/messaging/wire.ts index e76cbc8a89..d595ea978c 100644 --- a/examples/eth-dm/src/messaging/wire.ts +++ b/examples/eth-dm/src/messaging/wire.ts @@ -1,12 +1,64 @@ import * as EthCrypto from 'eth-crypto'; +import * as protobuf from 'protobufjs/light'; + +export interface PublicKeyMessagePayload { + ethDmPublicKey: Uint8Array; + ethAddress: Uint8Array; + signature: Uint8Array; +} + +const Root = protobuf.Root, + Type = protobuf.Type, + Field = protobuf.Field; /** * Message used to communicate the Eth-Dm public key linked to a given Ethereum account */ -export interface PublicKeyMessage { - ethDmPublicKey: string; - ethAddress: string; - sig: string; +export class PublicKeyMessage { + private static Type = new Type('PublicKeyMessage') + .add(new Field('ethDmPublicKey', 1, 'bytes')) + .add(new Field('ethAddress', 2, 'bytes')) + .add(new Field('signature', 3, 'bytes')); + private static Root = new Root() + .define('messages') + .add(PublicKeyMessage.Type); + + constructor(public payload: PublicKeyMessagePayload) {} + + public encode(): Uint8Array { + const message = PublicKeyMessage.Type.create(this.payload); + return PublicKeyMessage.Type.encode(message).finish(); + } + + public static decode( + bytes: Uint8Array | Buffer + ): PublicKeyMessage | undefined { + const payload = PublicKeyMessage.Type.decode( + bytes + ) as unknown as PublicKeyMessagePayload; + if (!payload.signature || !payload.ethDmPublicKey || !payload.ethAddress) { + console.log('Field missing on decoded Public Key Message', payload); + return; + } + return new PublicKeyMessage(payload); + } + + get ethDmPublicKey(): Uint8Array { + return this.payload.ethDmPublicKey; + } + + get ethAddress(): Uint8Array { + return this.payload.ethAddress; + } + + get signature(): Uint8Array { + return this.payload.signature; + } +} + +export function bytesToHexStr(bytes: Uint8Array): string { + const buf = new Buffer(bytes); + return buf.toString('hex'); } /** diff --git a/src/lib/waku.ts b/src/lib/waku.ts index 0d3b663e3e..093192217f 100644 --- a/src/lib/waku.ts +++ b/src/lib/waku.ts @@ -76,15 +76,20 @@ export class Waku { this.lightPush = lightPush; this.keepAliveTimers = {}; - const keepAlive = options.keepAlive ? options.keepAlive : 10; + const keepAlive = options.keepAlive !== undefined ? options.keepAlive : 10; - libp2p.connectionManager.on('peer:connect', (connection: Connection) => { - this.startKeepAlive(connection.remotePeer, keepAlive); - }); + if (keepAlive !== 0) { + libp2p.connectionManager.on('peer:connect', (connection: Connection) => { + this.startKeepAlive(connection.remotePeer, keepAlive); + }); - libp2p.connectionManager.on('peer:disconnect', (connection: Connection) => { - this.stopKeepAlive(connection.remotePeer); - }); + libp2p.connectionManager.on( + 'peer:disconnect', + (connection: Connection) => { + this.stopKeepAlive(connection.remotePeer); + } + ); + } } /**