"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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const anchor = __importStar(require("@coral-xyz/anchor"));
const anchor_1 = require("@coral-xyz/anchor");
const spl_token_1 = require("@solana/spl-token");
const web3_js_1 = require("@solana/web3.js");
const chai_1 = require("chai");
const SvmSpoke_common_1 = require("./SvmSpoke.common");
const web3_v1_1 = require("../../src/svm/web3-v1");
const { provider, program, owner, initializeState, createRoutePda, getVaultAta } = SvmSpoke_common_1.common;
describe("svm_spoke.routes", () => {
    anchor.setProvider(provider);
    const nonOwner = web3_js_1.Keypair.generate();
    let state, seed, tokenMint, routePda, vault;
    let routeChainId;
    let setEnableRouteAccounts;
    beforeEach(async () => {
        ({ state, seed } = await initializeState());
        tokenMint = await (0, spl_token_1.createMint)(provider.connection, provider.wallet.payer, owner, owner, 6);
        // Create a PDA for the route
        routeChainId = new anchor_1.BN(1);
        routePda = createRoutePda(tokenMint, seed, routeChainId);
        // Create ATA for the origin token to be stored by state (vault).
        vault = await getVaultAta(tokenMint, state);
        // Common accounts object
        setEnableRouteAccounts = {
            signer: owner,
            payer: owner,
            state,
            route: routePda,
            vault: vault,
            originTokenMint: tokenMint,
            tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
            associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
            systemProgram: anchor.web3.SystemProgram.programId,
        };
    });
    it("Sets, retrieves, and controls access to route enablement", async () => {
        // Enable the route as owner
        const tx = await program.methods
            .setEnableRoute(tokenMint, routeChainId, true)
            .accounts(setEnableRouteAccounts)
            .rpc();
        // Retrieve and verify the route is enabled
        let routeAccount = await program.account.route.fetch(routePda);
        chai_1.assert.isTrue(routeAccount.enabled, "Route should be enabled");
        // Verify the enabledDepositRoute event
        let events = await (0, web3_v1_1.readEventsUntilFound)(provider.connection, tx, [program]);
        let event = events[0].data;
        chai_1.assert.strictEqual(event.originToken.toString(), tokenMint.toString(), "originToken event match");
        chai_1.assert.strictEqual(event.destinationChainId.toString(), routeChainId.toString(), "destinationChainId should match");
        chai_1.assert.isTrue(event.enabled, "enabledDepositRoute enabled");
        // Disable the route as owner
        const tx2 = await program.methods
            .setEnableRoute(tokenMint, routeChainId, false)
            .accounts(setEnableRouteAccounts)
            .rpc();
        // Retrieve and verify the route is disabled
        routeAccount = await program.account.route.fetch(routePda);
        chai_1.assert.isFalse(routeAccount.enabled, "Route should be disabled");
        // Verify the enabledDepositRoute event
        events = await (0, web3_v1_1.readEventsUntilFound)(provider.connection, tx2, [program]);
        event = events[0].data; // take most recent event, index 0.
        chai_1.assert.strictEqual(event.originToken.toString(), tokenMint.toString(), "originToken event match");
        chai_1.assert.strictEqual(event.destinationChainId.toString(), routeChainId.toString(), "destinationChainId should match");
        chai_1.assert.isFalse(event.enabled, "enabledDepositRoute disabled");
        // Try to enable the route as non-owner
        try {
            await program.methods
                .setEnableRoute(tokenMint, routeChainId, true)
                .accounts({ ...setEnableRouteAccounts, signer: nonOwner.publicKey })
                .signers([nonOwner])
                .rpc();
            chai_1.assert.fail("Non-owner should not be able to set route enablement");
        }
        catch (err) {
            chai_1.assert.include(err.toString(), "Only the owner can call this function!", "Expected owner check error");
        }
        // Verify the route is still disabled after non-owner attempt
        routeAccount = await program.account.route.fetch(routePda);
        chai_1.assert.isFalse(routeAccount.enabled, "Route should still be disabled after non-owner attempt");
        // Verify the owner of the vault is the state
        const vaultAccount = await (0, spl_token_1.getAccount)(provider.connection, vault);
        chai_1.assert.strictEqual(vaultAccount.owner.toBase58(), state.toBase58(), "Vault owner should be the state");
        // Verify the owner of the state is the expected owner
        const stateAccount = await program.account.state.fetch(state);
        chai_1.assert.strictEqual(stateAccount.owner.toBase58(), owner.toBase58(), "State owner should be the expected owner");
    });
    it("Cannot misconfigure route with wrong origin token", async () => {
        const wrongOriginToken = web3_js_1.Keypair.generate().publicKey;
        const wrongRoutePda = createRoutePda(wrongOriginToken, seed, routeChainId);
        try {
            await program.methods
                .setEnableRoute(wrongOriginToken, routeChainId, true)
                .accounts({ ...setEnableRouteAccounts, route: wrongRoutePda })
                .rpc();
            chai_1.assert.fail("Setting route with wrong origin token should fail");
        }
        catch (err) {
            chai_1.assert.instanceOf(err, anchor.AnchorError);
            chai_1.assert.strictEqual(err.error.errorCode.code, "InvalidMint", "Expected error code InvalidMint");
        }
    });
});
