# farm/v1.ts

    import { ethers } from "ethers";
    import {
      CallbackType,
      getContract,
      getContractAddressAndAbiByContractName,
      viewContract,
      triggerContract,
    } from "@evo/utils/ethers/contractHelper";
    import { viewContractByContractName } from "@evo/utils/ethers/contractHelper";
    import { LandId } from "@evo/config/constants";
    import { TransactionResponse } from "@ethersproject/providers";

    /**
     * Get staker contract address by staking token
     * @param landId Land Id
     * @param provider Provider
     * @param stakingToken Staking token contract address
     * @param callback Callback
     * @returns any
     */
    export const farmGetStakerAddress = async (
      landId: LandId,
      provider: ethers.providers.Provider,
      stakingToken: string,
      callback?: CallbackType
    ): Promise<string> => {
      const result = await viewContractByContractName(
        landId,
        provider,
        "liquidityStakerFactory",
        "stakingRewardsInfoByStakingToken",
        [stakingToken],
        callback
      );
      return result.toString();
    };

    /**
     * Get the amount of staking token
     * @param landId Land Id
     * @param provider Provider
     * @param stakerContractAddress Contract address of staker
     * @param callback Callback
     * @returns any
     */
    export const farmGetStakerTotalSupply = async (
      landId: LandId,
      provider: ethers.providers.Provider,
      stakerContractAddress: string,
      callback?: CallbackType
    ): Promise<string> => {
      const liquidityStaker = getContractAddressAndAbiByContractName(landId, provider, "liquidityStaker");
      if (!liquidityStaker.interface) return "0";
      const contract = await getContract(provider, stakerContractAddress, liquidityStaker.interface);
      const result = await viewContract(contract, "totalSupply", [], callback);
      return result.toString();
    };

    /**
     * Get the amount of staking token for a specific address
     * @param landId Land Id
     * @param provider Provider
     * @param stakerContractAddress Contract address of staker
     * @param account Address
     * @param callback Callback
     * @returns any
     */
    export const farmGetStakerBalanceOf = async (
      landId: LandId,
      provider: ethers.providers.Provider,
      stakerContractAddress: string,
      account: string,
      callback?: CallbackType
    ): Promise<string> => {
      const liquidityStaker = getContractAddressAndAbiByContractName(landId, provider, "liquidityStaker");
      if (!liquidityStaker.interface) return "0";
      const contract = await getContract(provider, stakerContractAddress, liquidityStaker.interface);
      const result = await viewContract(contract, "balanceOf", [account], callback);
      return result.toString();
    };

    /**
     * Get the amount of token already earned
     * @param landId Land Id
     * @param provider Provider
     * @param stakerContractAddress Contract address of staker
     * @param account Address
     * @param callback Callback
     * @returns any
     */
    export const farmGetStakerEarned = async (
      landId: LandId,
      provider: ethers.providers.Provider,
      stakerContractAddress: string,
      account: string,
      callback?: CallbackType
    ): Promise<string> => {
      const liquidityStaker = getContractAddressAndAbiByContractName(landId, provider, "liquidityStaker");
      if (!liquidityStaker.interface) return "0";
      const contract = await getContract(provider, stakerContractAddress, liquidityStaker.interface);
      const result = await viewContract(contract, "earned", [account], callback);
      return result.toString();
    };

    /**
     * Stake token to staker contract
     * @param landId Land Id
     * @param signer Signer
     * @param stakerContractAddress Staker contract address
     * @param amount Stake amount
     * @param callback Callback
     * @returns any
     */
    export const farmGetStakerStakeToken = async (
      landId: LandId,
      signer: ethers.Signer,
      stakerContractAddress: string,
      amount: string,
      callback?: CallbackType
    ): Promise<TransactionResponse> => {
      const liquidityStaker = getContractAddressAndAbiByContractName(landId, signer, "liquidityStaker");
      const contract = await getContract(signer, stakerContractAddress, liquidityStaker.interface);
      const tx = await triggerContract(contract, "stake", [amount], callback);
      return tx;
    };

    /**
     * Withdraw token from staker contract
     * @param landId Land Id
     * @param signer Signer
     * @param stakerContractAddress Staker contract address
     * @param amount Withdraw amount
     * @param callback Callback
     * @returns any
     */
    export const farmStakerWithdraw = async (
      landId: LandId,
      signer: ethers.Signer,
      stakerContractAddress: string,
      amount: string,
      callback?: CallbackType
    ): Promise<TransactionResponse> => {
      const liquidityStaker = getContractAddressAndAbiByContractName(landId, signer, "liquidityStaker");
      const contract = await getContract(signer, stakerContractAddress, liquidityStaker.interface);
      const tx = await triggerContract(contract, "withdraw", [amount], callback);
      return tx;
    };

    /**
     * Claim reward
     * @param landId Land Id
     * @param signer Signer
     * @param stakerContractAddress Staker contract address
     * @param callback Callback
     * @returns any
     */
    export const farmGetStakerGetReward = async (
      landId: LandId,
      signer: ethers.Signer,
      stakerContractAddress: string,
      callback?: CallbackType
    ): Promise<TransactionResponse> => {
      const liquidityStaker = getContractAddressAndAbiByContractName(landId, signer, "liquidityStaker");
      const contract = await getContract(signer, stakerContractAddress, liquidityStaker.interface);
      const tx = await triggerContract(contract, "getReward", [], callback);
      return tx;
    };

    /**
     * Exit staker
     * @param landId Land Id
     * @param signer Signer
     * @param stakerContractAddress Staker contract address
     * @param callback Callback
     * @returns any
     */
    export const farmGetStakerExit = async (
      landId: LandId,
      signer: ethers.Signer,
      stakerContractAddress: string,
      callback?: CallbackType
    ): Promise<TransactionResponse> => {
      const liquidityStaker = getContractAddressAndAbiByContractName(landId, signer, "liquidityStaker");
      const contract = await getContract(signer, stakerContractAddress, liquidityStaker.interface);
      const tx = await triggerContract(contract, "exit", [], callback);
      return tx;
    };