rubic-sdk
Version:
Simplify dApp creation
206 lines • 10.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DebridgeCrossChainProvider = 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 blockchain_name_1 = require("../../../../../core/blockchain/models/blockchain-name");
const blockchain_id_1 = require("../../../../../core/blockchain/utils/blockchains-info/constants/blockchain-id");
const web3_pure_1 = require("../../../../../core/blockchain/web3-pure/web3-pure");
const dln_api_service_1 = require("../../../../common/providers/dln/dln-api-service");
const dln_utils_1 = require("../../../../common/providers/dln/dln-utils");
const get_from_without_fee_1 = require("../../../../common/utils/get-from-without-fee");
const get_solana_fee_1 = require("../../../../common/utils/get-solana-fee");
const cross_chain_trade_type_1 = require("../../models/cross-chain-trade-type");
const cross_chain_provider_1 = require("../common/cross-chain-provider");
const proxy_cross_chain_evm_trade_1 = require("../common/proxy-cross-chain-evm-facade/proxy-cross-chain-evm-trade");
const debridge_cross_chain_supported_blockchain_1 = require("./constants/debridge-cross-chain-supported-blockchain");
const debridge_cross_chain_factory_1 = require("./debridge-cross-chain-factory");
const deflation_token_manager_1 = require("../../../../deflation-token-manager/deflation-token-manager");
const on_chain_trade_type_1 = require("../../../../on-chain/calculation-manager/providers/common/models/on-chain-trade-type");
class DebridgeCrossChainProvider extends cross_chain_provider_1.CrossChainProvider {
constructor() {
super(...arguments);
this.type = cross_chain_trade_type_1.CROSS_CHAIN_TRADE_TYPE.DEBRIDGE;
this.disabledTrade = null;
}
isSupportedBlockchain(blockchain) {
return debridge_cross_chain_supported_blockchain_1.deBridgeCrossChainSupportedBlockchains.some(supportedBlockchain => supportedBlockchain === blockchain);
}
async calculate(from, toToken, options) {
const fromBlockchain = from.blockchain;
const toBlockchain = toToken.blockchain;
const useProxy = options?.useProxy?.[this.type] ?? true;
await this.checkDeflationTokens(from, toToken);
try {
const fakeAddress = dln_utils_1.DlnUtils.getFakeReceiver(toBlockchain);
const feeInfo = await this.getFeeInfo(fromBlockchain, options.providerAddress, from, useProxy);
const fromWithoutFee = (0, get_from_without_fee_1.getFromWithoutFee)(from, feeInfo.rubicProxy?.platformFee?.percent);
const requestParams = {
...this.getAffiliateFee(from),
srcChainId: blockchain_id_1.blockchainId[fromBlockchain],
srcChainTokenIn: dln_utils_1.DlnUtils.getSupportedAddress(from),
srcChainTokenInAmount: fromWithoutFee.stringWeiAmount,
dstChainId: blockchain_id_1.blockchainId[toBlockchain],
dstChainTokenOut: dln_utils_1.DlnUtils.getSupportedAddress(toToken),
dstChainTokenOutRecipient: this.getWalletAddress(fromBlockchain) || fakeAddress,
prependOperatingExpenses: false
};
this.disabledTrade = this.getEmptyTrade(from, toToken, requestParams, feeInfo, options.providerAddress);
const debridgeResponse = await dln_api_service_1.DlnApiService.fetchCrossChainQuote(requestParams);
const toAmount = new bignumber_js_1.default(debridgeResponse.estimation.dstChainTokenOut.maxTheoreticalAmount);
const to = new tokens_1.PriceTokenAmount({
...toToken.asStruct,
tokenAmount: web3_pure_1.Web3Pure.fromWei(toAmount.gt(0) ? toAmount : new bignumber_js_1.default(0), debridgeResponse.estimation.dstChainTokenOut.decimals)
});
const toTokenAmountMin = web3_pure_1.Web3Pure.fromWei(debridgeResponse.estimation.dstChainTokenOut.amount, debridgeResponse.estimation.dstChainTokenOut.decimals);
const slippage = Number(to.tokenAmount
.minus(toTokenAmountMin)
.dividedBy(toTokenAmountMin)
.multipliedBy(100)
.toFixed(2));
const transitToken = debridgeResponse.estimation.srcChainTokenOut ||
debridgeResponse.estimation.srcChainTokenIn;
const nativeToken = native_tokens_1.nativeTokensList[fromBlockchain];
const cryptoFeeToken = await tokens_1.PriceTokenAmount.createFromToken({
...nativeToken,
weiAmount: new bignumber_js_1.default(debridgeResponse.fixFee)
});
return {
trade: debridge_cross_chain_factory_1.DebridgeCrossChainFactory.createTrade(fromBlockchain, {
from,
to,
transactionRequest: requestParams,
gasData: await this.getGasData(from),
priceImpact: from.calculatePriceImpactPercent(to),
allowanceTarget: debridgeResponse?.tx?.allowanceTarget,
slippage,
feeInfo: {
...feeInfo,
provider: {
cryptoFee: {
amount: web3_pure_1.Web3Pure.fromWei(cryptoFeeToken.stringWeiAmount, cryptoFeeToken.decimals),
token: cryptoFeeToken
}
}
},
transitAmount: web3_pure_1.Web3Pure.fromWei(transitToken.amount, transitToken.decimals),
toTokenAmountMin,
cryptoFeeToken,
onChainTrade: null
}, options.providerAddress, await this.getRoutePath(debridgeResponse.estimation, from, to), useProxy),
tradeType: this.type
};
}
catch (err) {
const rubicSdkError = cross_chain_provider_1.CrossChainProvider.parseError(err);
const debridgeApiError = this.parseDebridgeApiError(err);
return {
trade: debridgeApiError instanceof errors_1.TooLowAmountError ? this.disabledTrade : null,
error: debridgeApiError || rubicSdkError,
tradeType: this.type
};
}
}
async getFeeInfo(fromBlockchain, providerAddress, percentFeeToken, useProxy) {
return proxy_cross_chain_evm_trade_1.ProxyCrossChainEvmTrade.getFeeInfo(fromBlockchain, providerAddress, percentFeeToken, useProxy);
}
parseDebridgeApiError(httpErrorResponse) {
if (httpErrorResponse?.error?.errorId === 'INCLUDED_GAS_FEE_NOT_COVERED_BY_INPUT_AMOUNT' ||
httpErrorResponse?.error?.errorId === 'ERROR_LOW_GIVE_AMOUNT') {
return new errors_1.TooLowAmountError();
}
// @TODO handle other debridge API error codes:
// CONNECTOR_1INCH_RETURNED_ERROR
// INCLUDED_GAS_FEE_CANNOT_BE_ESTIMATED_FOR_TRANSACTION_BUNDLE
return null;
}
async getRoutePath(estimation, from, to) {
const fromChainId = String(blockchain_id_1.blockchainId[from.blockchain]);
const toChainId = String(blockchain_id_1.blockchainId[to.blockchain]);
const transitFrom = [...estimation.costsDetails]
.reverse()
.find(el => el.chain === fromChainId);
const transitTo = estimation.costsDetails.find(el => el.chain === toChainId);
try {
const fromTokenAmount = transitFrom
? await tokens_1.TokenAmount.createToken({
blockchain: from.blockchain,
address: transitFrom.tokenOut,
weiAmount: new bignumber_js_1.default(transitFrom.amountOut)
})
: from;
const toTokenAmount = transitTo
? await tokens_1.TokenAmount.createToken({
blockchain: to.blockchain,
address: transitTo.tokenIn,
weiAmount: new bignumber_js_1.default(transitTo.amountIn)
})
: to;
return [
{
type: 'on-chain',
path: [from, fromTokenAmount],
provider: on_chain_trade_type_1.ON_CHAIN_TRADE_TYPE.DLN
},
{
type: 'on-chain',
path: [toTokenAmount, to],
provider: on_chain_trade_type_1.ON_CHAIN_TRADE_TYPE.DLN
}
];
}
catch {
return [
{
type: 'cross-chain',
path: [from, to],
provider: cross_chain_trade_type_1.CROSS_CHAIN_TRADE_TYPE.DEBRIDGE
}
];
}
}
getEmptyTrade(from, toToken, requestParams, feeInfo, providerAddress) {
const to = new tokens_1.PriceTokenAmount({
...toToken.asStruct,
tokenAmount: new bignumber_js_1.default(0)
});
const trade = debridge_cross_chain_factory_1.DebridgeCrossChainFactory.createTrade(from.blockchain, {
from,
to,
transactionRequest: requestParams,
priceImpact: null,
allowanceTarget: undefined,
slippage: 0,
feeInfo,
transitAmount: new bignumber_js_1.default(0),
toTokenAmountMin: to.tokenAmount,
onChainTrade: null,
cryptoFeeToken: to
}, providerAddress, [], false);
return trade;
}
async checkDeflationTokens(from, toToken) {
const deflationTokenManager = new deflation_token_manager_1.DeflationTokenManager();
await deflationTokenManager.checkToken(from);
await deflationTokenManager.checkToken(toToken);
}
getAffiliateFee(from) {
if (from.blockchain === blockchain_name_1.BLOCKCHAIN_NAME.SOLANA) {
const feePercent = (0, get_solana_fee_1.getSolanaFee)(from);
if (feePercent) {
return {
affiliateFeeRecipient: '4juPxgyQapaKdgxuCS7N8pRxjttXGRZsS5WTVZ42rNjn',
affiliateFeePercent: new bignumber_js_1.default(100).multipliedBy(feePercent).toNumber()
};
}
}
return {};
}
}
exports.DebridgeCrossChainProvider = DebridgeCrossChainProvider;
//# sourceMappingURL=debridge-cross-chain-provider.js.map