import { InvalidParametersError } from '@libp2p/interface'
import { CODE_P2P, isMultiaddr, multiaddr } from '@multiformats/multiaddr'
import type { AddressFilter } from '../index.js'
import type { Address as AddressPB } from '../pb/peer.js'
import type { PeerId, Address, AbortOptions } from '@libp2p/interface'
export async function dedupeFilterAndSortAddresses (peerId: PeerId, filter: AddressFilter, addresses: Array
, existingAddresses?: AddressPB[], options?: AbortOptions): Promise {
const addressMap = new Map()
for (const addr of addresses) {
if (addr == null) {
continue
}
if (addr.multiaddr instanceof Uint8Array) {
addr.multiaddr = multiaddr(addr.multiaddr)
}
if (!isMultiaddr(addr.multiaddr)) {
throw new InvalidParametersError('Multiaddr was invalid')
}
if (!(await filter(peerId, addr.multiaddr, options))) {
continue
}
const isCertified = addr.isCertified ?? false
const maStr = addr.multiaddr.toString()
const existingAddr = addressMap.get(maStr)
if (existingAddr != null) {
addr.isCertified = existingAddr.isCertified || isCertified
} else {
addressMap.set(maStr, {
multiaddr: addr.multiaddr,
isCertified
})
}
}
return [...addressMap.values()]
.sort((a, b) => {
return a.multiaddr.toString().localeCompare(b.multiaddr.toString())
})
.map(({ isCertified, multiaddr: ma }) => {
// strip the trailing peerId if it is present
const addrPeer = ma.getComponents().find(c => c.code === CODE_P2P)?.value
if (peerId.equals(addrPeer)) {
ma = ma.decapsulate(multiaddr(`/p2p/${peerId}`))
}
return {
isCertified,
multiaddr: ma.bytes
}
})
}