{"version":3,"sources":["../../src/utils/interest.ts"],"sourcesContent":["import {\n  BigDecimal,\n  BigDecimalish,\n  BigDecimals,\n  removeDecimals,\n  TimeInSeconds,\n  toBigDecimal,\n} from '@nadohq/utils';\nimport { SpotProduct } from '../common';\n\n/**\n * Calculate amount total borrowed for a product\n */\nexport function calcTotalBorrowed(\n  totalBorrowsNormalized: BigDecimalish,\n  cumulativeBorrowsMultiplierX18: BigDecimalish,\n): BigDecimal {\n  return toBigDecimal(totalBorrowsNormalized).multipliedBy(\n    removeDecimals(cumulativeBorrowsMultiplierX18),\n  );\n}\n\n/**\n * Calculate amount total deposited for a product.\n */\nexport function calcTotalDeposited(\n  totalDepositsNormalized: BigDecimalish,\n  cumulativeDepositsMultiplierX18: BigDecimalish,\n): BigDecimal {\n  return toBigDecimal(totalDepositsNormalized).multipliedBy(\n    removeDecimals(cumulativeDepositsMultiplierX18),\n  );\n}\n\n/**\n * Calculates utilization ratio = abs(total borrowed / total deposited)\n *\n * @param product Spot product\n */\nexport function calcUtilizationRatio(product: SpotProduct) {\n  if (product.totalDeposited.eq(0) || product.totalBorrowed.eq(0)) {\n    return toBigDecimal(0);\n  }\n  return product.totalBorrowed.abs().div(product.totalDeposited);\n}\n\n/**\n * Calculates per-second borrow interest rate for a product. For example, a returned rate of 0.1 indicates 10% borrower\n * interest. The calculation for interest rate is as follows:\n *\n * If utilization ratio > inflection:\n *  annual rate = (1 - utilization ratio) / (1 - inflection) * interestLargeCap + interestFloor + interestSmallCap\n *\n * If utilization ratio < inflection:\n *  annual rate = utilization * interestSmallCap / inflection + utilization\n *\n * The returned rate is annual rate / 31536000 seconds per year.\n *\n * @param product Spot product\n */\nexport function calcBorrowRatePerSecond(product: SpotProduct) {\n  const {\n    interestFloor,\n    interestInflectionUtil,\n    interestSmallCap,\n    interestLargeCap,\n  } = product;\n  const utilization = calcUtilizationRatio(product);\n  if (utilization.eq(0)) {\n    return toBigDecimal(0);\n  }\n  const pastInflection = utilization.gt(interestInflectionUtil);\n\n  let annualRate: BigDecimal;\n  if (pastInflection) {\n    const utilizationTerm = interestLargeCap.times(\n      toBigDecimal(utilization)\n        .minus(interestInflectionUtil)\n        .div(BigDecimals.ONE.minus(interestInflectionUtil)),\n    );\n    annualRate = interestFloor.plus(interestSmallCap).plus(utilizationTerm);\n  } else {\n    const utilizationTerm = utilization\n      .div(interestInflectionUtil)\n      .times(interestSmallCap);\n    annualRate = interestFloor.plus(utilizationTerm);\n  }\n\n  return annualRate.div(TimeInSeconds.YEAR);\n}\n\n/**\n * Calculates borrower interest rate compounded for a period of time.\n *\n * @param product Spot product\n * @param seconds Number of seconds for the time period\n */\nexport function calcBorrowRateForTimeRange(\n  product: SpotProduct,\n  seconds: BigDecimalish,\n  minDepositRate: BigDecimalish,\n) {\n  const borrowRatePerSecond = calcBorrowRatePerSecond(product);\n\n  // Convert to number for this, with some loss of precision, but using `.pow()` causes us to hit browser resource limits\n  const borrowRateForTime =\n    borrowRatePerSecond.plus(1).toNumber() ** toBigDecimal(seconds).toNumber() -\n    1;\n  return toBigDecimal(borrowRateForTime).plus(toBigDecimal(minDepositRate));\n}\n\n/**\n * Calculate depositor interest rate compounded for a period of time.\n *\n * @param product Spot product\n * @param seconds Number of seconds for the time period\n * @param interestFeeFrac Fraction of paid borrower interest that is paid as a fee (0.2 = 20% fee)\n */\nexport function calcRealizedDepositRateForTimeRange(\n  product: SpotProduct,\n  seconds: BigDecimalish,\n  interestFeeFrac: BigDecimalish,\n  minDepositRate: BigDecimalish,\n) {\n  const utilization = calcUtilizationRatio(product);\n  if (utilization.eq(0)) {\n    return toBigDecimal(0);\n  }\n  return utilization\n    .times(calcBorrowRateForTimeRange(product, seconds, toBigDecimal(0)))\n    .times(BigDecimals.ONE.minus(toBigDecimal(interestFeeFrac)))\n    .plus(toBigDecimal(minDepositRate));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAOO;AAMA,SAAS,kBACd,wBACA,gCACY;AACZ,aAAO,2BAAa,sBAAsB,EAAE;AAAA,QAC1C,6BAAe,8BAA8B;AAAA,EAC/C;AACF;AAKO,SAAS,mBACd,yBACA,iCACY;AACZ,aAAO,2BAAa,uBAAuB,EAAE;AAAA,QAC3C,6BAAe,+BAA+B;AAAA,EAChD;AACF;AAOO,SAAS,qBAAqB,SAAsB;AACzD,MAAI,QAAQ,eAAe,GAAG,CAAC,KAAK,QAAQ,cAAc,GAAG,CAAC,GAAG;AAC/D,eAAO,2BAAa,CAAC;AAAA,EACvB;AACA,SAAO,QAAQ,cAAc,IAAI,EAAE,IAAI,QAAQ,cAAc;AAC/D;AAgBO,SAAS,wBAAwB,SAAsB;AAC5D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,cAAc,qBAAqB,OAAO;AAChD,MAAI,YAAY,GAAG,CAAC,GAAG;AACrB,eAAO,2BAAa,CAAC;AAAA,EACvB;AACA,QAAM,iBAAiB,YAAY,GAAG,sBAAsB;AAE5D,MAAI;AACJ,MAAI,gBAAgB;AAClB,UAAM,kBAAkB,iBAAiB;AAAA,UACvC,2BAAa,WAAW,EACrB,MAAM,sBAAsB,EAC5B,IAAI,yBAAY,IAAI,MAAM,sBAAsB,CAAC;AAAA,IACtD;AACA,iBAAa,cAAc,KAAK,gBAAgB,EAAE,KAAK,eAAe;AAAA,EACxE,OAAO;AACL,UAAM,kBAAkB,YACrB,IAAI,sBAAsB,EAC1B,MAAM,gBAAgB;AACzB,iBAAa,cAAc,KAAK,eAAe;AAAA,EACjD;AAEA,SAAO,WAAW,IAAI,2BAAc,IAAI;AAC1C;AAQO,SAAS,2BACd,SACA,SACA,gBACA;AACA,QAAM,sBAAsB,wBAAwB,OAAO;AAG3D,QAAM,oBACJ,oBAAoB,KAAK,CAAC,EAAE,SAAS,SAAK,2BAAa,OAAO,EAAE,SAAS,IACzE;AACF,aAAO,2BAAa,iBAAiB,EAAE,SAAK,2BAAa,cAAc,CAAC;AAC1E;AASO,SAAS,oCACd,SACA,SACA,iBACA,gBACA;AACA,QAAM,cAAc,qBAAqB,OAAO;AAChD,MAAI,YAAY,GAAG,CAAC,GAAG;AACrB,eAAO,2BAAa,CAAC;AAAA,EACvB;AACA,SAAO,YACJ,MAAM,2BAA2B,SAAS,aAAS,2BAAa,CAAC,CAAC,CAAC,EACnE,MAAM,yBAAY,IAAI,UAAM,2BAAa,eAAe,CAAC,CAAC,EAC1D,SAAK,2BAAa,cAAc,CAAC;AACtC;","names":[]}