@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
127 lines • 6.1 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const network_1 = __importDefault(require("@ledgerhq/live-network/network"));
const bignumber_js_1 = require("bignumber.js");
const account_1 = require("../../account");
const currencies_1 = require("../../currencies");
const errors_1 = require("../../errors");
const _1 = require("./");
const mock_1 = require("./mock");
const isIntegrationTestEnv_1 = require("./utils/isIntegrationTestEnv");
const swap_1 = require("../providers/swap");
const getExchangeRates = async ({ exchange, transaction, currencyTo, providers = [], timeout, timeoutErrorMessage, }) => {
if ((0, isIntegrationTestEnv_1.isIntegrationTestEnv)())
return (0, mock_1.mockGetExchangeRates)(exchange, transaction, currencyTo);
const from = (0, account_1.getAccountCurrency)(exchange.fromAccount).id;
const unitFrom = (0, account_1.getAccountCurrency)(exchange.fromAccount).units[0];
const to = (currencyTo ?? (0, account_1.getAccountCurrency)(exchange.toAccount)).id;
const unitTo = (currencyTo && currencyTo.units[0]) ?? (0, account_1.getAccountCurrency)(exchange.toAccount).units[0];
const amountFrom = transaction.amount;
const tenPowMagnitude = new bignumber_js_1.BigNumber(10).pow(unitFrom.magnitude);
const apiAmount = new bignumber_js_1.BigNumber(amountFrom).div(tenPowMagnitude);
const providerList = providers
.filter(provider => provider.pairs.some(pair => pair.from === from && pair.to === to))
.map(item => item.provider);
const request = {
from,
to,
amountFrom: apiAmount.toString(),
providers: providerList,
};
const headers = (0, _1.getSwapUserIP)();
const res = await (0, network_1.default)({
method: "POST",
url: `${(0, _1.getSwapAPIBaseURL)()}/rate`,
...(timeout ? { timeout } : {}),
...(timeoutErrorMessage ? { timeoutErrorMessage } : {}),
data: request,
...(headers !== undefined ? headers : {}),
});
const rates = res.data.map(async (responseData) => {
const { rate: maybeRate, payoutNetworkFees: maybePayoutNetworkFees, rateId, provider, providerType, amountFrom, amountTo, tradeMethod, providerURL, expirationTime, } = responseData;
const error = await inferError(apiAmount, unitFrom, responseData);
if (error) {
return {
provider,
tradeMethod,
error,
};
}
const payoutNetworkFees = new bignumber_js_1.BigNumber(maybePayoutNetworkFees || 0);
const magnitudeAwarePayoutNetworkFees = payoutNetworkFees.times(new bignumber_js_1.BigNumber(10).pow(unitTo.magnitude));
const rate = maybeRate
? new bignumber_js_1.BigNumber(maybeRate)
: new bignumber_js_1.BigNumber(amountTo).minus(payoutNetworkFees).div(amountFrom);
// NB Allows us to simply multiply satoshi values from/to
const magnitudeAwareRate = rate.div(new bignumber_js_1.BigNumber(10).pow(unitFrom.magnitude - unitTo.magnitude));
const toAmount = new bignumber_js_1.BigNumber(amountTo).minus(payoutNetworkFees);
const magnitudeAwareToAmount = toAmount.times(new bignumber_js_1.BigNumber(10).pow(unitTo.magnitude));
// Nb no longer need to break it down on UI
const out = {
magnitudeAwareRate,
provider,
providerType,
rate,
rateId,
expirationTime,
toAmount: magnitudeAwareToAmount,
tradeMethod,
providerURL,
};
if (tradeMethod === "fixed") {
return {
...out,
payoutNetworkFees: magnitudeAwarePayoutNetworkFees,
rateId,
};
}
else {
return {
...out,
payoutNetworkFees: magnitudeAwarePayoutNetworkFees,
};
}
});
return rates;
};
const inferError = async (apiAmount, unitFrom, responseData) => {
const tenPowMagnitude = new bignumber_js_1.BigNumber(10).pow(unitFrom.magnitude);
const { amountTo, minAmountFrom, maxAmountFrom, errorCode, errorMessage, provider, status } = responseData;
const isDex = (await (0, swap_1.getSwapProvider)(provider)).type === "DEX";
// DEX quotes are out of limits error. We do not know if it is a low or high limit, neither the amount.
if ((!minAmountFrom || !maxAmountFrom) && status === "error" && errorCode !== 300 && isDex) {
return new errors_1.SwapExchangeRateAmountTooLowOrTooHigh(undefined, {
message: "",
});
}
if (!amountTo) {
// We are in an error case regardless of api version.
if (errorCode) {
return (0, _1.getSwapAPIError)(errorCode, errorMessage);
}
// For out of range errors we will have a min/max pairing
const hasAmountLimit = minAmountFrom || maxAmountFrom;
if (hasAmountLimit) {
const isTooSmall = minAmountFrom ? new bignumber_js_1.BigNumber(apiAmount).lte(minAmountFrom) : false;
const MinOrMaxError = isTooSmall
? errors_1.SwapExchangeRateAmountTooLow
: errors_1.SwapExchangeRateAmountTooHigh;
const key = isTooSmall ? "minAmountFromFormatted" : "maxAmountFromFormatted";
const amount = isTooSmall ? minAmountFrom : maxAmountFrom;
return new MinOrMaxError(undefined, {
[key]: (0, currencies_1.formatCurrencyUnit)(unitFrom, new bignumber_js_1.BigNumber(amount).times(tenPowMagnitude), {
alwaysShowSign: false,
disableRounding: true,
showCode: true,
}),
amount: new bignumber_js_1.BigNumber(amount),
});
}
}
return;
};
exports.default = getExchangeRates;
//# sourceMappingURL=getExchangeRates.js.map