"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.listenToOraclePriceChanges = listenToOraclePriceChanges;
const buffer_1 = require("buffer");
const OraclePrices_1 = require("@kamino-finance/scope-sdk/dist/@codegen/scope/accounts/OraclePrices");
const bufferedDispatcher_1 = require("./bufferedDispatcher");
const subscriptionHandle_1 = require("./subscriptionHandle");
const wsErrorReporter_1 = require("./wsErrorReporter");
const wsReconnectLoop_1 = require("./wsReconnectLoop");
/**
 * `onBeforeReconnect` fires once per address. Scope normally stores all
 * prices in a single OraclePrices account so the array is usually length 1
 * — but if you subscribe to several, dedupe at the consumer.
 */
function listenToOraclePriceChanges(params) {
    const commitment = params.commitment ?? 'confirmed';
    const dispatcher = (0, bufferedDispatcher_1.createBufferedDispatcher)({
        scheduler: params.scheduler,
        throttleMs: params.throttleMs,
        keyOf: (event) => event.address,
        onDeliver: params.onChange,
        onError: params.onError,
        errorPrefix: '[listenToOraclePriceChanges]',
        callSiteName: 'listenToOraclePriceChanges',
    });
    // Decode runs inside runReconnectLoop's onMessage — BEFORE the buffered
    // dispatcher — so a decode throw was being attributed to the reconnect
    // loop's default '[ws-reconnect-loop]' prefix instead of this listener.
    // Route decode failures through a listener-specific reporter so error
    // attribution is correct (and the user's onError still sees them).
    const decodeErrorReporter = (0, wsErrorReporter_1.makeWsErrorReporter)('[listenToOraclePriceChanges]', params.onError);
    const stopAddressLoops = params.oracleAddresses.map((oracleAddress) => (0, wsReconnectLoop_1.runReconnectLoop)({
        wsRpc: params.wsRpc,
        reconnectDelayMs: params.reconnectDelayMs,
        onError: params.onError,
        onLog: params.onLog,
        onBeforeReconnect: params.onBeforeReconnect,
        subscribe: (wsRpc, abortSignal) => wsRpc.accountNotifications(oracleAddress, { commitment, encoding: 'base64' }).subscribe({ abortSignal }),
        onMessage: ({ context, value }) => {
            const [base64Data] = value.data;
            let oraclePrices;
            try {
                oraclePrices = OraclePrices_1.OraclePrices.decode(buffer_1.Buffer.from(base64Data, 'base64'));
            }
            catch (e) {
                decodeErrorReporter.reportError(e);
                return;
            }
            dispatcher.push({
                address: oracleAddress,
                oraclePrices,
                slot: context.slot,
            });
        },
    }));
    return (0, subscriptionHandle_1.makeSubscriptionHandle)(() => {
        dispatcher.unsubscribe();
        stopAddressLoops.forEach((stopLoop) => stopLoop());
    }, () => dispatcher.flush());
}
//# sourceMappingURL=oracleListener.js.map