import { peerIdFromMultihash } from '@libp2p/peer-id';
import { arrayEquals } from '@libp2p/utils/array-equals';
import { multiaddr } from '@multiformats/multiaddr';
import * as Digest from 'multiformats/hashes/digest';
import { ENVELOPE_DOMAIN_PEER_RECORD, ENVELOPE_PAYLOAD_TYPE_PEER_RECORD } from './consts.js';
import { PeerRecord as Protobuf } from './peer-record.js';
/**
 * The PeerRecord is used for distributing peer routing records across the network.
 * It contains the peer's reachable listen addresses.
 */
export class PeerRecord {
    /**
     * Unmarshal Peer Record Protobuf
     */
    static createFromProtobuf = (buf) => {
        const peerRecord = Protobuf.decode(buf);
        const peerId = peerIdFromMultihash(Digest.decode(peerRecord.peerId));
        const multiaddrs = (peerRecord.addresses ?? []).map((a) => multiaddr(a.multiaddr));
        const seqNumber = peerRecord.seq;
        return new PeerRecord({ peerId, multiaddrs, seqNumber });
    };
    static DOMAIN = ENVELOPE_DOMAIN_PEER_RECORD;
    static CODEC = ENVELOPE_PAYLOAD_TYPE_PEER_RECORD;
    peerId;
    multiaddrs;
    seqNumber;
    domain = PeerRecord.DOMAIN;
    codec = PeerRecord.CODEC;
    marshaled;
    constructor(init) {
        const { peerId, multiaddrs, seqNumber } = init;
        this.peerId = peerId;
        this.multiaddrs = multiaddrs ?? [];
        this.seqNumber = seqNumber ?? BigInt(Date.now());
    }
    /**
     * Marshal a record to be used in an envelope
     */
    marshal() {
        if (this.marshaled == null) {
            this.marshaled = Protobuf.encode({
                peerId: this.peerId.toMultihash().bytes,
                seq: BigInt(this.seqNumber),
                addresses: this.multiaddrs.map((m) => ({
                    multiaddr: m.bytes
                }))
            });
        }
        return this.marshaled;
    }
    /**
     * Returns true if `this` record equals the `other`
     */
    equals(other) {
        if (!(other instanceof PeerRecord)) {
            return false;
        }
        // Validate PeerId
        if (!this.peerId.equals(other.peerId)) {
            return false;
        }
        // Validate seqNumber
        if (this.seqNumber !== other.seqNumber) {
            return false;
        }
        // Validate multiaddrs
        if (!arrayEquals(this.multiaddrs, other.multiaddrs)) {
            return false;
        }
        return true;
    }
}
//# sourceMappingURL=index.js.map