diff --git a/packages/bridge-controller/CHANGELOG.md b/packages/bridge-controller/CHANGELOG.md index cd0972952b3..f5f820e1c1c 100644 --- a/packages/bridge-controller/CHANGELOG.md +++ b/packages/bridge-controller/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add and export `calcSlippagePercentage`, a utility that calculates the absolute slippage percentage based on the adjusted return and the sent amount ([#5723](https://github.com/MetaMask/core/pull/5723)). + ### Changed - Bump `@metamask/controller-utils` to `^11.8.0` ([#5765](https://github.com/MetaMask/core/pull/5765)) diff --git a/packages/bridge-controller/src/index.ts b/packages/bridge-controller/src/index.ts index b71bf73377b..c90209f498c 100644 --- a/packages/bridge-controller/src/index.ts +++ b/packages/bridge-controller/src/index.ts @@ -103,7 +103,11 @@ export { getDefaultBridgeControllerState, } from './utils/bridge'; -export { isValidQuoteRequest, formatEtaInMinutes } from './utils/quote'; +export { + isValidQuoteRequest, + formatEtaInMinutes, + calcSlippagePercentage, +} from './utils/quote'; export { calcLatestSrcBalance } from './utils/balance'; diff --git a/packages/bridge-controller/src/utils/quote.test.ts b/packages/bridge-controller/src/utils/quote.test.ts index 0796c7596eb..21cff65c2eb 100644 --- a/packages/bridge-controller/src/utils/quote.test.ts +++ b/packages/bridge-controller/src/utils/quote.test.ts @@ -14,6 +14,7 @@ import { calcSwapRate, calcCost, formatEtaInMinutes, + calcSlippagePercentage, } from './quote'; import type { GenericQuoteRequest, @@ -522,4 +523,40 @@ describe('Quote Metadata Utils', () => { expect(result.usd).toBeNull(); }); }); + + describe('calcSlippagePercentage', () => { + it.each([ + ['100', '100', '100', '100', 0, 0], + ['95', '95', '100', '100', 5, 5], + ['98.3', '98.3', '100', '100', 1.7, 1.7], + [null, null, '100', '100', null, null], + ['105', '105', '100', '100', 5, 5], + ])( + 'calcSlippagePercentage: calculate slippage absolute value for received amount %p, usd %p, sent amount %p, usd %p to expected amount %p, usd %p', + ( + returnValueInCurrency: string | null, + returnUsd: string | null, + sentValueInCurrency: string | null, + sentUsd: string | null, + expectedValueInCurrency: number | null, + expectedUsd: number | null, + ) => { + const result = calcSlippagePercentage( + { + valueInCurrency: returnValueInCurrency, + usd: returnUsd, + }, + { + amount: '', + valueInCurrency: sentValueInCurrency, + usd: sentUsd, + }, + ); + expect(result.percentageInCurrency).toStrictEqual( + expectedValueInCurrency, + ); + expect(result.percentageInUsd).toStrictEqual(expectedUsd); + }, + ); + }); }); diff --git a/packages/bridge-controller/src/utils/quote.ts b/packages/bridge-controller/src/utils/quote.ts index 638c2e4a55d..db9ea1624f0 100644 --- a/packages/bridge-controller/src/utils/quote.ts +++ b/packages/bridge-controller/src/utils/quote.ts @@ -304,6 +304,42 @@ export const calcCost = ( : null, }); +/** + * Calculates the slippage absolute value percentage based on the adjusted return and sent amount. + * + * @param adjustedReturn - Adjusted return value + * @param sentAmount - Sent amount value + * @returns the slippage in percentage + */ +export const calcSlippagePercentage = ( + adjustedReturn: ReturnType, + sentAmount: ReturnType, +) => { + const cost = calcCost(adjustedReturn, sentAmount); + return { + percentageInCurrency: + cost.valueInCurrency && sentAmount.valueInCurrency + ? parseFloat( + new BigNumber(cost.valueInCurrency) + .div(sentAmount.valueInCurrency) + .times(100) + .abs() + .toFixed(2), + ) + : null, + percentageInUsd: + cost.usd && sentAmount.usd + ? parseFloat( + new BigNumber(cost.usd) + .div(sentAmount.usd) + .times(100) + .abs() + .toFixed(2), + ) + : null, + }; +}; + export const formatEtaInMinutes = ( estimatedProcessingTimeInSeconds: number, ) => {