UNPKG

@xlink-network/xlink-sdk

Version:
1 lines 12.5 kB
{"version":3,"sources":["../src/utils/feeRateHelpers.ts"],"sourcesContent":["import { BigNumber } from \"./BigNumber\"\nimport { concat, last, reduce } from \"./arrayHelpers\"\nimport { checkNever, OneOrMore } from \"./typeHelpers\"\nimport {\n TransferProphet,\n TransferProphet_Fee_Fixed,\n TransferProphet_Fee_Rate,\n TransferProphetAggregated,\n} from \"./types/TransferProphet\"\n\nexport interface TransferProphetAppliedResult {\n fees: (\n | (TransferProphet_Fee_Rate & { amount: BigNumber })\n | TransferProphet_Fee_Fixed\n )[]\n netAmount: BigNumber\n}\n\nexport const applyTransferProphets = (\n transferProphets: OneOrMore<TransferProphet>,\n amount: BigNumber,\n): OneOrMore<TransferProphetAppliedResult> => {\n return reduce(\n (acc, transferProphet) =>\n concat(acc, [applyTransferProphet(transferProphet, last(acc).netAmount)]),\n [{ fees: [], netAmount: amount }],\n transferProphets,\n )\n}\n\nexport const applyTransferProphet = (\n transferProphet: TransferProphet,\n amount: BigNumber,\n): TransferProphetAppliedResult => {\n const fees: TransferProphetAppliedResult[\"fees\"] = []\n\n let totalFeeAmount = BigNumber.ZERO\n for (const f of transferProphet.fees) {\n let feeAmount = BigNumber.ZERO\n\n if (f.type === \"rate\") {\n if (f.token !== transferProphet.bridgeToken) {\n throw new Error(\n `[XLinkSDK#applyTransferProphet] transferProphet.bridgeToken (${transferProphet.bridgeToken}) does not match rateFee.token (${f.token}), which is not expected`,\n )\n }\n feeAmount = BigNumber.max([\n f.minimumAmount,\n BigNumber.mul(f.rate, amount),\n ])\n fees.push({ ...f, amount: feeAmount })\n } else if (f.type === \"fixed\") {\n if (f.token === transferProphet.bridgeToken) {\n feeAmount = f.amount\n }\n fees.push(f)\n } else {\n checkNever(f)\n }\n\n totalFeeAmount = BigNumber.add(totalFeeAmount, feeAmount)\n }\n\n const netAmount = BigNumber.max([\n BigNumber.ZERO,\n BigNumber.minus(amount, totalFeeAmount),\n ])\n\n return { fees, netAmount }\n}\n\n/**\n * @example\n * composeTransferProphets(\n * [\n * // tokenA : chain1 -> chain2\n * transferProphetOf(tokenAChain1, tokenAChain2),\n * // tokenB : chain2 -> chain3\n * transferProphetOf(tokenBChain2, tokenBChain3),\n * // tokenC : chain3 -> chain4\n * transferProphetOf(tokenCChain3, tokenCChain4),\n * ],\n * [\n * // tokenA -> tokenB : chain2\n * exchangeRateOf(tokenAChain2, tokenBChain2),\n * // tokenB -> tokenC : chain3\n * exchangeRateOf(tokenBChain3, tokenCChain3),\n * ],\n * )\n */\nexport const composeTransferProphets = (\n transferProphets: readonly TransferProphet[],\n exchangeRates: readonly BigNumber[],\n): TransferProphetAggregated<TransferProphet[]> => {\n const cumulativeExchangeRates = calcCumulativeExchangeRates(exchangeRates)\n\n return reduce(\n (res, transferProphet, idx) => ({\n ...composeTransferProphet2(\n res,\n transferProphet,\n cumulativeExchangeRates[idx],\n ),\n transferProphets: [...res.transferProphets, transferProphet],\n }),\n composeTransferProphet2(\n transferProphets[0],\n transferProphets[1],\n cumulativeExchangeRates[0],\n ) as TransferProphetAggregated<TransferProphet[]>,\n transferProphets.slice(2),\n )\n}\n/**\n * @example\n * calcCumulativeExchangeRates([\n * exchangeRateOf(tokenA, tokenB),\n * exchangeRateOf(tokenB, tokenC),\n * exchangeRateOf(tokenC, tokenD),\n * // ...\n * ])\n *\n * // =>\n *\n * [\n * exchangeRateOf(tokenA, tokenB),\n * exchangeRateOf(tokenA, tokenC),\n * exchangeRateOf(tokenA, tokenD),\n * // ...\n * ]\n */\nconst calcCumulativeExchangeRates = (\n exchangeRates: readonly BigNumber[],\n): readonly BigNumber[] => {\n return BigNumber.cumulativeMul(BigNumber.ONE, exchangeRates).slice(1)\n}\n\nexport const composeTransferProphet2 = (\n transferProphet1: TransferProphet,\n transferProphet2: TransferProphet,\n exchangeRate: BigNumber,\n): TransferProphetAggregated<[TransferProphet, TransferProphet]> => {\n if (exchangeRate == null) {\n throw new Error(\n \"[XLinkSDK#composeTransferProphet2] exchangeRate is required\",\n )\n }\n\n const bridgeTokenMinFeeAmount = BigNumber.sum([\n ...transferProphet1.fees.flatMap(f =>\n f.type === \"rate\" && f.token === transferProphet1.bridgeToken\n ? [f.minimumAmount]\n : [],\n ),\n ...transferProphet2.fees.flatMap(f =>\n f.type === \"rate\" && f.token === transferProphet2.bridgeToken\n ? [\n /**\n * convert to the denomination of the first step token\n */\n BigNumber.div(f.minimumAmount, exchangeRate),\n ]\n : [],\n ),\n ])\n\n /**\n * flatFeeRate = 1 - (amount1 * (1-feeRate1) * (1-feeRate2) * (1-feeRateN...) / amount1)\n * flatFeeRate = 1 - (1-feeRate1) * (1-feeRate2) * (1-feeRateN...)\n */\n const step1FlatFeeRate = BigNumber.minus(\n BigNumber.ONE,\n last(\n BigNumber.cumulativeMul(\n BigNumber.ONE,\n transferProphet1.fees.flatMap(f =>\n f.type === \"rate\" && f.token === transferProphet1.bridgeToken\n ? [BigNumber.minus(1, f.rate)]\n : [],\n ),\n ),\n ),\n )\n /**\n * step2Amount = step1Amount * (1-feeRate1) * (1-feeRate2) * (1-feeRateN)... * exchangeRate\n * step2Amount = step1Amount * (1-flatFeeRate) * exchangeRate\n */\n const step1ToStep2Rate = BigNumber.mul(\n BigNumber.minus(1, step1FlatFeeRate),\n exchangeRate,\n )\n\n let minBridgeAmount: BigNumber | null = null\n if (\n BigNumber.isZero(bridgeTokenMinFeeAmount) /* min fee amount not set */ &&\n transferProphet1.minBridgeAmount == null &&\n transferProphet2.minBridgeAmount == null\n ) {\n minBridgeAmount = null\n } else {\n minBridgeAmount = BigNumber.max([\n bridgeTokenMinFeeAmount,\n transferProphet1.minBridgeAmount ?? 0,\n transferProphet2.minBridgeAmount == null\n ? 0\n : BigNumber.div(transferProphet2.minBridgeAmount, step1ToStep2Rate),\n ])\n }\n\n let maxBridgeAmount: BigNumber | null = null\n if (\n transferProphet1.maxBridgeAmount == null &&\n transferProphet2.maxBridgeAmount == null\n ) {\n maxBridgeAmount = null\n } else if (\n transferProphet1.maxBridgeAmount != null &&\n transferProphet2.maxBridgeAmount != null\n ) {\n maxBridgeAmount = BigNumber.min([\n transferProphet1.maxBridgeAmount,\n BigNumber.div(transferProphet2.maxBridgeAmount, step1ToStep2Rate),\n ])\n } else {\n maxBridgeAmount =\n transferProphet1.maxBridgeAmount ?? transferProphet2.maxBridgeAmount\n }\n\n return {\n isPaused: transferProphet1.isPaused || transferProphet2.isPaused,\n bridgeToken: transferProphet1.bridgeToken,\n minBridgeAmount,\n maxBridgeAmount,\n fees: [\n ...transferProphet1.fees,\n ...transferProphet2.fees.map(fee => {\n if (fee.type === \"fixed\") {\n if (fee.token !== transferProphet2.bridgeToken) return fee\n return {\n type: \"fixed\",\n token: transferProphet1.bridgeToken,\n amount: BigNumber.div(fee.amount, step1ToStep2Rate),\n } satisfies TransferProphet_Fee_Fixed\n }\n\n if (fee.type === \"rate\") {\n if (fee.token !== transferProphet2.bridgeToken) return fee\n return {\n type: \"rate\",\n token: transferProphet1.bridgeToken,\n /**\n * feeAmount = step2Amount * fee.rate\n * feeAmount = (step1Amount * (1 - step1FlatFeeRate) * exchangeRate) * fee.rate\n * step1Amount * newFeeRate = (step1Amount * (1 - step1FlatFeeRate) * exchangeRate) * fee.rate\n * newFeeRate = (1 - step1FlatFeeRate) * exchangeRate * fee.rate\n * newFeeRate = step1ToStep2Rate * fee.rate\n */\n rate: BigNumber.mul(step1ToStep2Rate, fee.rate),\n minimumAmount: BigNumber.div(fee.minimumAmount, step1ToStep2Rate),\n } satisfies TransferProphet_Fee_Rate\n }\n\n checkNever(fee)\n return fee\n }),\n ],\n transferProphets: [transferProphet1, transferProphet2],\n }\n}\n\nexport const composeRates2 = (\n rate1: BigNumber,\n rate2: BigNumber,\n): BigNumber => {\n /**\n * n = bridge amount\n * rate = ((n * r1) +\n * (n * (1 - r1)) * r2)\n * / n\n * |\n * V\n * = (n * r1 / n) +\n * (n * (1 - r1) * r2 / n)\n * |\n * V\n * = r1 + (1 - r1) * r2\n */\n // prettier-ignore\n return BigNumber.sum([\n rate1,\n BigNumber.mul(\n BigNumber.minus(1, rate1),\n rate2,\n ),\n ])\n}\n"],"mappings":"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","names":[]}