land/v1.ts

import { ethers } from "ethers";
import { getAddressesByLandId } from "@evo/utils/ethers/addressHelper";
import { pad0xBegin } from "@evo/utils/common/utils";
import { toHexAndPadLeft, padLeft } from "@evo/utils/ethers/utils";
import { CallbackType, getContractAddressAndAbiByContractName } from "@evo/utils/ethers/contractHelper";
import { triggerContractByContractName, viewContractByContractName } from "@evo/utils/ethers/contractHelper";
import { LandId } from "@evo/config/constants";
import { TransactionResponse } from "@ethersproject/providers";

/**
 * Land Bid With Token
 * @param signer Ethers signer
 * @param landTokenId Land token id
 * @param referrer Referrer
 * @param amount Amount of price in RING token
 * @param callback Callback
 */
export const landBidWithToken = async (
  landId: LandId,
  signer: ethers.Signer,
  landTokenId: string,
  referrer: string | null,
  amount: string,
  callback?: CallbackType
): Promise<TransactionResponse> => {
  const finalReferrer =
    referrer && ethers.utils.isAddress(referrer) ? referrer : "0x0000000000000000000000000000000000000000";

  if (landId === LandId.ETHEREUM || landId === LandId._ETHEREUM) {
    const data = finalReferrer
      ? `${pad0xBegin(landTokenId)}${ethers.utils.hexZeroPad(finalReferrer, 32).slice(2)}`
      : pad0xBegin(landTokenId);

    const addresses = getAddressesByLandId(landId);
    if (!addresses || !addresses.LAND_CLOCK_AUCTION) {
      throw "address error";
    }

    return triggerContractByContractName(
      landId,
      signer,
      "ring",
      "transfer(address,uint256,bytes)",
      [addresses.LAND_CLOCK_AUCTION, amount, data],
      callback
    );
  }

  return triggerContractByContractName(
    landId,
    signer,
    "landClockAuctionV3",
    "bidWithToken",
    [pad0xBegin(landTokenId), finalReferrer, amount],
    callback
  );
};

/**
 * Land Available Resources
 * @param provider Ethers provider
 * @param tokenId Token id
 * @param resources Resources
 * @param callback Callback
 * @returns String[]
 */
export const landGetAvailableResources = async (
  landId: LandId,
  provider: ethers.providers.Provider,
  tokenId: string,
  resources: string[],
  callback?: CallbackType
): Promise<string[]> => {
  const addresses = getAddressesByLandId(landId);
  if (!addresses) {
    return [];
  }

  const finalRes = resources.length
    ? [...resources]
    : [
        addresses.ELEMENT_GOLD,
        addresses.ELEMENT_WOOD,
        addresses.ELEMENT_WATER,
        addresses.ELEMENT_FIRE,
        addresses.ELEMENT_SOIL,
      ];
  const results = await viewContractByContractName(
    landId,
    provider,
    "apostleLandResource",
    "availableLandResources",
    [pad0xBegin(tokenId), finalRes],
    callback
  );
  return results[0].map((res: ethers.BigNumber[]) => {
    return res.toString();
  });
};

/**
 * Land Batch Claim Land Resource
 * @param signer Ethers signer
 * @param tokenIds Token ids
 * @param callback Callback
 */
export const landBatchClaimLandResource = (
  landId: LandId,
  signer: ethers.Signer,
  tokenIds: string[],
  callback?: CallbackType
): Promise<TransactionResponse> => {
  return triggerContractByContractName(
    landId,
    signer,
    "apostleLandResource",
    "batchClaimLandResource",
    [tokenIds.map((tokenId) => pad0xBegin(tokenId))],
    callback
  );
};

/**
 * Returns the current price of an auction.
 * @param provider Ethers signer
 * @param tokenId Token Id
 * @param callback Callback
 * @returns any
 */
export const landGetCurrentPriceByTokenId = async (
  landId: LandId,
  provider: ethers.providers.Provider,
  tokenId: string,
  callback?: CallbackType
): Promise<string> => {
  const results = await viewContractByContractName(
    landId,
    provider,
    "landClockAuctionV3",
    "getCurrentPriceInToken",
    [pad0xBegin(tokenId)],
    callback
  );
  return (results[0] as ethers.BigNumber).toHexString();
};

/**
 * Sell land asset
 * @param signer Ethers signer
 * @param from
 * @param tokenId - Land tokenId
 * @param start - start price
 * @param end - end price
 * @param duration - bid duration time in second
 * @param callback Callback
 * @returns {Promise<void>}
 */
export const landAskWithToken = (
  landId: LandId,
  signer: ethers.Signer,
  from: string,
  tokenId: string,
  startPrice: string,
  endPrice: string,
  duration: string,
  callback?: CallbackType
): Promise<TransactionResponse> => {
  const _from = padLeft(from.slice(2), 64, "0");
  const _start = toHexAndPadLeft(startPrice).slice(2);
  const _end = toHexAndPadLeft(endPrice).slice(2);
  const _duration = toHexAndPadLeft(duration).slice(2);
  const data = `0x${_start}${_end}${_duration}${_from}`;
  const landClockAuctionContract = getContractAddressAndAbiByContractName(landId, signer, "landClockAuctionV3");

  return triggerContractByContractName(
    landId,
    signer,
    "objectOwnership",
    "approveAndCall",
    [landClockAuctionContract.address, pad0xBegin(tokenId), data],
    callback
  );
};

/**
 * Cancel a land auction.
 * @param landId Land Id
 * @param signer Signer
 * @param tokenId Id of the Land
 * @param callback Callback
 * @returns any
 */
export const landCancelAskWithToken = (
  landId: LandId,
  signer: ethers.Signer,
  tokenId: string,
  callback?: CallbackType
): Promise<TransactionResponse> => {
  return triggerContractByContractName(
    landId,
    signer,
    "landClockAuctionV3",
    "cancelAuction",
    [pad0xBegin(tokenId)],
    callback
  );
};

/**
 * Get Avaliable item resources.
 * @param landId Land Id
 * @param provider Provider
 * @param porpsContractAddress Item contract address
 * @param tokenId Id of item
 * @param resourcesContractAddress Array of resources contract address
 * @param callback Callback
 * @returns any
 */
export const landGetAvailableItemResources = async (
  landId: LandId,
  provider: ethers.providers.Provider,
  porpsContractAddress: string,
  tokenId: string,
  resourcesContractAddress: string[],
  callback?: CallbackType
): Promise<string[]> => {
  const results = await viewContractByContractName(
    landId,
    provider,
    "apostleLandResource",
    "availableItemResources",
    [porpsContractAddress, pad0xBegin(tokenId), resourcesContractAddress],
    callback
  );

  return results[0].map((res: ethers.BigNumber) => res.toString());
};

/**
 * Batch claim item resource.
 * @param landId Land Id
 * @param signer Signer
 * @param drillContractAddress drill contract address
 * @param tokenIds Array of drill token Ids
 * @param callback Callback
 * @returns any
 */
export const landBatchClaimItemResource = (
  landId: LandId,
  signer: ethers.Signer,
  drillContractAddress: string[],
  tokenIds: string[],
  callback?: CallbackType
): Promise<TransactionResponse> => {
  return triggerContractByContractName(
    landId,
    signer,
    "apostleLandResourceV2",
    "batchClaimItemResource",
    [drillContractAddress, tokenIds.map((tokenId) => pad0xBegin(tokenId))],
    callback
  );
};

/**
 * Claim item resource.
 * @param landId Land Id
 * @param signer Signer
 * @param drillContractAddress Drill contract address
 * @param tokenId Token Id
 * @param callback Callback
 * @returns any
 */
export const landClaimItemResource = (
  landId: LandId,
  signer: ethers.Signer,
  drillContractAddress: string,
  tokenId: string,
  callback?: CallbackType
): Promise<TransactionResponse> => {
  return triggerContractByContractName(
    landId,
    signer,
    "apostleLandResource",
    "claimItemResource",
    [drillContractAddress, pad0xBegin(tokenId)],
    callback
  );
};

/**
 * Transfer land
 * @param landId Land Id
 * @param signer Signer
 * @param from Land owner
 * @param to Recipient
 * @param tokenId Token Id
 * @param callback Callback
 * @returns any
 */
export const landTransfer = (
  landId: LandId,
  signer: ethers.Signer,
  from: string,
  to: string,
  tokenId: string,
  callback?: CallbackType
): Promise<TransactionResponse> => {
  return triggerContractByContractName(
    landId,
    signer,
    "objectOwnership",
    "transferFrom",
    [from, to, pad0xBegin(tokenId)],
    callback
  );
};

/**
 * Claim land asset
 * @param landId Land Id
 * @param signer Signer
 * @param landTokenId Land token Id
 * @param callback Callback
 * @returns any
 */
export const landClaimLand = (
  landId: LandId,
  signer: ethers.Signer,
  landTokenId: string,
  callback?: CallbackType
): Promise<TransactionResponse> => {
  return triggerContractByContractName(
    landId,
    signer,
    "landClockAuctionV3",
    "claimLandAsset",
    [pad0xBegin(landTokenId)],
    callback
  );
};