"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 });
exports.common = void 0;
const anchor = __importStar(require("@coral-xyz/anchor"));
const anchor_1 = require("@coral-xyz/anchor");
const web3_js_1 = require("@solana/web3.js");
const ethers_1 = require("ethers");
const spl_token_1 = require("@solana/spl-token");
const SvmUtils_1 = require("../../src/SvmUtils");
const chai_1 = require("chai");
const provider = anchor.AnchorProvider.env();
const program = anchor.workspace.SvmSpoke;
const owner = provider.wallet.publicKey;
const chainId = new anchor_1.BN(420);
const remoteDomain = new anchor_1.BN(0); // Ethereum
const localDomain = 5; // Solana
const crossDomainAdmin = (0, SvmUtils_1.evmAddressToPublicKey)(ethers_1.ethers.Wallet.createRandom().address);
const seedBalance = 20000000;
const destinationChainId = new anchor_1.BN(1);
const recipient = web3_js_1.Keypair.generate().publicKey;
const exclusiveRelayer = web3_js_1.Keypair.generate().publicKey;
const outputToken = new web3_js_1.PublicKey("1111111111113EsMD5n1VA94D2fALdb1SAKLam8j"); // TODO: this is lazy. this is cast USDC from Eth mainnet.
const inputAmount = new anchor_1.BN(500000);
const outputAmount = inputAmount;
const quoteTimestamp = new anchor_1.BN(Math.floor(Date.now() / 1000) - 60); // 60 seconds ago.
const fillDeadline = new anchor_1.BN(Math.floor(Date.now() / 1000) + 600); // 600 seconds from now.
const exclusivityPeriod = new anchor_1.BN(300); // 300 seconds.
const message = Buffer.from("Test message");
const depositQuoteTimeBuffer = new anchor_1.BN(3600); // 1 hour.
const fillDeadlineBuffer = new anchor_1.BN(3600 * 4); // 4 hours.
const initializeState = async (seed, initialState) => {
    const actualSeed = seed || new anchor_1.BN(Math.floor(Math.random() * 1000000));
    const seeds = [Buffer.from("state"), actualSeed.toArrayLike(Buffer, "le", 8)];
    const [state] = web3_js_1.PublicKey.findProgramAddressSync(seeds, program.programId);
    if (!initialState) {
        initialState = {
            initialNumberOfDeposits: new anchor_1.BN(0),
            chainId,
            remoteDomain,
            crossDomainAdmin,
            depositQuoteTimeBuffer,
            fillDeadlineBuffer,
        };
    }
    const initializeAccounts = { state: state, signer: owner, systemProgram: anchor.web3.SystemProgram.programId };
    await program.methods
        .initialize(actualSeed, initialState.initialNumberOfDeposits.toNumber(), initialState.chainId, initialState.remoteDomain.toNumber(), initialState.crossDomainAdmin, initialState.depositQuoteTimeBuffer.toNumber(), initialState.fillDeadlineBuffer.toNumber())
        .accounts(initializeAccounts)
        .rpc();
    return state;
};
const createRoutePda = (originToken, state, routeChainId) => {
    return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("route"), originToken.toBytes(), state.toBytes(), routeChainId.toArrayLike(Buffer, "le", 8)], program.programId)[0];
};
const getVaultAta = (tokenMint, state) => {
    return (0, spl_token_1.getAssociatedTokenAddressSync)(tokenMint, state, true, spl_token_1.TOKEN_PROGRAM_ID, spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID);
};
async function setCurrentTime(program, state, signer, newTime) {
    let setCurrentTimeAccounts = { state, signer: signer.publicKey };
    await program.methods.setCurrentTime(newTime.toNumber()).accounts(setCurrentTimeAccounts).signers([signer]).rpc();
}
async function getCurrentTime(program, state) {
    return (await program.account.state.fetch(state)).currentTime;
}
function assertSE(a, b, errorMessage) {
    if (a === undefined || b === undefined) {
        throw new Error("Undefined value" + errorMessage);
    }
    else {
        chai_1.assert.strictEqual(a.toString(), b.toString(), errorMessage);
    }
}
exports.common = {
    provider,
    connection: provider.connection,
    program,
    owner,
    chainId,
    remoteDomain,
    localDomain,
    crossDomainAdmin,
    seedBalance,
    destinationChainId,
    recipient,
    exclusiveRelayer,
    outputToken,
    inputAmount,
    outputAmount,
    quoteTimestamp,
    fillDeadline,
    exclusivityPeriod,
    message,
    depositQuoteTimeBuffer,
    fillDeadlineBuffer,
    initializeState,
    createRoutePda,
    getVaultAta,
    setCurrentTime,
    getCurrentTime,
    assert: chai_1.assert,
    assertSE,
    depositData: {
        depositor: null, // Placeholder, to be assigned in the test file
        recipient,
        inputToken: null, // Placeholder, to be assigned in the test file
        outputToken,
        inputAmount,
        outputAmount,
        destinationChainId,
        exclusiveRelayer,
        quoteTimestamp,
        fillDeadline,
        exclusivityPeriod,
        message,
    },
};
