All files / config errorHandlerUtils.ts

100% Statements 63/63
100% Branches 38/38
100% Functions 12/12
100% Lines 62/62

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267                  2x   1x   5x 5x 4x   1x 1x 1x 1x     2x 2x     1x   1x   1x     2x                                                                                                         2x   20x       20x 1x 19x 16x 84x             12x 12x     3x 1x 1x           6x 1x               5x                                         2x     5x   5x                                     5x 13x 4x       1x                 2x     3x   3x 3x   3x                           3x 8x 2x     1x     2x             5x                             5x 10x 4x       1x     2x 9x 9x 9x     2x       5x 1x     4x 3x     1x    
interface ErrorResponse {
  success: false;
  error: string;
  data?: any;
}
 
const errorMessagesFn: Record<
  string,
  Record<string, (error: any) => string>
> = {
  removeLiquidity: {
    "InvalidPercent(percent)": () => "The percentage value is invalid.",
    WithdrawalTimeout: (error) => {
      const timestamp = Number(error?.error?.cause?.data?.args?.[0]);
      if (!timestamp) {
        return "An error occurred while fetching the withdrawal timeout.";
      }
      const bigInTime = new Date(timestamp * 1000);
      const remainingSeconds = Math.floor(bigInTime.getTime() / 1000);
      const remainingTime = formatTime(remainingSeconds);
      return `You must wait for the withdrawal timeout period to expire. Remaining time: ${remainingTime} seconds.`;
    },
    LiquidityNotOwned: (error) => {
      const depositId = error?.error?.cause?.data?.args?.[0] || "";
      return `You do not own the liquidity deposit with ID ${depositId}. Please verify your account and try again.`;
    },
    "Withdrawn amount should be greater than zero": () =>
      `The withdrawal amount must be greater than zero. Please specify a valid amount.`,
    InsufficientTotalLiquidity: () =>
      `The requested withdrawal amount exceeds the pool's total liquidity. Please try amount lower amount.`,
    InvalidWithdrawnAmount: () =>
      `The requested withdrawal amount should be more than 0. Please try amount higher amount.`,
  },
};
const errorMessages: Record<string, Record<string, string>> = {
  calculatePremium: {
    "Bet timestamp invalid": `The bet ID is either expired or not yet valid. Please use a current bet ID.`,
    "Sub-bet outcome already resolved": `This bet has already been resolved. Please use an active, unresolved bet ID.`,
    "InvalidBetId: Bet does not exist": `Bet does not exist`,
    "Sub-bet condition RESOLVED, CANCELED or PAUSED": `This sub-bet condition is resolved, canceled, or paused. Insurance is not available for such bets.`,
    InvalidConditionId: `This condition is invalid. Please verify and try again.`,
    BetAlreadyPaid: `This bet has already been paid. Cannot be paid again.`,
    BetConditionAlreadyResolvedAsWon: `This bet condition is already resolved as won. No further actions can be taken.`,
    ComboBetHasNoSubBets: ` This bet condition is already resolved as won. No further actions can be taken.`,
    ComboBetAlreadyClaimed: `This bet has already been claimed. Claims cannot be made again.`,
    SubBetOutcomeAlreadyResolved: `The sub-bet outcome has already been resolved. Please check the status before proceeding.`,
    GameCanceled: `This game has been canceled. Insurance cannot be purchased for canceled games.`,
    ConditionStateViolation: `This sub-bet condition is resolved, canceled, or paused. Insurance is not available for such bets.`,
    UnsupportedBetType: ` This sub-bet condition is resolved, canceled, or paused. Insurance is not available for such bets.`,
    "Invalid odds range": `The odds must be within the valid range. Please try different bet to meet this condition.`,
    "Invalid amount range": `The amount must be within the valid range. Please try different bet to meet this condition.`,
    "Odds out of range": `Odds are out of the allowed range.`,
    "Amount out of range": `Bet amount is out of the allowed range.`,
    "Number of legs exceeds the maximum allowed limit": `Your sub-bets legs in your combo bet. The current maximum allowed is maxSubBetLimit. Please place a new bet with fewer legs and try again.`,
    "Combo bet has no sub-bets": `Your combo bet must include at least one sub-bet. Please add sub-bets and try again!`,
    "Invalid bet type": `The bet type selected is invalid. Please choose a valid option and try again.`,
    "Odds must be at least 1.0": `The odds must be at least 1.0. Please adjust your bet to meet this condition.`,
  },
  addLiquidity: {
    "SmallDeposit()": `The deposit amount is below the minimum required. Please increase your deposit and try again.`,
    "LargeDeposit()": `The deposit amount exceeds the maximum allowed. Please reduce your deposit and try again.`,
    LargeDeposit: `The deposit amount exceeds the maximum allowed. Please reduce your deposit and try again.`,
    ReachedMaxPoolLimit: `The pool has reached its maximum capacity of liquidity. Please try again later.`,
    "UserCapExceeded()": `The pool has reached its maximum capacity of liquidity. Please try again later.`,
  },
  buyCover: {
    InvalidSlippagePercent: `The slippage percentage must be between 1% and the maximum allowed. Please adjust and try again.`,
    "BetAlreadyInsured()": `This bet is already insured. You cannot purchase insurance for it again.`,
    BetAlreadyInsured: `This bet is already insured. You cannot purchase insurance for it again.`,
    NotBetSlipOwner: `You are not the owner of this bet slip. Only the owner can purchase insurance.`,
    PremiumExceedsSlippageTolerance: `The premium amount exceeds your slippage tolerance. Please adjust the slippage settings.`,
    InsufficientLiquidity: `There is insufficient liquidity to insure the bet amount on platform. Please try later.`,
    "Details: MetaMask Tx Signature: User denied transaction signature.": `User denied transaction signature`,
    "Insufficient liquidity for the bet amount": `Insufficient liquidity for the bet amount`,
  },
  settleClaim: {
    InvalidCoverId: `The cover ID is invalid. Please verify your insurance details and try again.`,
    CallerNotOwner: `You are not the owner of this insurance cover. Please verify your ownership and try again.`,
    CoverAlreadyClaimed: `This insurance cover has already been claimed. Duplicate claims are not allowed.`,
    CoverAlreadyExpired: `This insurance cover has expired. Claims cannot be made on expired covers.`,
    CoverStateManual: `This insurance cover is in manual review. Please wait for resolution or contact support.`,
    NotClaimable: `This insurance cover is not eligible for a claim at this time. Please verify the cover's status.`,
    "Cover does not exist": `The cover does not exist. Please check the provided cover ID.`,
    "Policy state already set": `The policy is already in the selected state. No further action is required.`,
  },
};
 
export const handleError = (error: any, context: string): ErrorResponse => {
  const contextErrors =
    context === "removeLiquidity"
      ? errorMessagesFn[context]
      : errorMessages[context];
 
  if (error?.message?.includes("User rejected the request.")) {
    return { success: false, error: "User denied transaction signature." };
  } else if (contextErrors) {
    for (const [key, messageFn] of Object?.entries(contextErrors)) {
      if (
        error?.error?.cause?.reason?.includes(key) ||
        error?.error?.shortMessage?.includes(key) ||
        error?.error?.message?.includes(key) ||
        error?.toString().includes(key)
      ) {
        const passMSG =
          context === "removeLiquidity" ? messageFn(error) : messageFn;
        return { success: false, error: passMSG };
      }
    }
  } else if (context === "other") {
    if (typeof error.error === "string") {
      return {
        success: false,
        error: error.error,
      };
    }
  }
  if (error?.error?.message === "Kohin instance not initialized") {
    return {
      success: false,
      error: `The Kohin instance is not initialized; your RPC URL might be incorrect.`,
    };
  }
 
  // Fallback error response
 
  return {
    success: false,
    error: `Something went wrong. Please Try Again!`,
    data: error,
  };
};
 
interface ValidateCalculatePremiumParams {
  odds: number;
  betAmount: number;
  limits: {
    minOdds: number;
    maxOdds: number;
    minAmount: number;
    maxAmount: number;
  };
  type: number;
  numLegs: number;
  maxSubBetLimit?: number;
}
 
export function validateForCalculatePremium(
  params: ValidateCalculatePremiumParams
): { success: boolean; error?: string } {
  const { odds, betAmount, limits, type, numLegs, maxSubBetLimit } = params; // Destructure parameters
 
  const validations = [
    {
      condition: odds < limits.minOdds || odds > limits.maxOdds,
      error: `The current odds of your bet are ${odds}. Please place a new bet with odds within the allowed range of ${limits.minOdds} to ${limits.maxOdds} and try again.`,
    },
    {
      condition: betAmount < limits.minAmount || betAmount > limits.maxAmount,
      error: `The current bet amount is ${betAmount}. Please place a new bet with an amount within the allowed range of ${limits.minAmount} to ${limits.maxAmount} and try again.`,
    },
    {
      condition: type !== 0 && type !== 1,
      error: `The bet type selected is invalid. Please choose a valid option and try again.`,
    },
    {
      condition: maxSubBetLimit && numLegs > maxSubBetLimit,
      error: `You've selected ${numLegs} legs in your combo bet. The current maximum allowed is ${maxSubBetLimit}. Please place a new bet with fewer legs and try again.`,
    },
  ];
 
  for (const { condition, error } of validations) {
    if (condition) {
      return { success: false, error };
    }
  }
 
  return { success: true };
}
 
interface validateForAddLiquidityParams {
  maxDeposit: number;
  minDeposit: number;
  amount: number;
}
 
export function validateForAddLiquidity(
  params: validateForAddLiquidityParams
): { success: boolean; error?: string } {
  const { maxDeposit, minDeposit, amount } = params;
 
  const minDepositFormatted = minDeposit.toFixed(2);
  const maxDepositFormatted = maxDeposit.toFixed(2);
 
  const validations = [
    {
      condition: !amount,
      error: `Please add some amount before you proceed.`,
    },
    {
      condition: amount < minDeposit,
      error: `Please try adding amount of at least ${minDepositFormatted} USDT.`,
    },
    {
      condition: amount > maxDeposit,
      error: `Please try adding amount of less then ${maxDepositFormatted} USDT.`,
    },
  ];
  for (const { condition, error } of validations) {
    if (condition) {
      return { success: false, error };
    }
  }
  return { success: true };
}
 
export function validateForBuyCover(
  slippagePercent: number,
  maxSlippagePercent: number,
  isBooked: boolean,
  coverPremium: bigint,
  tokenBalance: bigint
): { success: boolean; error?: string } {
  const validations = [
    {
      condition: slippagePercent < 1 || slippagePercent > maxSlippagePercent,
      error: `The slippage percentage must be between 1% and the maximum allowed. Please adjust and try again.`,
    },
    {
      condition: isBooked,
      error: `Cover is already booked for this bet ID.`,
    },
    {
      condition: coverPremium > tokenBalance,
      error: `Single bets are not supported in this feature. Please create a combo bet to purchase insurance coverage and try again.`,
    },
  ];
 
  for (const { condition, error } of validations) {
    if (condition) {
      return { success: false, error };
    }
  }
 
  return { success: true };
}
 
export function formatTime(remainingTimeInSeconds: number): string {
  const minutes = Math.floor(remainingTimeInSeconds / 60);
  const seconds = remainingTimeInSeconds % 60;
  return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
}
 
export function validateAffiliateAddress(address: string): {
  success: boolean;
  error?: string;
} {
  if (!address) {
    return { success: false, error: "Kohin-JS: Invalid affiliate address." };
  }
 
  if (address.length !== 42 || !/^0x[a-fA-F0-9]{40}$/.test(address)) {
    return { success: false, error: "Kohin-JS: Invalid affiliate address." };
  }
 
  return { success: true };
}