"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const sinon_1 = __importDefault(require("sinon"));
const axios_1 = __importDefault(require("axios"));
const errors_1 = require("../../../src/providers/chain-state/external/adapters/errors");
const moralis_1 = require("../../../src/providers/chain-state/external/adapters/moralis");
const moralis_utils_1 = require("../../../src/providers/chain-state/external/adapters/moralis-utils");
const transaction_1 = require("../../../src/providers/chain-state/evm/models/transaction");
const config_1 = __importDefault(require("../../../src/config"));
const VALID_TX_HASH = '0xabc123def456abc123def456abc123def456abc123def456abc123def456abc1';
const MOCK_MORALIS_TX = {
    chain: 'ETH',
    network: 'mainnet',
    hash: VALID_TX_HASH,
    block_number: '18000000',
    block_hash: '0xblockhash123',
    block_timestamp: '2023-09-01T12:00:00.000Z',
    value: '1000000000000000000',
    gas: '21000',
    gas_price: '20000000000',
    receipt_gas_used: '21000',
    nonce: 5,
    to_address: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD1E',
    from_address: '0x388C818CA8B9251b393131C08a736A67ccB19297',
    input: '0x',
    internal_transactions: [],
    category: 'token send',
    transaction_index: 42
};
describe('MoralisAdapter', function () {
    let sandbox;
    let adapter;
    let axiosGetStub;
    const savedExternalProviders = config_1.default.externalProviders;
    before(function () {
        config_1.default.externalProviders = {
            ...savedExternalProviders,
            moralis: { apiKey: 'test-moralis-key' }
        };
    });
    after(function () {
        config_1.default.externalProviders = savedExternalProviders;
    });
    beforeEach(function () {
        sandbox = sinon_1.default.createSandbox();
        sandbox.stub(transaction_1.EVMTransactionStorage, 'addEffectsToTxs').callsFake(() => { });
        sandbox.stub(transaction_1.EVMTransactionStorage, 'abiDecode').returns(undefined);
        sandbox.stub(transaction_1.EVMTransactionStorage, '_apiTransform').callsFake((tx) => tx);
        axiosGetStub = sandbox.stub(axios_1.default, 'get');
        adapter = new moralis_1.MoralisAdapter({ name: 'moralis', priority: 1 });
    });
    afterEach(function () {
        sandbox.restore();
    });
    // --- Constructor ---
    describe('constructor', function () {
        it('should throw if apiKey missing from config', function () {
            const saved = config_1.default.externalProviders;
            config_1.default.externalProviders = { moralis: { apiKey: '' } };
            (0, chai_1.expect)(() => new moralis_1.MoralisAdapter({ name: 'moralis', priority: 1 }))
                .to.throw('apiKey is required');
            config_1.default.externalProviders = saved;
        });
        it('should set the adapter name', function () {
            (0, chai_1.expect)(adapter.name).to.equal('Moralis');
        });
    });
    // --- getTransaction ---
    describe('getTransaction', function () {
        const params = { chain: 'ETH', network: 'mainnet', chainId: '1', txId: VALID_TX_HASH };
        it('should fetch and transform a transaction', async function () {
            axiosGetStub.resolves({ data: MOCK_MORALIS_TX });
            const result = await adapter.getTransaction(params);
            (0, chai_1.expect)(result).to.exist;
            (0, chai_1.expect)(result.txid).to.equal(VALID_TX_HASH);
            (0, chai_1.expect)(result.blockHeight).to.equal(18000000);
        });
        it('should return undefined on 404', async function () {
            axiosGetStub.rejects({ isAxiosError: true, response: { status: 404 } });
            (0, chai_1.expect)(await adapter.getTransaction(params)).to.be.undefined;
        });
        it('should return undefined when response data is empty', async function () {
            axiosGetStub.resolves({ data: null });
            (0, chai_1.expect)(await adapter.getTransaction(params)).to.be.undefined;
        });
        it('should throw INVALID_REQUEST for bad txId format', async function () {
            try {
                await adapter.getTransaction({ ...params, txId: 'not-a-hash' });
                chai_1.expect.fail('Should have thrown');
            }
            catch (err) {
                (0, chai_1.expect)(err).to.be.instanceOf(errors_1.AdapterError);
                (0, chai_1.expect)(err.code).to.equal(errors_1.AdapterErrorCode.INVALID_REQUEST);
                (0, chai_1.expect)(axiosGetStub.called).to.be.false;
            }
        });
    });
    // --- Error classification ---
    describe('error classification', function () {
        const params = { chain: 'ETH', network: 'mainnet', chainId: '1', txId: VALID_TX_HASH };
        const errorCases = [
            {
                scenario: 'HTTP 401 → AUTH',
                error: { isAxiosError: true, response: { status: 401 } },
                expectedCode: errors_1.AdapterErrorCode.AUTH
            },
            {
                scenario: 'HTTP 403 → AUTH',
                error: { isAxiosError: true, response: { status: 403 } },
                expectedCode: errors_1.AdapterErrorCode.AUTH
            },
            {
                scenario: 'HTTP 429 → RATE_LIMIT',
                error: { isAxiosError: true, response: { status: 429 } },
                expectedCode: errors_1.AdapterErrorCode.RATE_LIMIT
            },
            {
                scenario: 'HTTP 500 → UPSTREAM',
                error: { isAxiosError: true, response: { status: 500 } },
                expectedCode: errors_1.AdapterErrorCode.UPSTREAM
            },
            {
                scenario: 'timeout → TIMEOUT',
                error: { isAxiosError: true, code: 'ECONNABORTED' },
                expectedCode: errors_1.AdapterErrorCode.TIMEOUT
            }
        ];
        for (const { scenario, error, expectedCode } of errorCases) {
            it(`should classify ${scenario}`, async function () {
                axiosGetStub.rejects(error);
                try {
                    await adapter.getTransaction(params);
                    chai_1.expect.fail('Should have thrown');
                }
                catch (err) {
                    (0, chai_1.expect)(err).to.be.instanceOf(errors_1.AdapterError);
                    (0, chai_1.expect)(err.code).to.equal(expectedCode);
                }
            });
        }
    });
    // --- healthCheck ---
    describe('healthCheck', function () {
        it('should return true on success', async function () {
            axiosGetStub.resolves({ data: {} });
            (0, chai_1.expect)(await adapter.healthCheck()).to.equal(true);
        });
        it('should return false on failure', async function () {
            axiosGetStub.rejects(new Error('network error'));
            (0, chai_1.expect)(await adapter.healthCheck()).to.equal(false);
        });
    });
    // --- chainId in query ---
    describe('chainId in requests', function () {
        const params = { chain: 'ETH', network: 'mainnet', chainId: '1', txId: VALID_TX_HASH };
        it('should pass hex chainId through', async function () {
            axiosGetStub.resolves({ data: MOCK_MORALIS_TX });
            await adapter.getTransaction({ ...params, chainId: '0x1' });
            (0, chai_1.expect)(axiosGetStub.firstCall.args[0]).to.include('chain=0x1');
        });
        it('should convert decimal chainId to hex', async function () {
            axiosGetStub.resolves({ data: MOCK_MORALIS_TX });
            await adapter.getTransaction({ ...params, chainId: '137' });
            (0, chai_1.expect)(axiosGetStub.firstCall.args[0]).to.include('chain=0x89');
        });
    });
    // --- Shared moralis-utils ---
    describe('moralis-utils', function () {
        describe('transformMoralisTransaction', function () {
            it('should map snake_case Moralis fields to IEVMTransactionTransformed', function () {
                const result = (0, moralis_utils_1.transformMoralisTransaction)(MOCK_MORALIS_TX);
                (0, chai_1.expect)(result.txid).to.equal(MOCK_MORALIS_TX.hash);
                (0, chai_1.expect)(result.blockHeight).to.equal(18000000);
                (0, chai_1.expect)(result.chain).to.equal('ETH');
                (0, chai_1.expect)(result.network).to.equal('mainnet');
            });
            it('should handle camelCase field variants', function () {
                const camelTx = {
                    ...MOCK_MORALIS_TX,
                    block_number: undefined,
                    blockNumber: '18000000',
                    block_timestamp: undefined,
                    blockTimestamp: '2023-09-01T12:00:00.000Z',
                    to_address: undefined,
                    toAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD1E',
                    from_address: undefined,
                    fromAddress: '0x388C818CA8B9251b393131C08a736A67ccB19297',
                    gas_price: undefined,
                    gasPrice: '20000000000',
                    receipt_gas_used: undefined,
                    receiptGasUsed: '21000'
                };
                const result = (0, moralis_utils_1.transformMoralisTransaction)(camelTx);
                (0, chai_1.expect)(result.blockHeight).to.equal(18000000);
            });
            it('should use transaction_hash for ERC20 transfers', function () {
                const erc20 = { ...MOCK_MORALIS_TX, hash: undefined, transaction_hash: '0xerc20hash' };
                const result = (0, moralis_utils_1.transformMoralisTransaction)(erc20);
                (0, chai_1.expect)(result.txid).to.equal('0xerc20hash');
            });
        });
        describe('transformMoralisInternalTx', function () {
            it('should map internal transaction fields', function () {
                const internal = {
                    from: '0x388C818CA8B9251b393131C08a736A67ccB19297',
                    to: '0x742d35Cc6634C0532925a3b844Bc9e7595f2bD1E',
                    gas: '21000',
                    gas_used: '21000',
                    input: '0x',
                    output: '0x',
                    type: 'CALL',
                    value: '1000000000000000000'
                };
                const result = (0, moralis_utils_1.transformMoralisInternalTx)(internal);
                (0, chai_1.expect)(result.type).to.equal('CALL');
                (0, chai_1.expect)(result.value).to.equal('1000000000000000000');
            });
        });
        describe('transformMoralisTokenTransfer', function () {
            it('should extend base transaction with token fields', function () {
                const transfer = {
                    ...MOCK_MORALIS_TX,
                    transaction_hash: MOCK_MORALIS_TX.hash,
                    contract_address: '0xtokencontract',
                    token_name: 'USDC'
                };
                const result = (0, moralis_utils_1.transformMoralisTokenTransfer)(transfer);
                (0, chai_1.expect)(result.contractAddress).to.equal('0xtokencontract');
                (0, chai_1.expect)(result.name).to.equal('USDC');
            });
        });
        describe('formatMoralisChainId', function () {
            it('should pass through hex chainId unchanged', function () {
                (0, chai_1.expect)((0, moralis_utils_1.formatMoralisChainId)('0x1')).to.equal('0x1');
            });
            it('should convert decimal string to hex', function () {
                (0, chai_1.expect)((0, moralis_utils_1.formatMoralisChainId)('137')).to.equal('0x89');
            });
            it('should convert bigint to hex', function () {
                (0, chai_1.expect)((0, moralis_utils_1.formatMoralisChainId)(BigInt(1))).to.equal('0x1');
            });
            it('should throw for invalid chainId', function () {
                (0, chai_1.expect)(() => (0, moralis_utils_1.formatMoralisChainId)('not-a-number')).to.throw();
            });
        });
        describe('buildMoralisQueryString', function () {
            it('should build key=value pairs', function () {
                const qs = (0, moralis_utils_1.buildMoralisQueryString)({ chain: '0x1', limit: 10 });
                (0, chai_1.expect)(qs).to.equal('?chain=0x1&limit=10');
            });
            it('should encode array values', function () {
                const qs = (0, moralis_utils_1.buildMoralisQueryString)({ contract_addresses: ['0xA', '0xB'] });
                (0, chai_1.expect)(qs).to.include('contract_addresses%5B0%5D=0xA');
                (0, chai_1.expect)(qs).to.include('contract_addresses%5B1%5D=0xB');
            });
            it('should skip null/undefined values', function () {
                const qs = (0, moralis_utils_1.buildMoralisQueryString)({ chain: '0x1', extra: null });
                (0, chai_1.expect)(qs).to.equal('?chain=0x1');
            });
            it('should return empty string for no params', function () {
                (0, chai_1.expect)((0, moralis_utils_1.buildMoralisQueryString)({})).to.equal('');
            });
        });
        describe('transformMoralisQueryParams', function () {
            it('should add block range when startBlock/endBlock present', function () {
                const result = (0, moralis_utils_1.transformMoralisQueryParams)({ chainId: '1', args: { startBlock: 100, endBlock: 200 } });
                (0, chai_1.expect)(result.from_block).to.equal(100);
                (0, chai_1.expect)(result.to_block).to.equal(200);
            });
            it('should add date range when no block range', function () {
                const result = (0, moralis_utils_1.transformMoralisQueryParams)({ chainId: '1', args: { startDate: '2023-01-01', endDate: '2023-12-31' } });
                (0, chai_1.expect)(result.from_date).to.equal('2023-01-01');
                (0, chai_1.expect)(result.to_date).to.equal('2023-12-31');
            });
            it('should convert positive direction to ASC', function () {
                const result = (0, moralis_utils_1.transformMoralisQueryParams)({ chainId: '1', args: { direction: 1 } });
                (0, chai_1.expect)(result.order).to.equal('ASC');
            });
            it('should convert negative direction to DESC', function () {
                const result = (0, moralis_utils_1.transformMoralisQueryParams)({ chainId: '1', args: { direction: -1 } });
                (0, chai_1.expect)(result.order).to.equal('DESC');
            });
        });
    });
});
//# sourceMappingURL=moralis.test.js.map