"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const bson_1 = require("bson");
const chai_1 = require("chai");
const sinon = __importStar(require("sinon"));
const stream_1 = require("stream");
const wallet_1 = require("../../../src/models/wallet");
const walletAddress_1 = require("../../../src/models/walletAddress");
const transaction_1 = require("../../../src/providers/chain-state/evm/models/transaction");
const integration_1 = require("../../helpers/integration");
const chain = 'ETH';
const network = 'regtest';
describe('EVM Memory Leak Prevention', function () {
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const suite = this;
    this.timeout(30000);
    let globalSandbox;
    let ETH;
    before(integration_1.intBeforeHelper);
    after(async () => (0, integration_1.intAfterHelper)(suite));
    beforeEach(async () => {
        globalSandbox = sinon.createSandbox();
        // Use the ETH module instance
        const { ETH: ETHModule } = await Promise.resolve().then(() => __importStar(require('../../../src/modules/ethereum/api/csp')));
        ETH = ETHModule;
        await transaction_1.EVMTransactionStorage.collection.deleteMany({});
        await wallet_1.WalletStorage.collection.deleteMany({});
        await walletAddress_1.WalletAddressStorage.collection.deleteMany({});
    });
    afterEach(() => {
        globalSandbox.restore();
    });
    function createMockReqRes() {
        const reqStream = new stream_1.PassThrough();
        const req = reqStream;
        const resStream = new stream_1.PassThrough();
        const res = resStream;
        res.write = resStream.write.bind(resStream);
        res.end = resStream.end.bind(resStream);
        res.type = () => res;
        res.status = () => res;
        res.send = () => res;
        // Consume data to keep stream flowing
        resStream.on('data', () => { });
        return { req, res, reqEmitter: reqStream, resEmitter: resStream };
    }
    describe('Cursor Cleanup on Client Disconnect', () => {
        it('should not crash when client disconnects during streamWalletTransactions', async () => {
            const address = '0x7F17aF79AABC4A297A58D389ab5905fEd4Ec9502';
            const objectId = bson_1.ObjectId.createFromHexString('60f9abed0e32086bf9903bb5');
            const wallet = {
                _id: objectId,
                chain,
                network,
                name: 'test-wallet',
                pubKey: '0x029ec2ebdebe6966259cf3c6f35c4f126b82fe072bf9d0e81dad375f1d6d2d9054',
                path: 'm/44\'/60\'/0\'/0/0',
                singleAddress: true
            };
            await wallet_1.WalletStorage.collection.insertOne(wallet);
            await walletAddress_1.WalletAddressStorage.collection.insertOne({
                chain,
                network,
                wallet: objectId,
                address,
                processed: true
            });
            const txCount = 5;
            const txs = new Array(txCount).fill({}).map((_, i) => ({
                chain,
                network,
                blockHeight: 1,
                gasPrice: 10 * 1e9,
                data: Buffer.from(''),
                from: address,
                to: '0xRecipient123',
                txid: '0x' + (i + 1).toString(16).padStart(64, '0'),
                wallets: [objectId]
            }));
            await transaction_1.EVMTransactionStorage.collection.insertMany(txs);
            const { req, res, reqEmitter } = createMockReqRes();
            const streamPromise = ETH.streamWalletTransactions({
                chain,
                network,
                wallet,
                req,
                res,
                args: {}
            });
            // Wait for stream to start
            await new Promise(resolve => setTimeout(resolve, 100));
            // Simulate client disconnect
            reqEmitter.emit('close');
            // Wait for cleanup
            await new Promise(resolve => setTimeout(resolve, 100));
            // Should not throw - the implementation should handle cleanup gracefully
            await streamPromise.catch(() => { });
            // If we get here without crashing, the test passes
            (0, chai_1.expect)(true).to.be.true;
        });
        it('should handle multiple interrupted requests without accumulating resources', async () => {
            const address = '0x7F17aF79AABC4A297A58D389ab5905fEd4Ec9502';
            const objectId = bson_1.ObjectId.createFromHexString('60f9abed0e32086bf9903bb5');
            const wallet = {
                _id: objectId,
                chain,
                network,
                name: 'test-wallet-multi',
                pubKey: '0x029ec2ebdebe6966259cf3c6f35c4f126b82fe072bf9d0e81dad375f1d6d2d9054',
                path: 'm/44\'/60\'/0\'/0/0',
                singleAddress: true
            };
            await wallet_1.WalletStorage.collection.insertOne(wallet);
            await walletAddress_1.WalletAddressStorage.collection.insertOne({
                chain,
                network,
                wallet: objectId,
                address,
                processed: true
            });
            const txCount = 5;
            const txs = new Array(txCount).fill({}).map((_, i) => ({
                chain,
                network,
                blockHeight: 1,
                gasPrice: 10 * 1e9,
                data: Buffer.from(''),
                from: address,
                to: '0xRecipient456',
                txid: '0x' + (i + 100).toString(16).padStart(64, '0'),
                wallets: [objectId]
            }));
            await transaction_1.EVMTransactionStorage.collection.insertMany(txs);
            // Make 3 requests that all get interrupted
            const numRequests = 3;
            for (let i = 0; i < numRequests; i++) {
                const { req, res, reqEmitter } = createMockReqRes();
                const streamPromise = ETH.streamWalletTransactions({
                    chain,
                    network,
                    wallet,
                    req,
                    res,
                    args: {}
                });
                await new Promise(resolve => setTimeout(resolve, 50));
                reqEmitter.emit('close');
                await new Promise(resolve => setTimeout(resolve, 50));
                await streamPromise.catch(() => { });
            }
            // If we completed all requests without issues, test passes
            (0, chai_1.expect)(true).to.be.true;
        });
    });
    describe('Provider Instance Reuse', () => {
        it('should complete streaming without errors', async () => {
            const address = '0x7F17aF79AABC4A297A58D389ab5905fEd4Ec9502';
            const objectId = bson_1.ObjectId.createFromHexString('60f9abed0e32086bf9903bb5');
            const wallet = {
                _id: objectId,
                chain,
                network,
                name: 'test-wallet-provider',
                pubKey: '0x029ec2ebdebe6966259cf3c6f35c4f126b82fe072bf9d0e81dad375f1d6d2d9054',
                path: 'm/44\'/60\'/0\'/0/0',
                singleAddress: true
            };
            await wallet_1.WalletStorage.collection.insertOne(wallet);
            await walletAddress_1.WalletAddressStorage.collection.insertOne({
                chain,
                network,
                wallet: objectId,
                address,
                processed: true
            });
            const txCount = 5;
            const txs = new Array(txCount).fill({}).map((_, i) => ({
                chain,
                network,
                blockHeight: 1,
                gasPrice: 10 * 1e9,
                data: Buffer.from(''),
                from: address,
                to: '0xRecipient789',
                txid: '0x' + (i + 200).toString(16).padStart(64, '0'),
                wallets: [objectId]
            }));
            await transaction_1.EVMTransactionStorage.collection.insertMany(txs);
            const { req, res, resEmitter } = createMockReqRes();
            let receivedTxCount = 0;
            resEmitter.on('data', () => {
                receivedTxCount++;
            });
            await new Promise((resolve, reject) => {
                resEmitter.on('finish', resolve);
                resEmitter.on('error', reject);
                ETH.streamWalletTransactions({
                    chain,
                    network,
                    wallet,
                    req,
                    res,
                    args: {}
                }).catch(reject);
            });
            // Verify that we received some transactions (stream worked)
            (0, chai_1.expect)(receivedTxCount).to.be.greaterThan(0);
        });
    });
});
//# sourceMappingURL=memory-leaks.test.js.map