Skip to content

Commit

Permalink
Fix rounding for getRedeemReward
Browse files Browse the repository at this point in the history
  • Loading branch information
maxima-net committed Aug 31, 2022
1 parent c31e754 commit 61e4077
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 30 deletions.
26 changes: 17 additions & 9 deletions src/blockchain/atomexProtocolMultiChain/helper.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import BigNumber from 'bignumber.js';

import type { Currency } from '../../common';
import type { PriceManager } from '../../exchange';
import { toFixedBigNumber } from '../../utils/converters';
import type { AtomexBlockchainProvider } from '../atomexBlockchainProvider';
import type { FeesInfo } from '../models/index';

export const getRedeemRewardInNativeCurrency = async (
currencyOrId: Currency | Currency['id'],
redeemFee: FeesInfo,
priceManager: PriceManager
priceManager: PriceManager,
blockchainProvider: AtomexBlockchainProvider
): Promise<FeesInfo> => {
const nativeTokenPriceInUsd = await priceManager.getAveragePrice({ baseCurrency: currencyOrId, quoteCurrency: 'USD' });
const currency = typeof currencyOrId === 'string' ? blockchainProvider.getCurrency(currencyOrId) : currencyOrId;
if (!currency)
throw new Error(`Currency info not found for ${currencyOrId}`);

const nativeTokenPriceInUsd = await priceManager.getAveragePrice({ baseCurrency: currency, quoteCurrency: 'USD' });
if (!nativeTokenPriceInUsd)
throw new Error(`Price for ${currencyOrId} in USD not found`);

Expand All @@ -20,7 +28,7 @@ export const getRedeemRewardInNativeCurrency = async (
const k = maxRewardPercentValue / Math.log((1 - maxRewardPercent) / maxRewardForRedeemDeviation);
const p = (1 - maxRewardPercent) / Math.exp(redeemFeeInUsd.toNumber() / k) + maxRewardPercent;

const rewardForRedeem = redeemFee.estimated.multipliedBy(1 + p);
const rewardForRedeem = toFixedBigNumber(redeemFee.estimated.multipliedBy(1 + p), Math.min(currency.decimals, 9), BigNumber.ROUND_FLOOR);
const result: FeesInfo = { estimated: rewardForRedeem, max: rewardForRedeem };

return result;
Expand All @@ -43,12 +51,12 @@ export const getRedeemRewardInToken = async (
const nativeTokenPriceInCurrency = await priceManager.getAveragePrice({ baseCurrency: nativeCurrency, quoteCurrency: currencyOrId });

if (!nativeTokenPriceInCurrency)
throw new Error(`Price for ${nativeCurrency.id} in ${currencyOrId} not found`);
throw new Error(`Price for ${nativeCurrency.id} in ${currency.id} not found`);

const inNativeToken = await getRedeemRewardInNativeCurrency(nativeCurrency.id, redeemFee, priceManager);
const inNativeToken = await getRedeemRewardInNativeCurrency(nativeCurrency.id, redeemFee, priceManager, blockchainProvider);
const rewardForRedeem = toFixedBigNumber(
inNativeToken.estimated.multipliedBy(nativeTokenPriceInCurrency), Math.min(currency.decimals, 9), BigNumber.ROUND_FLOOR
);

return {
estimated: inNativeToken.estimated.multipliedBy(nativeTokenPriceInCurrency),
max: inNativeToken.max.multipliedBy(nativeTokenPriceInCurrency)
};
return { estimated: rewardForRedeem, max: rewardForRedeem };
};
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class EthereumWeb3AtomexProtocolMultiChain extends Web3AtomexProtocolMult
}

getRedeemReward(redeemFee: FeesInfo): Promise<FeesInfo> {
return atomexProtocolMultiChainHelper.getRedeemRewardInNativeCurrency(this.currencyId, redeemFee, this.priceManager);
return atomexProtocolMultiChainHelper.getRedeemRewardInNativeCurrency(this.currencyId, redeemFee, this.priceManager, this.atomexBlockchainProvider);
}

getRedeemFees(params: Partial<AtomexProtocolMultiChainInitiateParameters>): Promise<FeesInfo> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class TezosTaquitoAtomexProtocolMultiChain extends TaquitoAtomexProtocolM
}

getRedeemReward(redeemFee: FeesInfo): Promise<FeesInfo> {
return atomexProtocolMultiChainHelper.getRedeemRewardInNativeCurrency(this.currencyId, redeemFee, this.priceManager);
return atomexProtocolMultiChainHelper.getRedeemRewardInNativeCurrency(this.currencyId, redeemFee, this.priceManager, this.atomexBlockchainProvider);
}

getRedeemFees(params: Partial<AtomexProtocolMultiChainInitiateParameters>): Promise<FeesInfo> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,37 @@ describe('Atomex Protocol Multi Chain utils', () => {
return priceManager;
};

const createBlockchainProvider = (currencies: Record<string, Currency>, nativeCurrencyId: string) => {
const createBlockchainProvider = (currencies: Record<string, Currency>, nativeCurrencyId?: string) => {
const blockchainProvider = new MockBlockchainProvider();

blockchainProvider.getCurrency.mockImplementation(currencyId => {
return currencies[currencyId];
});

blockchainProvider.getNativeCurrencyInfo.mockImplementation(() => {
const currency = currencies[nativeCurrencyId];
if (nativeCurrencyId) {
blockchainProvider.getNativeCurrencyInfo.mockImplementation(() => {
const currency = currencies[nativeCurrencyId];

return {
currency,
atomexProtocol: null as unknown as AtomexProtocol,
balanceProvider: null as unknown as BalancesProvider,
blockchainToolkitProvider: null as unknown as BlockchainToolkitProvider,
swapTransactionsProvider: null as unknown as SwapTransactionsProvider
} as CurrencyInfo;
});
return {
currency,
atomexProtocol: null as unknown as AtomexProtocol,
balanceProvider: null as unknown as BalancesProvider,
blockchainToolkitProvider: null as unknown as BlockchainToolkitProvider,
swapTransactionsProvider: null as unknown as SwapTransactionsProvider
} as CurrencyInfo;
});
}

return blockchainProvider;
};

test.each(redeemRewardNativeCurrencyTestCases)(
'returns redeem reward for native currency (%s)',
async (_, { currencyId, prices, redeemFee, expectedRedeemReward }) => {
async (_, { currencyId, currencies, prices, redeemFee, expectedRedeemReward }) => {
const priceManager = createPriceManager(prices);
const blockchainProvider = createBlockchainProvider(currencies);

const redeemReward = await atomexProtocolMultiChainHelper.getRedeemRewardInNativeCurrency(currencyId, redeemFee, priceManager);
const redeemReward = await atomexProtocolMultiChainHelper.getRedeemRewardInNativeCurrency(currencyId, redeemFee, priceManager, blockchainProvider);
expect(redeemReward).toEqual(expectedRedeemReward);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import BigNumber from 'bignumber.js';

import type { FeesInfo } from '../../../../src/blockchain';
import type { FeesInfo } from '../../../../src/blockchain/index';
import type { Currency } from '../../../../src/common/index';

const redeemRewardNativeCurrencyTestCases: ReadonlyArray<[
message: string,
data: {
currencyId: string;
currencies: Record<string, Currency>;
prices: Record<string, BigNumber>;
redeemFee: FeesInfo;
expectedRedeemReward: FeesInfo;
Expand All @@ -14,6 +16,43 @@ const redeemRewardNativeCurrencyTestCases: ReadonlyArray<[
[
'Simple (XTZ)',
{
currencies: {
XTZ: {
id: 'XTZ',
name: 'Tezos',
symbol: 'XTZ',
blockchain: 'tezos',
type: 'native',
decimals: 6
}
},
prices: {
'XTZ/USD': new BigNumber('2.15')
},
currencyId: 'XTZ',
redeemFee: {
estimated: new BigNumber('0.011'),
max: new BigNumber('999')
},
expectedRedeemReward: {
estimated: new BigNumber('0.021979'),
max: new BigNumber('0.021979')
}
}
],
[
'Simple (XTZ) if it has decimals equals 12',
{
currencies: {
XTZ: {
id: 'XTZ',
name: 'Tezos',
symbol: 'XTZ',
blockchain: 'tezos',
type: 'native',
decimals: 12
}
},
prices: {
'XTZ/USD': new BigNumber('2.15')
},
Expand All @@ -23,8 +62,8 @@ const redeemRewardNativeCurrencyTestCases: ReadonlyArray<[
max: new BigNumber('999')
},
expectedRedeemReward: {
estimated: new BigNumber('0.021979139924875144'),
max: new BigNumber('0.021979139924875144')
estimated: new BigNumber('0.021979139'),
max: new BigNumber('0.021979139')
}
}
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const redeemRewardTokenTestCases: ReadonlyArray<[
symbol: 'TZBTC',
blockchain: 'tezos',
type: 'fa1.2',
decimals: 6
decimals: 8
},
XTZ: {
id: 'XTZ',
Expand All @@ -46,11 +46,48 @@ const redeemRewardTokenTestCases: ReadonlyArray<[
max: new BigNumber('999')
},
expectedRedeemReward: {
estimated: new BigNumber('0.00000153722104634576757136'),
max: new BigNumber('0.00000153722104634576757136')
estimated: new BigNumber('0.00000153'),
max: new BigNumber('0.00000153')
}
}
],
[
'Simple (TZBTC) if it has decimals 11',
{
currencies: {
TZBTC: {
id: 'TZBTC',
name: 'Tezos BTC',
symbol: 'TZBTC',
blockchain: 'tezos',
type: 'fa1.2',
decimals: 11
},
XTZ: {
id: 'XTZ',
name: 'Tezos',
symbol: 'XTZ',
blockchain: 'tezos',
type: 'native',
decimals: 15
}
},
prices: {
'XTZ/USD': new BigNumber('2.15'),
'XTZ/TZBTC': new BigNumber('0.00006994')
},
currencyId: 'TZBTC',
nativeCurrencyId: 'XTZ',
redeemFee: {
estimated: new BigNumber('0.011'),
max: new BigNumber('999')
},
expectedRedeemReward: {
estimated: new BigNumber('0.000001537'),
max: new BigNumber('0.000001537')
}
}
]
];

export default redeemRewardTokenTestCases;

0 comments on commit 61e4077

Please sign in to comment.