diff --git a/packages/ipfs-core/src/components/id.js b/packages/ipfs-core/src/components/id.js index be35168bba..770e94eac8 100644 --- a/packages/ipfs-core/src/components/id.js +++ b/packages/ipfs-core/src/components/id.js @@ -4,6 +4,12 @@ import { withTimeoutOption } from 'ipfs-core-utils/with-timeout-option' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import PeerId from 'peer-id' import { NotStartedError } from '../errors.js' +import errCode from 'err-code' + +/** + * @typedef {import('libp2p')} Libp2p + * @typedef {import('ipfs-core-types/src/utils').AbortOptions} AbortOptions + */ /** * @param {Object} config @@ -15,10 +21,6 @@ export function createId ({ peerId, network }) { * @type {import('ipfs-core-types/src/root').API<{}>["id"]} */ async function id (options = {}) { // eslint-disable-line require-await - if (options.peerId === peerId.toB58String()) { - delete options.peerId - } - const net = network.try() if (!net) { @@ -38,25 +40,17 @@ export function createId ({ peerId, network }) { } } - const id = options.peerId ? PeerId.createFromB58String(options.peerId.toString()) : peerId const { libp2p } = net - - let publicKey = id.pubKey ? id.pubKey : libp2p.peerStore.keyBook.get(id) - - if (!publicKey) { - publicKey = await libp2p._dht.getPublicKey(id, options) - } - - const addresses = options.peerId ? libp2p.peerStore.addressBook.getMultiaddrsForPeer(id) : libp2p.multiaddrs - const protocols = options.peerId ? libp2p.peerStore.protoBook.get(id) : Array.from(libp2p.upgrader.protocols.keys()) - const agentVersion = uint8ArrayToString(libp2p.peerStore.metadataBook.getValue(id, 'AgentVersion') || new Uint8Array()) - const protocolVersion = uint8ArrayToString(libp2p.peerStore.metadataBook.getValue(id, 'ProtocolVersion') || new Uint8Array()) - const idStr = id.toB58String() + const peerIdToId = options.peerId ? PeerId.parse(options.peerId) : peerId + const peer = await findPeer(peerIdToId, libp2p, options) + const agentVersion = uint8ArrayToString(peer.metadata.get('AgentVersion') || new Uint8Array()) + const protocolVersion = uint8ArrayToString(peer.metadata.get('ProtocolVersion') || new Uint8Array()) + const idStr = peer.id.toB58String() return { id: idStr, - publicKey: uint8ArrayToString(publicKey.bytes, 'base64pad'), - addresses: (addresses || []) + publicKey: uint8ArrayToString(peer.publicKey.bytes, 'base64pad'), + addresses: (peer.addresses || []) .map(ma => { const str = ma.toString() @@ -72,8 +66,56 @@ export function createId ({ peerId, network }) { .map(ma => new Multiaddr(ma)), agentVersion, protocolVersion, - protocols: (protocols || []).sort() + protocols: (peer.protocols || []).sort() } } return withTimeoutOption(id) } + +/** + * @param {PeerId} peerId + * @param {Libp2p} libp2p + * @param {AbortOptions} options + */ +async function findPeer (peerId, libp2p, options) { + let peer = libp2p.peerStore.get(peerId) + + if (!peer) { + peer = await findPeerOnDht(peerId, libp2p, options) + } + + let publicKey = peerId.pubKey ? peerId.pubKey : libp2p.peerStore.keyBook.get(peerId) + + if (!publicKey) { + publicKey = await libp2p._dht.getPublicKey(peerId, options) + } + + return { + ...peer, + publicKey, + metadata: peer.metadata || new Map(), + addresses: peer.addresses.map(addr => addr.multiaddr) + } +} + +/** + * + * @param {PeerId} peerId + * @param {Libp2p} libp2p + * @param {AbortOptions} options + */ +async function findPeerOnDht (peerId, libp2p, options) { + for await (const event of libp2p._dht.findPeer(peerId, options)) { + if (event.name === 'FINAL_PEER') { + break + } + } + + const peer = libp2p.peerStore.get(peerId) + + if (!peer) { + throw errCode(new Error('Could not find peer'), 'ERR_NOT_FOUND') + } + + return peer +}