From b4bd644b4a18e87377cf1a7b49b6c647b17746dd Mon Sep 17 00:00:00 2001 From: Aleksandr Kraiz Date: Thu, 25 Aug 2022 14:49:59 +0400 Subject: [PATCH] Remove isThroughPoolOptimal --- README.md | 2 - src/OrionUnit/Exchange/getSwapInfo.ts | 28 +++- .../Exchange/getSwapMarketFeeInfo.ts | 126 ------------------ src/OrionUnit/Exchange/swapMarket.ts | 23 ++-- .../OrionAggregator/schemas/swapInfoSchema.ts | 4 +- 5 files changed, 32 insertions(+), 151 deletions(-) delete mode 100644 src/OrionUnit/Exchange/getSwapMarketFeeInfo.ts diff --git a/README.md b/README.md index f94eecd..697a85d 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,6 @@ console.log(fee); // assetIn: 'ORN', // assetOut: 'USDT', // path: [ 'ORN', 'USDT' ], -// isThroughPoolOptimal: false, // executionInfo: '...', // orderInfo: { // assetPair: 'ORN-USDT', @@ -285,7 +284,6 @@ Swap info response example: "availableAmountIn": 25.2, "availableAmountOut": null, "path": ["ORN", "USDT"], - "isThroughPoolOptimal": true, "orderInfo": { "assetPair": "ORN-USDT", "side": "SELL", diff --git a/src/OrionUnit/Exchange/getSwapInfo.ts b/src/OrionUnit/Exchange/getSwapInfo.ts index 8db5af7..2f0e58e 100644 --- a/src/OrionUnit/Exchange/getSwapInfo.ts +++ b/src/OrionUnit/Exchange/getSwapInfo.ts @@ -66,9 +66,10 @@ export default async function getSwapInfo({ options?.poolOnly ? 'pools' : undefined, ); - if (swapInfo.orderInfo !== null && options?.poolOnly === true && options.poolOnly !== swapInfo.isThroughPoolOptimal) { - throw new Error(`Unexpected Orion Aggregator response. Please, contact support. Report swap request id: ${swapInfo.id}`); - } + const { exchanges: swapExchanges } = swapInfo; + const { factories } = await simpleFetch(orionBlockchain.getPoolsConfig)(); + const poolExchangesList = factories !== undefined ? Object.keys(factories) : []; + const [firstSwapExchange] = swapExchanges; // if (swapInfo.type === 'exactReceive' && amountBN.lt(swapInfo.minAmountOut)) { // throw new Error(`Amount is too low. Min amountOut is ${swapInfo.minAmountOut} ${assetOut}`); @@ -80,15 +81,27 @@ export default async function getSwapInfo({ // if (swapInfo.orderInfo === null) throw new Error(swapInfo.executionInfo); - let isThroughPoolOptimal: boolean; - if (options?.poolOnly) isThroughPoolOptimal = true; - else isThroughPoolOptimal = swapInfo.isThroughPoolOptimal; + let route: 'pool' | 'aggregator'; + if (options?.poolOnly) { + route = 'pool'; + } else if ( + swapExchanges !== undefined + && poolExchangesList.length > 0 + && swapExchanges.length === 1 + && firstSwapExchange + && poolExchangesList.some((poolExchange) => poolExchange === firstSwapExchange) + ) { + route = 'pool'; + } else { + route = 'aggregator'; + } - if (isThroughPoolOptimal) { + if (route === 'pool') { const transactionCost = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT).mul(gasPriceWei); const denormalizedTransactionCost = utils.denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION); return { + route, swapInfo, fee: { assetName: nativeCryptocurrency, @@ -128,6 +141,7 @@ export default async function getSwapInfo({ } return { + route, swapInfo, fee: { assetName: feeAsset, diff --git a/src/OrionUnit/Exchange/getSwapMarketFeeInfo.ts b/src/OrionUnit/Exchange/getSwapMarketFeeInfo.ts deleted file mode 100644 index 274ccd4..0000000 --- a/src/OrionUnit/Exchange/getSwapMarketFeeInfo.ts +++ /dev/null @@ -1,126 +0,0 @@ -import BigNumber from 'bignumber.js'; -import { ethers } from 'ethers'; -import { utils } from '../..'; -import { NATIVE_CURRENCY_PRECISION, SWAP_THROUGH_ORION_POOL_GAS_LIMIT } from '../../constants'; -import { OrionAggregator } from '../../services/OrionAggregator'; -import { OrionBlockchain } from '../../services/OrionBlockchain'; - -import simpleFetch from '../../simpleFetch'; -import getNativeCryptocurrency from '../../utils/getNativeCryptocurrency'; - -export type GetSwapMarketInfoParams = { - type: 'exactSpend' | 'exactReceive', - assetIn: string, - assetOut: string, - amount: BigNumber.Value, - feeAsset: string, - orionBlockchain: OrionBlockchain, - orionAggregator: OrionAggregator - options?: { - poolOnly?: boolean, - } -} - -export default async function getSwapMarketFeeInfo({ - type, - assetIn, - assetOut, - amount, - feeAsset, - orionBlockchain, - orionAggregator, - options, -}: GetSwapMarketInfoParams) { - if (amount === '') throw new Error('Amount can not be empty'); - if (assetIn === '') throw new Error('AssetIn can not be empty'); - if (assetOut === '') throw new Error('AssetOut can not be empty'); - if (feeAsset === '') throw new Error('Fee asset can not be empty'); - - const amountBN = new BigNumber(amount); - if (amountBN.isNaN()) throw new Error(`Amount '${amount.toString()}' is not a number`); - if (amountBN.lte(0)) throw new Error(`Amount '${amount.toString()}' should be greater than 0`); - - const { - assetToAddress, - } = await simpleFetch(orionBlockchain.getInfo)(); - const nativeCryptocurrency = getNativeCryptocurrency(assetToAddress); - - const feeAssets = await simpleFetch(orionBlockchain.getTokensFee)(); - const pricesInOrn = await simpleFetch(orionBlockchain.getPrices)(); - const gasPriceWei = await simpleFetch(orionBlockchain.getGasPriceWei)(); - - const gasPriceGwei = ethers.utils.formatUnits(gasPriceWei, 'gwei').toString(); - - const assetInAddress = assetToAddress[assetIn]; - if (!assetInAddress) throw new Error(`Asset '${assetIn}' not found`); - const feeAssetAddress = assetToAddress[feeAsset]; - if (!feeAssetAddress) throw new Error(`Fee asset '${feeAsset}' not found. Available assets: ${Object.keys(feeAssets).join(', ')}`); - - const swapInfo = await simpleFetch(orionAggregator.getSwapInfo)( - type, - assetIn, - assetOut, - amount.toString(), - false, - options?.poolOnly ? 'pools' : undefined, - ); - - if (swapInfo.orderInfo !== null && options?.poolOnly === true && options.poolOnly !== swapInfo.isThroughPoolOptimal) { - throw new Error(`Unexpected Orion Aggregator response. Please, contact support. Report swap request id: ${swapInfo.id}`); - } - - if (swapInfo.type === 'exactReceive' && amountBN.lt(swapInfo.minAmountOut)) { - throw new Error(`Amount is too low. Min amountOut is ${swapInfo.minAmountOut} ${assetOut}`); - } - - if (swapInfo.type === 'exactSpend' && amountBN.lt(swapInfo.minAmountIn)) { - throw new Error(`Amount is too low. Min amountIn is ${swapInfo.minAmountIn} ${assetIn}`); - } - - if (swapInfo.orderInfo === null) throw new Error(swapInfo.executionInfo); - - let isThroughPoolOptimal: boolean; - if (options?.poolOnly) isThroughPoolOptimal = true; - else isThroughPoolOptimal = swapInfo.isThroughPoolOptimal; - - if (isThroughPoolOptimal) { - const transactionCost = ethers.BigNumber.from(SWAP_THROUGH_ORION_POOL_GAS_LIMIT).mul(gasPriceWei); - const denormalizedTransactionCost = utils.denormalizeNumber(transactionCost, NATIVE_CURRENCY_PRECISION); - - return { - feeAsset: nativeCryptocurrency, - feeAssetAddress: ethers.constants.AddressZero, - feeAmount: denormalizedTransactionCost.toString(), - }; - } - - const [baseAssetName] = swapInfo.orderInfo.assetPair.split('-'); - if (baseAssetName === undefined) throw new Error('Base asset name is undefined'); - const baseAssetAddress = assetToAddress[baseAssetName]; - if (!baseAssetAddress) throw new Error(`No asset address for ${baseAssetName}`); - - // Fee calculation - const baseAssetPriceInOrn = pricesInOrn?.[baseAssetAddress]; - if (!baseAssetPriceInOrn) throw new Error(`Base asset price ${baseAssetName} in ORN not found`); - const baseCurrencyPriceInOrn = pricesInOrn[ethers.constants.AddressZero]; - if (!baseCurrencyPriceInOrn) throw new Error('Base currency price in ORN not found'); - const feeAssetPriceInOrn = pricesInOrn[feeAssetAddress]; - if (!feeAssetPriceInOrn) throw new Error(`Fee asset price ${feeAsset} in ORN not found`); - const feePercent = feeAssets?.[feeAsset]; - if (!feePercent) throw new Error(`Fee asset ${feeAsset} not available`); - - const { totalFeeInFeeAsset } = utils.calculateFeeInFeeAsset( - swapInfo.orderInfo.amount, - feeAssetPriceInOrn, - baseAssetPriceInOrn, - baseCurrencyPriceInOrn, - gasPriceGwei, - feePercent, - ); - - return { - feeAsset, - feeAssetAddress, - feeAmount: totalFeeInFeeAsset, - }; -} diff --git a/src/OrionUnit/Exchange/swapMarket.ts b/src/OrionUnit/Exchange/swapMarket.ts index b688cd0..0007ec5 100644 --- a/src/OrionUnit/Exchange/swapMarket.ts +++ b/src/OrionUnit/Exchange/swapMarket.ts @@ -131,14 +131,10 @@ export default async function swapMarket({ const { exchanges: swapExchanges } = swapInfo; - const firstSwapExchange = swapExchanges?.[0]; + const [firstSwapExchange] = swapExchanges; if (swapExchanges) options?.logger?.(`Swap exchanges: ${swapExchanges.join(', ')}`); - if (swapInfo.orderInfo !== null && options?.poolOnly === true && options.poolOnly !== swapInfo.isThroughPoolOptimal) { - throw new Error(`Unexpected Orion Aggregator response. Please, contact support. Report swap request id: ${swapInfo.id}`); - } - if (swapInfo.type === 'exactReceive' && amountBN.lt(swapInfo.minAmountOut)) { throw new Error(`Amount is too low. Min amountOut is ${swapInfo.minAmountOut} ${assetOut}`); } @@ -161,16 +157,16 @@ export default async function swapMarket({ if (qtyPrecisionBN.lt(qtyDecimalPlaces)) throw new Error(`Actual amount decimal places (${qtyDecimalPlaces}) is greater than max allowed decimal places (${qtyPrecisionBN.toString()}) on pair ${baseAssetName}-${quoteAssetName}`); + let route: 'aggregator' | 'pool'; + const percent = new BigNumber(slippagePercent).div(100); - let isThroughPoolOptimal: boolean; - if (options?.developer?.route !== undefined) { - isThroughPoolOptimal = options.developer.route === 'pool'; - options?.logger?.('Swap is through pool (because route forced to pool)'); + route = options.developer.route; + options?.logger?.(`Swap is through ${route} (because route forced to ${route})`); } else if (options?.poolOnly) { options?.logger?.('Swap is through pool (because "poolOnly" option is true)'); - isThroughPoolOptimal = true; + route = 'pool'; } else if ( swapExchanges !== undefined && poolExchangesList.length > 0 @@ -179,13 +175,12 @@ export default async function swapMarket({ && poolExchangesList.some((poolExchange) => poolExchange === firstSwapExchange) ) { options?.logger?.(`Swap is through pool [via ${firstSwapExchange}] (detected by "exchanges" field)`); - isThroughPoolOptimal = true; + route = 'pool'; } else { - if (swapInfo.isThroughPoolOptimal) options?.logger?.('Swap is through pool (detected by "isThroughPoolOptimal" field)'); - isThroughPoolOptimal = swapInfo.isThroughPoolOptimal; + route = 'aggregator'; } - if (isThroughPoolOptimal) { + if (route === 'pool') { let factoryAddress: string | undefined; if (factories && firstSwapExchange) { factoryAddress = factories?.[firstSwapExchange]; diff --git a/src/services/OrionAggregator/schemas/swapInfoSchema.ts b/src/services/OrionAggregator/schemas/swapInfoSchema.ts index 3863539..aa0c506 100644 --- a/src/services/OrionAggregator/schemas/swapInfoSchema.ts +++ b/src/services/OrionAggregator/schemas/swapInfoSchema.ts @@ -7,7 +7,7 @@ const swapInfoBase = z.object({ assetIn: z.string(), assetOut: z.string(), path: z.array(z.string()), - isThroughPoolOptimal: z.boolean(), + // isThroughPoolOptimal: z.boolean(), // deprecated executionInfo: z.string(), orderInfo: z.object({ assetPair: z.string(), @@ -15,7 +15,7 @@ const swapInfoBase = z.object({ amount: z.number(), safePrice: z.number(), }).nullable(), - exchanges: z.array(z.string()).optional(), + exchanges: z.array(z.string()), price: z.number().nullable(), // spending asset price minAmountOut: z.number(), minAmountIn: z.number(),