diff --git a/sdk/src/index.ts b/sdk/src/index.ts index 72e822f..e5eaf5b 100644 --- a/sdk/src/index.ts +++ b/sdk/src/index.ts @@ -1,6 +1,7 @@ export * from './wrappedAsset'; export * from './types'; export * from './quotes'; +export * from './slippage'; export * from './utils/constants'; export * from './utils/permit'; export * from './utils/sources'; diff --git a/sdk/src/slippage.ts b/sdk/src/slippage.ts new file mode 100644 index 0000000..55524db --- /dev/null +++ b/sdk/src/slippage.ts @@ -0,0 +1,92 @@ +import { BigNumberish } from '@ethersproject/bignumber'; +import { + ChainId, + EthereumAddress, + Slippage, + SlippageError, + SlippageParams, +} from './types'; +import { API_BASE_URL } from './utils/constants'; + +/** + * Function to get a slippage formatted quote url to use with backend + * + * @param {ChainId} params.chainId + * @param {ChainId} params.toChainId + * @param {EthereumAddress} params.sellTokenAddress + * @param {EthereumAddress} params.buyTokenAddress + * @param {BigNumberish} params.buyAmount + * @param {BigNumberish} params.sellAmount + * @returns {string} + */ +const buildRainbowSlippageUrl = ({ + chainId, + toChainId, + sellTokenAddress, + buyTokenAddress, + buyAmount, + sellAmount, +}: { + chainId: number; + toChainId?: number; + sellTokenAddress: EthereumAddress; + buyTokenAddress: EthereumAddress; + buyAmount?: BigNumberish; + sellAmount?: BigNumberish; +}) => { + const searchParams = new URLSearchParams({ + buyToken: buyTokenAddress, + chainId: String(chainId), + sellToken: sellTokenAddress, + toChainId: String(toChainId), + ...(sellAmount + ? { sellAmount: String(sellAmount) } + : { buyAmount: String(buyAmount) }), + }); + return `${API_BASE_URL}/v1/slippage?` + searchParams.toString(); +}; + +/** + * Function to get slippage from rainbow's swap aggregator backend + * + * @param {SlippageParams} params + * @param {ChainId} params.chainId + * @param {ChainId} params.toChainId + * @param {EthereumAddress} params.sellTokenAddress + * @param {EthereumAddress} params.buyTokenAddress + * @param {BigNumberish} params.sellAmount + * @param {BigNumberish} params.buyAmount + * @returns {Promise} + */ +export const getSlippage = async ( + params: SlippageParams +): Promise => { + const { + chainId = ChainId.mainnet, + toChainId, + sellTokenAddress, + buyTokenAddress, + sellAmount, + buyAmount, + } = params; + + if (isNaN(Number(sellAmount)) && isNaN(Number(buyAmount))) { + return null; + } + + const url = buildRainbowSlippageUrl({ + buyAmount, + buyTokenAddress, + chainId, + sellAmount, + sellTokenAddress, + toChainId, + }); + + const response = await fetch(url); + const slippage = await response.json(); + if (slippage.error) { + return slippage as SlippageError; + } + return slippage?.data as Slippage; +}; diff --git a/sdk/src/types/index.ts b/sdk/src/types/index.ts index 6f5d586..10f1ad7 100644 --- a/sdk/src/types/index.ts +++ b/sdk/src/types/index.ts @@ -257,3 +257,22 @@ export interface CrosschainQuoteExecutionDetails { method: any; params: TransactionOptions; } + +export interface SlippageParams { + chainId: number; + sellTokenAddress: EthereumAddress; + buyTokenAddress: EthereumAddress; + sellAmount?: BigNumberish; + buyAmount?: BigNumberish; + toChainId?: number; +} + +export interface SlippageError { + error: boolean; + error_code?: number; + message: string; +} + +export interface Slippage { + slippagePercent: number; +}