/// <reference types="node" />
import { EventEmitter } from 'events';
import { Socket } from 'net';
import { DisconnectionReason, ReputationEvent, SwapClientType } from '../constants/enums';
import Logger from '../Logger';
import NodeKey from '../nodekey/NodeKey';
import { OutgoingOrder } from '../orderbook/types';
import Network from './Network';
import { Packet } from './packets';
import { ResponseType } from './packets/Packet';
import * as packets from './packets/types';
import { Address, NodeConnectionInfo, NodeState } from './types';
/** Key info about a peer for display purposes */
declare type PeerInfo = {
    address: string;
    nodePubKey?: string;
    alias?: string;
    inbound: boolean;
    pairs?: string[];
    xudVersion?: string;
    secondsConnected: number;
    lndPubKeys?: {
        [currency: string]: string | undefined;
    };
    connextIdentifier?: string;
};
interface Peer {
    on(event: 'packet', listener: (packet: Packet) => void): this;
    on(event: 'reputation', listener: (event: ReputationEvent) => void): this;
    /** Adds a listener to be called when the peer's advertised but inactive pairs should be verified. */
    on(event: 'verifyPairs', listener: () => void): this;
    /** Adds a listener to be called when a previously active pair is dropped by the peer or deactivated. */
    on(event: 'pairDropped', listener: (pairId: string) => void): this;
    on(event: 'nodeStateUpdate', listener: () => void): this;
    once(event: 'close', listener: () => void): this;
    emit(event: 'connect'): boolean;
    emit(event: 'reputation', reputationEvent: ReputationEvent): boolean;
    emit(event: 'close'): boolean;
    emit(event: 'packet', packet: Packet): boolean;
    /** Notifies listeners that the peer's advertised but inactive pairs should be verified. */
    emit(event: 'verifyPairs'): boolean;
    /** Notifies listeners that a previously active pair was dropped by the peer or deactivated. */
    emit(event: 'pairDropped', pairId: string): boolean;
    emit(event: 'nodeStateUpdate'): boolean;
}
/** Represents a remote peer and manages a TCP socket and incoming/outgoing communication with that peer. */
declare class Peer extends EventEmitter {
    private logger;
    address: Address;
    inbound: boolean;
    /** The reason this peer disconnected from us. */
    recvDisconnectionReason?: DisconnectionReason;
    /** The reason we told this peer we disconnected from it. */
    sentDisconnectionReason?: DisconnectionReason;
    expectedNodePubKey?: string;
    /** Whether the peer is included in the p2p pool list of peers and will receive broadcasted packets. */
    active: boolean;
    /** Timer to periodically call getNodes #402 */
    discoverTimer?: NodeJS.Timer;
    /**
     * Currencies that we cannot swap because we are missing a swap client identifier or because the
     * peer's token identifier for this currency does not match ours - for example this may happen
     * because a peer is using a different token contract address for a currency than we are.
     */
    disabledCurrencies: Set<string>;
    /** Interval to check required responses from peer. */
    static readonly STALL_INTERVAL = 5000;
    private status;
    /** Trading pairs advertised by this peer which we have verified that we can swap. */
    private activePairs;
    /** Currencies that we have verified we can swap with this peer. */
    private activeCurrencies;
    private socket?;
    private readonly parser;
    /** Timer to retry connection to peer after the previous attempt failed. */
    private retryConnectionTimer?;
    private stallTimer?;
    private pingTimer?;
    private checkPairsTimer?;
    private readonly responseMap;
    /** The epoch time in ms when we connected to this peer. */
    private connectTime;
    private connectionRetriesRevoked;
    /** The version of xud this peer is using. */
    private _version?;
    /** The node pub key of this peer. */
    private _nodePubKey?;
    private _alias?;
    private nodeState?;
    private sessionInitPacket?;
    private outEncryptionKey?;
    private readonly network;
    private readonly framer;
    /** Interval for pinging peers. */
    private static readonly PING_INTERVAL;
    /** Interval for checking if we can reactivate any inactive pairs with peers. */
    private static readonly CHECK_PAIRS_INTERVAL;
    /** Response timeout for response packets. */
    private static readonly RESPONSE_TIMEOUT;
    /** Connection retries min delay. */
    private static readonly CONNECTION_RETRIES_MIN_DELAY;
    /** Connection retries max delay. */
    private static readonly CONNECTION_RETRIES_MAX_DELAY;
    /** Connection retries max period. */
    private static readonly CONNECTION_RETRIES_MAX_PERIOD;
    /** The version of xud this peer is using, or an empty string if it is still not known. */
    get version(): string;
    /** The hex-encoded node public key for this peer, or undefined if it is still not known. */
    get nodePubKey(): string | undefined;
    set nodePubKey(nodePubKey: string | undefined);
    get alias(): string | undefined;
    get label(): string;
    get addresses(): Address[] | undefined;
    get connextIdentifier(): string | undefined;
    /** Returns a list of trading pairs advertised by this peer. */
    get advertisedPairs(): string[];
    get connected(): boolean;
    get info(): PeerInfo;
    /**
     * @param address The socket address for the connection to this peer.
     */
    constructor(logger: Logger, address: Address, network: Network);
    /**
     * Creates a Peer from an inbound socket connection.
     */
    static fromInbound: (socket: Socket, logger: Logger, network: Network) => Peer;
    getAdvertisedCurrencies: () => Set<string>;
    getLndPubKey(currency?: string): string | undefined;
    getIdentifier: (clientType: SwapClientType, currency?: string | undefined) => string | undefined;
    getTokenIdentifier: (currency: string) => string | undefined;
    getStatus: () => string;
    /**
     * Prepares a peer for use by establishing a socket connection and beginning the handshake.
     * @returns the session init packet from beginning the handshake
     */
    beginOpen: ({ ownNodeState, ownNodeKey, ownVersion, expectedNodePubKey, retryConnecting, torport, }: {
        /** Our node state data to send to the peer. */
        ownNodeState: NodeState;
        /** Our identity node key. */
        ownNodeKey: NodeKey;
        /** The version of xud we are running. */
        ownVersion: string;
        /** The expected nodePubKey of the node we are opening a connection with. */
        expectedNodePubKey?: string | undefined;
        /** Whether to retry to connect upon failure. */
        retryConnecting?: boolean | undefined;
        /** Port that Tor's exposed SOCKS5 proxy is listening on. */
        torport: number;
    }) => Promise<packets.SessionInitPacket>;
    /**
     * Finishes opening a peer for use by marking the peer as opened, completing the handshake,
     * and setting up the ping packet timer.
     * @param ownNodeState our node state data to send to the peer
     * @param ownNodeKey our identity node key
     * @param ownVersion the version of xud we are running
     * @param sessionInit the session init packet we received when beginning the handshake
     */
    completeOpen: (ownNodeState: NodeState, ownNodeKey: NodeKey, ownVersion: string, sessionInit: packets.SessionInitPacket) => Promise<void>;
    /**
     * Close a peer by ensuring the socket is destroyed and terminating all timers.
     */
    close: (reason?: DisconnectionReason | undefined, reasonPayload?: string | undefined) => Promise<void>;
    revokeConnectionRetries: () => void;
    sendPacket: (packet: Packet) => Promise<void>;
    sendOrders: (orders: OutgoingOrder[], reqId: string) => Promise<void>;
    /** Sends a [[NodesPacket]] containing node connection info to this peer. */
    sendNodes: (nodes: NodeConnectionInfo[], reqId: string) => Promise<void>;
    deactivateCurrency: (currency: string) => void;
    activateCurrency: (currency: string) => Set<string>;
    disableCurrency: (currency: string) => void;
    enableCurrency: (currency: string) => void;
    /**
     * Deactivates a trading pair with this peer.
     */
    deactivatePair: (pairId: string) => void;
    /**
     * Activates a trading pair with this peer.
     */
    activatePair: (pairId: string) => Promise<void>;
    isPairActive: (pairId: string) => boolean;
    isCurrencyActive: (currency: string) => boolean;
    /**
     * Gets lnd client's listening uris for the provided currency.
     * @param currency
     */
    getLndUris(currency: string): string[] | undefined;
    /**
     * Ensure we are connected (for inbound connections) or listen for the `connect` socket event (for outbound connections)
     * and set the [[connectTime]] timestamp. If an outbound connection attempt errors or times out, throw an error.
     */
    private initConnection;
    private initStall;
    /**
     * Waits for a packet to be received from peer.
     * @returns A promise that is resolved once the packet is received or rejects on timeout.
     */
    wait: (reqId: string, resType: ResponseType, timeout?: number | undefined, cb?: ((packet: Packet) => void) | undefined) => Promise<Packet>;
    private waitSessionInit;
    /**
     * Potentially timeout peer if it hasn't responded.
     */
    private checkTimeout;
    /**
     * Wait for a packet to be received from peer.
     */
    private addResponseTimeout;
    private getOrAddPendingResponseEntry;
    /**
     * Fulfill a pending response entry for solicited responses, penalize unsolicited responses.
     * @returns false if no pending response entry exists for the provided key, otherwise true
     */
    private fulfillResponseEntry;
    /**
     * Binds listeners to a newly connected socket for `error`, `close`, and `data` events.
     */
    private bindSocket;
    private bindParser;
    /** Checks if a given packet is solicited and fulfills the pending response entry if it's a response. */
    private isPacketSolicited;
    private handlePacket;
    /**
     * Authenticates the identity of a peer with a [[SessionInitPacket]] and sets the peer's node state.
     * Throws an error and closes the peer if authentication fails.
     * @param packet the session init packet
     * @param nodePubKey our node pub key
     * @param expectedNodePubKey the expected node pub key of the sender of the init packet
     */
    private authenticateSessionInit;
    /**
     * Sets public key and alias for this node together so that they are always in sync.
     */
    setIdentifiers(nodePubKey: string): void;
    /**
     * Sends a [[SessionInitPacket]] and waits for a [[SessionAckPacket]].
     */
    private initSession;
    /**
     * Sends a [[SessionAckPacket]] in response to a given [[SessionInitPacket]].
     */
    private ackSession;
    /**
     * Begins the handshake by waiting for a [[SessionInitPacket]] as well as sending our own
     * [[SessionInitPacket]] first if we are the outbound peer.
     * @returns the session init packet we receive
     */
    private beginHandshake;
    /**
     * Completes the handshake by sending the [[SessionAckPacket]] and our [[SessionInitPacket]] if it
     * has not been sent already, as is the case with inbound peers.
     */
    private completeHandshake;
    private sendPing;
    sendGetNodes: () => Promise<packets.GetNodesPacket>;
    discoverNodes: () => Promise<number>;
    private sendPong;
    private handlePing;
    private createSessionInitPacket;
    private handleDisconnecting;
    private handleSessionInit;
    private handleNodeStateUpdate;
    private setOutEncryption;
    private setInEncryption;
}
export default Peer;
export { PeerInfo };
