import { expect } from 'chai';
import { before, describe, it } from 'mocha';
import { HookType } from '@hyperlane-xyz/provider-sdk/altvm';
import { ArtifactState, } from '@hyperlane-xyz/provider-sdk/artifact';
import { SvmSigner } from '../clients/signer.js';
import { SvmHookArtifactManager } from '../hook/hook-artifact-manager.js';
import { SvmIgpHookReader, SvmIgpHookWriter, deriveIgpSalt, } from '../hook/igp-hook.js';
import { SvmMerkleTreeHookReader, SvmMerkleTreeHookWriter, } from '../hook/merkle-tree-hook.js';
import { createRpc } from '../rpc.js';
import { TEST_SVM_CHAIN_METADATA } from '../testing/constants.js';
import { TEST_PROGRAM_IDS, airdropSol } from '../testing/setup.js';
import { address } from '@solana/kit';
const TEST_PRIVATE_KEY = '0x0000000000000000000000000000000000000000000000000000000000000001';
describe('SVM Hook E2E Tests', function () {
    this.timeout(180_000);
    let rpc;
    let signer;
    before(async () => {
        rpc = createRpc(TEST_SVM_CHAIN_METADATA.rpcUrl);
        signer = await SvmSigner.connectWithSigner([TEST_SVM_CHAIN_METADATA.rpcUrl], TEST_PRIVATE_KEY);
        await airdropSol(rpc, address(signer.getSignerAddress()));
    });
    describe('Merkle Tree Hook', () => {
        it('should create and read Merkle Tree Hook (returns mailbox address)', async () => {
            const writer = new SvmMerkleTreeHookWriter({ mailboxAddress: TEST_PROGRAM_IDS.mailbox }, rpc, signer);
            const [deployed, receipts] = await writer.create({
                artifactState: ArtifactState.NEW,
                config: { type: HookType.MERKLE_TREE },
            });
            expect(receipts).to.have.length(0);
            expect(deployed.artifactState).to.equal(ArtifactState.DEPLOYED);
            expect(deployed.config.type).to.equal(HookType.MERKLE_TREE);
            expect(deployed.deployed.address).to.equal(TEST_PROGRAM_IDS.mailbox);
            expect(deployed.deployed.programId).to.equal(TEST_PROGRAM_IDS.mailbox);
            const reader = new SvmMerkleTreeHookReader(rpc);
            const readResult = await reader.read(TEST_PROGRAM_IDS.mailbox);
            expect(readResult.artifactState).to.equal(ArtifactState.DEPLOYED);
            expect(readResult.config.type).to.equal(HookType.MERKLE_TREE);
        });
        it('should return empty transactions for update', async () => {
            const writer = new SvmMerkleTreeHookWriter({ mailboxAddress: TEST_PROGRAM_IDS.mailbox }, rpc, signer);
            const artifact = {
                artifactState: ArtifactState.DEPLOYED,
                config: { type: HookType.MERKLE_TREE },
                deployed: {
                    address: TEST_PROGRAM_IDS.mailbox,
                    programId: TEST_PROGRAM_IDS.mailbox,
                },
            };
            const updateTxs = await writer.update(artifact);
            expect(updateTxs).to.have.length(0);
        });
    });
    describe('IGP Hook', () => {
        it('should create and read IGP Hook with gas oracle configs', async function () {
            const salt = deriveIgpSalt('hyperlane-test');
            const writer = new SvmIgpHookWriter({ program: { programId: TEST_PROGRAM_IDS.igp } }, rpc, salt, signer);
            const igpConfig = {
                type: HookType.INTERCHAIN_GAS_PAYMASTER,
                owner: signer.getSignerAddress(),
                beneficiary: signer.getSignerAddress(),
                oracleKey: signer.getSignerAddress(),
                oracleConfig: {
                    1: {
                        gasPrice: '50000000000',
                        tokenExchangeRate: '1000000000000000000',
                    },
                    137: {
                        gasPrice: '100000000000',
                        tokenExchangeRate: '500000000000000000',
                    },
                },
                overhead: {
                    1: 100000,
                    137: 80000,
                },
            };
            const [deployed, receipts] = await writer.create({
                artifactState: ArtifactState.NEW,
                config: igpConfig,
            });
            expect(receipts).to.have.length.greaterThan(0);
            expect(deployed.artifactState).to.equal(ArtifactState.DEPLOYED);
            expect(deployed.config.type).to.equal(HookType.INTERCHAIN_GAS_PAYMASTER);
            expect(deployed.deployed.programId).to.equal(TEST_PROGRAM_IDS.igp);
            const reader = new SvmIgpHookReader(rpc, salt);
            const readResult = await reader.read(TEST_PROGRAM_IDS.igp);
            expect(readResult.artifactState).to.equal(ArtifactState.DEPLOYED);
            expect(readResult.config.type).to.equal(HookType.INTERCHAIN_GAS_PAYMASTER);
        });
        it('should generate update transactions for config changes', async function () {
            const salt = deriveIgpSalt('hyperlane-update-test');
            const writer = new SvmIgpHookWriter({ program: { programId: TEST_PROGRAM_IDS.igp } }, rpc, salt, signer);
            const updateConfig = {
                type: HookType.INTERCHAIN_GAS_PAYMASTER,
                owner: signer.getSignerAddress(),
                beneficiary: signer.getSignerAddress(),
                oracleKey: signer.getSignerAddress(),
                oracleConfig: {
                    1: {
                        gasPrice: '50000000000',
                        tokenExchangeRate: '1000000000000000000',
                    },
                },
                overhead: {
                    1: 100000,
                },
            };
            const [deployed] = await writer.create({
                artifactState: ArtifactState.NEW,
                config: updateConfig,
            });
            const updateTxs = await writer.update({
                ...deployed,
                config: {
                    ...deployed.config,
                    oracleConfig: {
                        ...deployed.config.oracleConfig,
                        42161: {
                            gasPrice: '100000000',
                            tokenExchangeRate: '1000000000000000000',
                        },
                    },
                    overhead: {
                        ...deployed.config.overhead,
                        42161: 50000,
                    },
                },
            });
            expect(updateTxs).to.have.length.greaterThan(0);
            expect(updateTxs[0].annotation).to.include('oracle');
        });
    });
    describe('Hook Artifact Manager', () => {
        it('should detect hook type from address', async () => {
            const manager = new SvmHookArtifactManager(rpc, TEST_PROGRAM_IDS.mailbox);
            const merkleHookArtifact = await manager.readHook(TEST_PROGRAM_IDS.mailbox);
            expect(merkleHookArtifact.config.type).to.equal(HookType.MERKLE_TREE);
        });
        it('should create readers for different hook types', () => {
            const manager = new SvmHookArtifactManager(rpc, TEST_PROGRAM_IDS.mailbox);
            const merkleReader = manager.createReader(HookType.MERKLE_TREE);
            expect(merkleReader).to.be.instanceOf(SvmMerkleTreeHookReader);
            const igpReader = manager.createReader(HookType.INTERCHAIN_GAS_PAYMASTER);
            expect(igpReader).to.be.instanceOf(SvmIgpHookReader);
        });
        it('should create writers for different hook types', () => {
            const manager = new SvmHookArtifactManager(rpc, TEST_PROGRAM_IDS.mailbox);
            const merkleWriter = manager.createWriter(HookType.MERKLE_TREE, signer);
            expect(merkleWriter).to.be.instanceOf(SvmMerkleTreeHookWriter);
            const igpWriter = manager.createWriter(HookType.INTERCHAIN_GAS_PAYMASTER, signer);
            expect(igpWriter).to.be.instanceOf(SvmIgpHookWriter);
        });
    });
});
//# sourceMappingURL=hook.e2e-test.js.map