"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OracleAnnouncement = void 0;
const bufio_1 = require("@node-dlc/bufio");
const bip_schnorr_1 = require("bip-schnorr");
const MessageType_1 = require("../MessageType");
const getTlv_1 = require("../serialize/getTlv");
const OracleEvent_1 = require("./OracleEvent");
/**
 * Oracle announcement that describe an event and the way that an oracle will
 * attest to it. Updated to be rust-dlc compliant.
 *
 * In order to make it possible to hold oracles accountable in cases where
 * they do not release a signature for an event outcome, there needs to be
 * a proof that an oracle has committed to a given outcome. This proof is
 * given in a so-called oracle announcement, which contains an oracle event
 * together with the oracle public key and a signature over its serialization,
 * which must be valid with respect to the specified public key.
 *
 * This also makes it possible for users to obtain oracle event information
 * from an un-trusted peer while being guaranteed that it originates from a
 * given oracle.
 */
class OracleAnnouncement {
    constructor() {
        /**
         * The type for oracle_announcement message. oracle_announcement = 55332
         */
        this.type = OracleAnnouncement.type;
    }
    /**
     * Creates an OracleAnnouncement from JSON data
     * @param json JSON object representing oracle announcement
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
    static fromJSON(json) {
        const instance = new OracleAnnouncement();
        // Handle different field name variations
        instance.announcementSig = Buffer.from(json.announcementSignature ||
            json.announcementSig ||
            json.announcement_signature, 'hex');
        instance.oraclePubkey = Buffer.from(json.oraclePublicKey || json.oraclePubkey || json.oracle_public_key, 'hex');
        instance.oracleEvent = OracleEvent_1.OracleEvent.fromJSON(json.oracleEvent || json.oracle_event);
        return instance;
    }
    /**
     * Deserializes an oracle_announcement message
     * @param buf
     */
    static deserialize(buf) {
        const instance = new OracleAnnouncement();
        const reader = new bufio_1.BufferReader(buf);
        reader.readBigSize(); // read type
        instance.length = reader.readBigSize();
        instance.announcementSig = reader.readBytes(64);
        instance.oraclePubkey = reader.readBytes(32);
        instance.oracleEvent = OracleEvent_1.OracleEvent.deserialize((0, getTlv_1.getTlv)(reader));
        return instance;
    }
    /**
     * Validates the oracle announcement according to rust-dlc specification.
     * This includes validating the oracle event and verifying the announcement signature.
     * @throws Will throw an error if validation fails
     */
    validate() {
        // Validate oracle event first
        this.oracleEvent.validate();
        // Validate oracle public key format (32 bytes for x-only)
        if (!this.oraclePubkey || this.oraclePubkey.length !== 32) {
            throw new Error('Oracle public key must be 32 bytes (x-only format)');
        }
        // Validate announcement signature format (64 bytes for Schnorr)
        if (!this.announcementSig || this.announcementSig.length !== 64) {
            throw new Error('Announcement signature must be 64 bytes (Schnorr format)');
        }
        // Verify announcement signature over the oracle event
        try {
            const msg = bip_schnorr_1.math.taggedHash('DLC/oracle/announcement/v0', this.oracleEvent.serialize());
            (0, bip_schnorr_1.verify)(this.oraclePubkey, msg, this.announcementSig);
        }
        catch (error) {
            throw new Error(`Invalid announcement signature: ${error.message}`);
        }
    }
    /**
     * Returns the nonces from the oracle event.
     * This is useful for finding matching oracle announcements.
     */
    getNonces() {
        return this.oracleEvent.oracleNonces;
    }
    /**
     * Returns the event maturity epoch from the oracle event.
     */
    getEventMaturityEpoch() {
        return this.oracleEvent.eventMaturityEpoch;
    }
    /**
     * Returns the event ID from the oracle event.
     */
    getEventId() {
        return this.oracleEvent.eventId;
    }
    /**
     * Converts oracle_announcement to JSON (canonical rust-dlc format)
     */
    toJSON() {
        return {
            announcementSignature: this.announcementSig.toString('hex'),
            oraclePublicKey: this.oraclePubkey.toString('hex'),
            oracleEvent: this.oracleEvent.toJSON(),
        };
    }
    /**
     * Serializes the oracle_announcement message into a Buffer
     */
    serialize() {
        const writer = new bufio_1.BufferWriter();
        writer.writeBigSize(this.type);
        const dataWriter = new bufio_1.BufferWriter();
        dataWriter.writeBytes(this.announcementSig);
        dataWriter.writeBytes(this.oraclePubkey);
        dataWriter.writeBytes(this.oracleEvent.serialize());
        writer.writeBigSize(dataWriter.size);
        writer.writeBytes(dataWriter.toBuffer());
        return writer.toBuffer();
    }
}
exports.OracleAnnouncement = OracleAnnouncement;
OracleAnnouncement.type = MessageType_1.MessageType.OracleAnnouncement;
//# sourceMappingURL=OracleAnnouncement.js.map