Remove isThroughPoolOptimal

This commit is contained in:
Aleksandr Kraiz
2022-08-25 14:49:59 +04:00
parent d2a6c9c127
commit b4bd644b4a
5 changed files with 32 additions and 151 deletions

View File

@@ -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",

View File

@@ -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,

View File

@@ -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,
};
}

View File

@@ -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];

View File

@@ -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(),