import { address as parseAddress } from '@solana/kit';
import { HookType } from '@hyperlane-xyz/provider-sdk/altvm';
import { throwUnsupportedHookType, } from '@hyperlane-xyz/provider-sdk/hook';
import { assert } from '@hyperlane-xyz/utils';
import { HYPERLANE_SVM_PROGRAM_BYTES } from '../hyperlane/program-bytes.js';
import { detectHookType } from './hook-query.js';
import { DEFAULT_IGP_SALT, SvmIgpHookReader, SvmIgpHookWriter, } from './igp-hook.js';
import { SvmMerkleTreeHookReader, SvmMerkleTreeHookWriter, } from './merkle-tree-hook.js';
export class SvmHookArtifactManager {
    rpc;
    mailboxAddress;
    salt;
    constructor(rpc, mailboxAddress, salt = DEFAULT_IGP_SALT) {
        this.rpc = rpc;
        this.mailboxAddress = mailboxAddress;
        this.salt = salt;
    }
    async readHook(address) {
        const addr = parseAddress(address);
        const hookType = await detectHookType(this.rpc, addr);
        if (hookType !== null) {
            return this.createReader(this.altVmToTypeKey(hookType)).read(address);
        }
        // The only other supported hook on SVM is the merkle tree hook, which IS
        // the mailbox program. Validate the address matches before assuming.
        assert(this.mailboxAddress, 'Mailbox address is required to detect merkle tree hooks on SVM');
        assert(addr === this.mailboxAddress, `Unknown hook address ${address}: not an IGP program; expected the configured mailbox (${this.mailboxAddress}) for Merkle detection`);
        return this.createReader('merkleTreeHook').read(address);
    }
    createReader(type) {
        const readers = {
            merkleTreeHook: () => new SvmMerkleTreeHookReader(this.rpc),
            interchainGasPaymaster: () => new SvmIgpHookReader(this.rpc, this.salt),
        };
        const factory = readers[type];
        if (!factory) {
            return throwUnsupportedHookType(type, 'Sealevel');
        }
        return factory();
    }
    createWriter(type, signer) {
        const writers = {
            merkleTreeHook: () => {
                assert(this.mailboxAddress, 'Mailbox address is required to create a merkle tree hook writer on SVM');
                return new SvmMerkleTreeHookWriter({ mailboxAddress: this.mailboxAddress }, this.rpc, signer);
            },
            interchainGasPaymaster: () => new SvmIgpHookWriter({ program: { programBytes: HYPERLANE_SVM_PROGRAM_BYTES.igp } }, this.rpc, this.salt, signer),
        };
        const factory = writers[type];
        if (!factory) {
            return throwUnsupportedHookType(type, 'Sealevel');
        }
        return factory();
    }
    altVmToTypeKey(hookType) {
        switch (hookType) {
            case HookType.MERKLE_TREE:
                return 'merkleTreeHook';
            case HookType.INTERCHAIN_GAS_PAYMASTER:
                return 'interchainGasPaymaster';
            default:
                throw new Error(`Unsupported hook type on Solana: ${hookType}`);
        }
    }
}
//# sourceMappingURL=hook-artifact-manager.js.map