From 0bb1b802c8fc2f32eaef10efbc88005dce6c6020 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 15 Jul 2022 16:35:52 +0000 Subject: [PATCH] feat: programmatically set agentVersion for use in identify (#1296) If no `agentVersion` is provided for the Identify protocol, the default `AGENT_VERSION` will now be set to * `js-libp2p/ UserAgent=` when running in Node.js * `js-libp2p/ UserAgent=` when running in the browser (also when running in a webworker) Fixes #686 Supersedes #1240 Co-authored-by: Kevin Westphal Co-authored-by: Kevin <56823591+6d7a@users.noreply.github.com> --- package.json | 1 + scripts/update-version.js | 14 ++++++++++++++ src/config.ts | 10 ++++++++++ src/version.ts | 1 - test/identify/service.spec.ts | 24 ++++++++++++++++++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 scripts/update-version.js diff --git a/package.json b/package.json index dbb88013..f2543453 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ "clean": "aegir clean", "lint": "aegir lint", "dep-check": "aegir dep-check", + "prepublishOnly": "node scripts/update-version.js", "build": "aegir build", "generate": "run-s generate:proto:*", "generate:proto:circuit": "protons ./src/circuit/pb/index.proto", diff --git a/scripts/update-version.js b/scripts/update-version.js new file mode 100644 index 00000000..2620790a --- /dev/null +++ b/scripts/update-version.js @@ -0,0 +1,14 @@ +import { readFile, writeFile } from 'fs/promises' + +const pkg = JSON.parse( + await readFile( + new URL('../package.json', import.meta.url) + ) +) + +await writeFile( + new URL('../src/version.ts', import.meta.url), + `export const version = '${pkg.version}' +export const name = '${pkg.name}' +` +) diff --git a/src/config.ts b/src/config.ts index c82b9d1d..6e88a674 100644 --- a/src/config.ts +++ b/src/config.ts @@ -10,6 +10,7 @@ import type { Libp2pInit } from './index.js' import { codes, messages } from './errors.js' import errCode from 'err-code' import type { RecursivePartial } from '@libp2p/interfaces' +import { isNode, isBrowser, isWebWorker, isElectronMain, isElectronRenderer, isReactNative } from 'wherearewe' const DefaultConfig: Partial = { addresses: { @@ -116,5 +117,14 @@ export function validateConfig (opts: RecursivePartial): Libp2pInit throw errCode(new Error(messages.ERR_PROTECTOR_REQUIRED), codes.ERR_PROTECTOR_REQUIRED) } + // Append user agent version to default AGENT_VERSION depending on the environment + if (resultingOptions.identify.host.agentVersion === AGENT_VERSION) { + if (isNode || isElectronMain) { + resultingOptions.identify.host.agentVersion += ` UserAgent=${globalThis.process.version}` + } else if (isBrowser || isWebWorker || isElectronRenderer || isReactNative) { + resultingOptions.identify.host.agentVersion += ` UserAgent=${globalThis.navigator.userAgent}` + } + } + return resultingOptions } diff --git a/src/version.ts b/src/version.ts index c77a04e1..36a3d88e 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1,3 +1,2 @@ - export const version = '0.0.0' export const name = 'libp2p' diff --git a/test/identify/service.spec.ts b/test/identify/service.spec.ts index e772bad3..152d00c2 100644 --- a/test/identify/service.spec.ts +++ b/test/identify/service.spec.ts @@ -14,6 +14,7 @@ import { peerIdFromString } from '@libp2p/peer-id' import type { PeerId } from '@libp2p/interface-peer-id' import type { Libp2pNode } from '../../src/libp2p.js' import { pEvent } from 'p-event' +import { AGENT_VERSION } from '../../src/identify/consts.js' describe('libp2p.dialer.identifyService', () => { let peerId: PeerId @@ -147,6 +148,29 @@ describe('libp2p.dialer.identifyService', () => { await pWaitFor(() => connection.streams.length === 0) }) + it('should append UserAgent information to default AGENT_VERSION', async () => { + // Stub environment version for testing dynamic AGENT_VERSION + sinon.stub(process, 'version').value('vTEST') + + if (typeof globalThis.navigator !== 'undefined') { + sinon.stub(navigator, 'userAgent').value('vTEST') + } + + libp2p = await createLibp2pNode(createBaseOptions({ + peerId + })) + + await libp2p.start() + + if (libp2p.identifyService == null) { + throw new Error('Identity service was not configured') + } + + const storedAgentVersion = await libp2p.peerStore.metadataBook.getValue(peerId, 'AgentVersion') + + expect(AGENT_VERSION + ' UserAgent=vTEST').to.equal(uint8ArrayToString(storedAgentVersion ?? new Uint8Array())) + }) + it('should store host data and protocol version into metadataBook', async () => { const agentVersion = 'js-project/1.0.0'