@renproject/ren
Version:
Official Ren JavaScript SDK for bridging crypto assets cross-chain.
120 lines • 5.93 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.estimateTransactionFee = exports.BIP_DENOMINATOR = void 0;
const utils_1 = require("@renproject/utils");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
exports.BIP_DENOMINATOR = 10000;
// Some assets may have their gas price defined in a different unit.
const assetGasDivisors = {
LUNA: 5,
};
const estimateTransactionFee = async (renVM, asset, fromChain, toChain) => {
// Determine if the transaction is a lock-and-mint, burn-and-release or
// burn-and-mint.
const [blockState, isLockAssetOnFromChain, isLockAssetOnToChain, isMintAssetOnFromChain, isMintAssetOnToChain, decimalsOnFromChain, decimalsOnToChain, isDepositAssetOnFromChain, isDepositAssetOnToChain,] = await Promise.all([
renVM.queryBlockState(asset, 5),
fromChain.isLockAsset(asset),
toChain.isLockAsset(asset),
(0, utils_1.isContractChain)(fromChain) && fromChain.isMintAsset(asset),
(0, utils_1.isContractChain)(toChain) && toChain.isMintAsset(asset),
fromChain.assetDecimals(asset),
toChain.assetDecimals(asset),
(0, utils_1.isDepositChain)(fromChain) && fromChain.isDepositAsset(asset),
(0, utils_1.isDepositChain)(toChain) && toChain.isDepositAsset(asset),
]);
if (!isLockAssetOnFromChain && !isMintAssetOnFromChain) {
throw utils_1.ErrorWithCode.updateError(new Error(`Asset not supported by chain ${fromChain.chain}.`), utils_1.RenJSError.PARAMETER_ERROR);
}
if (!isLockAssetOnToChain && !isMintAssetOnToChain) {
throw utils_1.ErrorWithCode.updateError(new Error(`Asset not supported by chain ${toChain.chain}.`), utils_1.RenJSError.PARAMETER_ERROR);
}
const isLockAndMint = isLockAssetOnFromChain;
const isBurnAndRelease = isLockAssetOnToChain;
// const isBurnAndMint = isMintAssetOnFromChain && isMintAssetOnToChain;
if (!blockState[asset]) {
throw utils_1.ErrorWithCode.updateError(new Error(`No fee details found for ${asset}`), utils_1.RenJSError.UNKNOWN_ERROR);
}
const { gasLimit, gasCap, minimumAmount: minimumBeforeFees, dustAmount, } = blockState[asset];
// For burning, use the fees for the origin chain. For other txs, use
// the fees for the target chain.
const feesChain = isBurnAndRelease ? fromChain.chain : toChain.chain;
const mintAndBurnFees = blockState[asset].fees.chains.filter((chainFees) => chainFees.chain === feesChain)[0];
// No other way of getting proper decimals for burn-and-mints.
const nativeDecimals = Math.max(decimalsOnFromChain, decimalsOnToChain);
const requiresTransfer = (isLockAndMint && isDepositAssetOnFromChain) ||
(isBurnAndRelease && isDepositAssetOnToChain);
const fixedFee = requiresTransfer
? gasLimit
.times(gasCap)
.shiftedBy(-assetGasDivisors[asset] || 0)
.plus(isBurnAndRelease ? dustAmount.plus(1) : 0)
: new bignumber_js_1.default(0);
const mintFee = mintAndBurnFees && mintAndBurnFees.mintFee
? mintAndBurnFees.mintFee.toNumber()
: 15;
const burnFee = mintAndBurnFees && mintAndBurnFees.burnFee
? mintAndBurnFees.burnFee.toNumber()
: 15;
const burnAndMintFee = mintAndBurnFees && mintAndBurnFees.burnAndMintFee
? mintAndBurnFees.burnAndMintFee.toNumber()
: 15;
const variableFee = isLockAndMint
? mintFee
: isBurnAndRelease
? burnFee
: burnAndMintFee;
const minimumAmount = minimumBeforeFees
.plus(fixedFee)
.plus(minimumBeforeFees
.plus(fixedFee)
.times(variableFee)
.dividedBy(exports.BIP_DENOMINATOR)
.decimalPlaces(0, bignumber_js_1.default.ROUND_DOWN));
const estimateOutput = (input) => {
const amount = bignumber_js_1.default.isBigNumber(input) ||
typeof input === "string" ||
typeof input === "number"
? input
: input.amount;
const convertUnit = typeof input === "object" && !bignumber_js_1.default.isBigNumber(input)
? input.convertUnit || false
: false;
const amountBN = new bignumber_js_1.default(amount).shiftedBy(convertUnit ? nativeDecimals : 0);
if (amountBN.isLessThan(minimumAmount)) {
return new bignumber_js_1.default(0);
}
if (isLockAndMint) {
return bignumber_js_1.default.max(amountBN
.minus(fixedFee)
.times(exports.BIP_DENOMINATOR - variableFee)
.dividedBy(exports.BIP_DENOMINATOR)
.decimalPlaces(0, bignumber_js_1.default.ROUND_DOWN), 0).shiftedBy(convertUnit ? -nativeDecimals : 0);
}
else if (isBurnAndRelease) {
return bignumber_js_1.default.max(amountBN
.times(exports.BIP_DENOMINATOR - variableFee)
.dividedBy(exports.BIP_DENOMINATOR)
.minus(fixedFee)
.decimalPlaces(0, bignumber_js_1.default.ROUND_DOWN), 0).shiftedBy(convertUnit ? -nativeDecimals : 0);
}
else {
// Burn-and-mint transaction. If a fixed-fee is ever added for all
// transactions, it will need to be added here.
return bignumber_js_1.default.max(amountBN
.times(exports.BIP_DENOMINATOR - variableFee)
.dividedBy(exports.BIP_DENOMINATOR)
.decimalPlaces(0, bignumber_js_1.default.ROUND_DOWN), 0).shiftedBy(convertUnit ? -nativeDecimals : 0);
}
};
return {
fixedFee,
variableFee,
minimumAmount,
estimateOutput,
};
};
exports.estimateTransactionFee = estimateTransactionFee;
//# sourceMappingURL=fees.js.map