UNPKG

rubic-sdk

Version:
184 lines • 9.3 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.OneinchAbstractProvider = void 0; const bignumber_js_1 = __importDefault(require("bignumber.js")); const errors_1 = require("../../../../../../../common/errors"); const tokens_1 = require("../../../../../../../common/tokens"); const native_tokens_1 = require("../../../../../../../common/tokens/constants/native-tokens"); const decorators_1 = require("../../../../../../../common/utils/decorators"); const options_1 = require("../../../../../../../common/utils/options"); const token_native_address_proxy_1 = require("../../../../../../common/utils/token-native-address-proxy"); const on_chain_trade_type_1 = require("../../../common/models/on-chain-trade-type"); const on_chain_proxy_contract_1 = require("../../../common/on-chain-proxy-service/constants/on-chain-proxy-contract"); const get_gas_fee_info_1 = require("../../../common/utils/get-gas-fee-info"); const evm_provider_default_options_1 = require("../on-chain-provider/evm-on-chain-provider/constants/evm-provider-default-options"); const evm_on_chain_provider_1 = require("../on-chain-provider/evm-on-chain-provider/evm-on-chain-provider"); const constants_1 = require("./constants"); const oneinch_trade_1 = require("./oneinch-trade"); const utils_1 = require("./utils"); class OneinchAbstractProvider extends evm_on_chain_provider_1.EvmOnChainProvider { constructor() { super(...arguments); this.defaultOptions = { ...evm_provider_default_options_1.evmProviderDefaultOptions, disableMultihops: false, wrappedAddress: constants_1.oneinchApiParams.nativeAddress }; } get type() { return on_chain_trade_type_1.ON_CHAIN_TRADE_TYPE.ONE_INCH; } get apiBaseUrl() { return (0, utils_1.getOneinchApiBaseUrl)(this.blockchain); } async loadContractAddress() { const response = await this.httpClient.get(`${this.apiBaseUrl}/approve/spender`); return response.address; } /** * Calculates input amount, based on amount, user wants to get. * @param from Token to sell. * @param to Token to get with output amount. * @param options Additional options. */ async calculateExactOutputAmount(from, to, options) { return (await this.calculate(to, from, options)).to.tokenAmount; } async calculate(from, toToken, options) { const fromAddress = options?.useProxy || this.defaultOptions.useProxy ? on_chain_proxy_contract_1.onChainProxyContractAddress[from.blockchain] : this.walletAddress; const fullOptions = (0, options_1.combineOptions)(options, { ...this.defaultOptions, fromAddress }); const { fromWithoutFee, proxyFeeInfo } = await this.handleProxyContract(from, fullOptions); const fromTokenClone = (0, token_native_address_proxy_1.createTokenNativeAddressProxy)(fromWithoutFee, constants_1.oneinchApiParams.nativeAddress); const toTokenClone = (0, token_native_address_proxy_1.createTokenNativeAddressProxy)(toToken, constants_1.oneinchApiParams.nativeAddress); const [dexContractAddress, { toTokenAmountInWei, estimatedGas, path, data }] = await Promise.all([ this.loadContractAddress(), this.getTradeInfo(fromTokenClone, toTokenClone, fullOptions) ]); path[0] = from; path[path.length - 1] = toToken; const to = new tokens_1.PriceTokenAmount({ ...toToken.asStruct, weiAmount: toTokenAmountInWei }); const oneinchTradeStruct = { dexContractAddress, from, to, slippageTolerance: fullOptions.slippageTolerance, disableMultihops: fullOptions.disableMultihops, path, gasFeeInfo: null, data, useProxy: fullOptions.useProxy, proxyFeeInfo, fromWithoutFee, withDeflation: fullOptions.withDeflation }; if (fullOptions.gasCalculation === 'disabled') { return new oneinch_trade_1.OneinchTrade(oneinchTradeStruct, fullOptions.providerAddress); } const gasPriceInfo = await this.getGasPriceInfo(); const gasLimit = (await oneinch_trade_1.OneinchTrade.getGasLimit(oneinchTradeStruct)) || estimatedGas; const gasFeeInfo = (0, get_gas_fee_info_1.getGasFeeInfo)(gasLimit, gasPriceInfo); return new oneinch_trade_1.OneinchTrade({ ...oneinchTradeStruct, gasFeeInfo }, fullOptions.providerAddress); } async getTradeInfo(from, toToken, options) { const isDefaultWrappedAddress = options.wrappedAddress === constants_1.oneinchApiParams.nativeAddress; const isNative = from.isNative || from.address === constants_1.oneinchApiParams.nativeAddress; const fromTokenAddress = isNative && !isDefaultWrappedAddress ? options.wrappedAddress : from.address; const toTokenAddress = toToken.address; const quoteTradeParams = { params: { fromTokenAddress, toTokenAddress, amount: from.stringWeiAmount, ...(options.disableMultihops && { connectorTokens: `${fromTokenAddress},${toTokenAddress}` }) } }; let oneInchTrade; let estimatedGas; let toTokenAmount; let data = null; try { if (!options.fromAddress) { throw new Error('Address is not set'); } if (options.gasCalculation !== 'disabled') { await oneinch_trade_1.OneinchTrade.checkIfNeedApproveAndThrowError(from, options.fromAddress, options.useProxy); } const swapTradeParams = { params: { ...quoteTradeParams.params, slippage: (options.slippageTolerance * 100).toString(), fromAddress: options.fromAddress, disableEstimate: options.gasCalculation === 'disabled' } }; oneInchTrade = await this.httpClient.get(`${this.apiBaseUrl}/swap`, swapTradeParams); estimatedGas = new bignumber_js_1.default(oneInchTrade.tx.gas); toTokenAmount = oneInchTrade.toTokenAmount; data = oneInchTrade.tx.data; } catch (_err) { oneInchTrade = await this.httpClient.get(`${this.apiBaseUrl}/quote`, quoteTradeParams); if (oneInchTrade.hasOwnProperty('errors') || !oneInchTrade.toTokenAmount) { throw new errors_1.RubicSdkError('1inch quote error'); } estimatedGas = new bignumber_js_1.default(oneInchTrade.estimatedGas); toTokenAmount = oneInchTrade.toTokenAmount; } const path = await this.extractPath(from, toToken, oneInchTrade); return { toTokenAmountInWei: new bignumber_js_1.default(toTokenAmount), estimatedGas, path, data }; } /** * Extracts tokens path from oneInch api response. * @returns Promise<Token[]> Tokens array, used in the route. */ async extractPath(fromToken, toToken, oneInchTrade) { const addressesPath = oneInchTrade.protocols[0].map(protocol => { if (!protocol?.[0]) { throw new errors_1.RubicSdkError('Protocol array must not be empty'); } return protocol[0].toTokenAddress; }); addressesPath.pop(); const tokensPathWithoutNative = await tokens_1.Token.createTokens(addressesPath.filter(tokenAddress => tokenAddress !== constants_1.oneinchApiParams.nativeAddress), this.blockchain); let tokensPathWithoutNativeIndex = 0; const tokensPath = addressesPath.map(tokenAddress => { if (tokenAddress === constants_1.oneinchApiParams.nativeAddress) { return native_tokens_1.nativeTokensList[this.blockchain]; } const token = tokensPathWithoutNative[tokensPathWithoutNativeIndex]; if (!token) { throw new errors_1.RubicSdkError('Token has to be defined'); } tokensPathWithoutNativeIndex++; return token; }); return [fromToken, ...tokensPath, toToken]; } } __decorate([ decorators_1.Cache ], OneinchAbstractProvider.prototype, "apiBaseUrl", null); exports.OneinchAbstractProvider = OneinchAbstractProvider; //# sourceMappingURL=oneinch-abstract-provider.js.map