import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY, } from "@solana/web3.js";
import { isBytes, parseTokenTransferVaa, } from "../../vaa";
import { deriveClaimKey, derivePostedVaaKey, getWormholeDerivedAccounts, } from "../wormhole";
import { deriveAuthoritySignerKey, deriveCustodyKey, deriveCustodySignerKey, deriveEndpointKey, deriveMintAuthorityKey, deriveRedeemerAccountKey, deriveSenderAccountKey, deriveTokenBridgeConfigKey, deriveWrappedMetaKey, deriveWrappedMintKey, } from "./accounts";
import { getTransferNativeWithPayloadAccounts, getTransferWrappedWithPayloadAccounts, } from "./instructions";
/**
 * Generate Token Bridge PDAs.
 *
 * @param cpiProgramId
 * @param tokenBridgeProgramId
 * @param wormholeProgramId
 * @returns
 */
export function getTokenBridgeDerivedAccounts(cpiProgramId, tokenBridgeProgramId, wormholeProgramId) {
    var _a = getWormholeDerivedAccounts(tokenBridgeProgramId, wormholeProgramId), tokenBridgeEmitter = _a.wormholeEmitter, wormholeBridge = _a.wormholeBridge, wormholeFeeCollector = _a.wormholeFeeCollector, tokenBridgeSequence = _a.wormholeSequence;
    return {
        tokenBridgeConfig: deriveTokenBridgeConfigKey(tokenBridgeProgramId),
        tokenBridgeAuthoritySigner: deriveAuthoritySignerKey(tokenBridgeProgramId),
        tokenBridgeCustodySigner: deriveCustodySignerKey(tokenBridgeProgramId),
        tokenBridgeMintAuthority: deriveMintAuthorityKey(tokenBridgeProgramId),
        tokenBridgeSender: deriveSenderAccountKey(cpiProgramId),
        tokenBridgeRedeemer: deriveRedeemerAccountKey(cpiProgramId),
        wormholeBridge: wormholeBridge,
        tokenBridgeEmitter: tokenBridgeEmitter,
        wormholeFeeCollector: wormholeFeeCollector,
        tokenBridgeSequence: tokenBridgeSequence,
    };
}
/**
 * Generate accounts needed to perform `transfer_wrapped_with_payload` instruction
 * as cross-program invocation.
 *
 * @param cpiProgramId
 * @param tokenBridgeProgramId
 * @param wormholeProgramId
 * @param payer
 * @param message
 * @param fromTokenAccount
 * @param mint
 * @returns
 */
export function getTransferNativeWithPayloadCpiAccounts(cpiProgramId, tokenBridgeProgramId, wormholeProgramId, payer, message, fromTokenAccount, mint) {
    var accounts = getTransferNativeWithPayloadAccounts(tokenBridgeProgramId, wormholeProgramId, payer, message, fromTokenAccount, mint, cpiProgramId);
    return {
        payer: accounts.payer,
        tokenBridgeConfig: accounts.config,
        fromTokenAccount: accounts.from,
        mint: accounts.mint,
        tokenBridgeCustody: accounts.custody,
        tokenBridgeAuthoritySigner: accounts.authoritySigner,
        tokenBridgeCustodySigner: accounts.custodySigner,
        wormholeBridge: accounts.wormholeBridge,
        wormholeMessage: accounts.wormholeMessage,
        tokenBridgeEmitter: accounts.wormholeEmitter,
        tokenBridgeSequence: accounts.wormholeSequence,
        wormholeFeeCollector: accounts.wormholeFeeCollector,
        clock: accounts.clock,
        tokenBridgeSender: accounts.sender,
        rent: accounts.rent,
        systemProgram: accounts.systemProgram,
        tokenProgram: accounts.tokenProgram,
        wormholeProgram: accounts.wormholeProgram,
    };
}
/**
 * Generate accounts needed to perform `transfer_wrapped_with_payload` instruction
 * as cross-program invocation.
 *
 * @param cpiProgramId
 * @param tokenBridgeProgramId
 * @param wormholeProgramId
 * @param payer
 * @param message
 * @param fromTokenAccount
 * @param tokenChain
 * @param tokenAddress
 * @param [fromTokenAccountOwner]
 * @returns
 */
export function getTransferWrappedWithPayloadCpiAccounts(cpiProgramId, tokenBridgeProgramId, wormholeProgramId, payer, message, fromTokenAccount, tokenChain, tokenAddress, fromTokenAccountOwner) {
    var accounts = getTransferWrappedWithPayloadAccounts(tokenBridgeProgramId, wormholeProgramId, payer, message, fromTokenAccount, fromTokenAccountOwner === undefined ? cpiProgramId : fromTokenAccountOwner, tokenChain, tokenAddress, cpiProgramId);
    return {
        payer: accounts.payer,
        tokenBridgeConfig: accounts.config,
        fromTokenAccount: accounts.from,
        fromTokenAccountOwner: accounts.fromOwner,
        tokenBridgeWrappedMint: accounts.mint,
        tokenBridgeWrappedMeta: accounts.wrappedMeta,
        tokenBridgeAuthoritySigner: accounts.authoritySigner,
        wormholeBridge: accounts.wormholeBridge,
        wormholeMessage: accounts.wormholeMessage,
        tokenBridgeEmitter: accounts.wormholeEmitter,
        tokenBridgeSequence: accounts.wormholeSequence,
        wormholeFeeCollector: accounts.wormholeFeeCollector,
        clock: accounts.clock,
        tokenBridgeSender: accounts.sender,
        rent: accounts.rent,
        systemProgram: accounts.systemProgram,
        tokenProgram: accounts.tokenProgram,
        wormholeProgram: accounts.wormholeProgram,
    };
}
/**
 * Generate accounts needed to perform `complete_native_with_payload` instruction
 * as cross-program invocation.
 *
 * Note: `toFeesTokenAccount` is the same as `toTokenAccount`. For your program,
 * you only need to pass your `toTokenAccount` into the complete transfer
 * instruction for the `toFeesTokenAccount`.
 *
 * @param cpiProgramId
 * @param tokenBridgeProgramId
 * @param wormholeProgramId
 * @param payer
 * @param vaa
 * @returns
 */
export function getCompleteTransferNativeWithPayloadCpiAccounts(cpiProgramId, tokenBridgeProgramId, wormholeProgramId, payer, vaa) {
    var parsed = isBytes(vaa) ? parseTokenTransferVaa(vaa) : vaa;
    var mint = new PublicKey(parsed.tokenAddress);
    var toTokenAccount = new PublicKey(parsed.to);
    return {
        payer: new PublicKey(payer),
        tokenBridgeConfig: deriveTokenBridgeConfigKey(tokenBridgeProgramId),
        vaa: derivePostedVaaKey(wormholeProgramId, parsed.hash),
        tokenBridgeClaim: deriveClaimKey(tokenBridgeProgramId, parsed.emitterAddress, parsed.emitterChain, parsed.sequence),
        tokenBridgeForeignEndpoint: deriveEndpointKey(tokenBridgeProgramId, parsed.emitterChain, parsed.emitterAddress),
        toTokenAccount: toTokenAccount,
        tokenBridgeRedeemer: deriveRedeemerAccountKey(cpiProgramId),
        toFeesTokenAccount: toTokenAccount,
        tokenBridgeCustody: deriveCustodyKey(tokenBridgeProgramId, mint),
        mint: mint,
        tokenBridgeCustodySigner: deriveCustodySignerKey(tokenBridgeProgramId),
        rent: SYSVAR_RENT_PUBKEY,
        systemProgram: SystemProgram.programId,
        tokenProgram: TOKEN_PROGRAM_ID,
        wormholeProgram: new PublicKey(wormholeProgramId),
    };
}
/**
 * Generate accounts needed to perform `complete_wrapped_with_payload` instruction
 * as cross-program invocation.
 *
 * Note: `toFeesTokenAccount` is the same as `toTokenAccount`. For your program,
 * you only need to pass your `toTokenAccount` into the complete transfer
 * instruction for the `toFeesTokenAccount`.
 *
 * @param cpiProgramId
 * @param tokenBridgeProgramId
 * @param wormholeProgramId
 * @param payer
 * @param vaa
 * @returns
 */
export function getCompleteTransferWrappedWithPayloadCpiAccounts(cpiProgramId, tokenBridgeProgramId, wormholeProgramId, payer, vaa) {
    var parsed = isBytes(vaa) ? parseTokenTransferVaa(vaa) : vaa;
    var mint = deriveWrappedMintKey(tokenBridgeProgramId, parsed.tokenChain, parsed.tokenAddress);
    var toTokenAccount = new PublicKey(parsed.to);
    return {
        payer: new PublicKey(payer),
        tokenBridgeConfig: deriveTokenBridgeConfigKey(tokenBridgeProgramId),
        vaa: derivePostedVaaKey(wormholeProgramId, parsed.hash),
        tokenBridgeClaim: deriveClaimKey(tokenBridgeProgramId, parsed.emitterAddress, parsed.emitterChain, parsed.sequence),
        tokenBridgeForeignEndpoint: deriveEndpointKey(tokenBridgeProgramId, parsed.emitterChain, parsed.emitterAddress),
        toTokenAccount: toTokenAccount,
        tokenBridgeRedeemer: deriveRedeemerAccountKey(cpiProgramId),
        toFeesTokenAccount: toTokenAccount,
        tokenBridgeWrappedMint: mint,
        tokenBridgeWrappedMeta: deriveWrappedMetaKey(tokenBridgeProgramId, mint),
        tokenBridgeMintAuthority: deriveMintAuthorityKey(tokenBridgeProgramId),
        rent: SYSVAR_RENT_PUBKEY,
        systemProgram: SystemProgram.programId,
        tokenProgram: TOKEN_PROGRAM_ID,
        wormholeProgram: new PublicKey(wormholeProgramId),
    };
}
