mirror of
https://github.com/status-im/MyCrypto.git
synced 2025-01-10 19:16:10 +00:00
Equivalent Values Fixes (#500)
* Initialize with no requested currencies, so that the initial request always fires. * Adjust tokens with different decimals for equivalent values. * Reuse libs units function. * Create lib function and tests for base conversion behavior.
This commit is contained in:
parent
e6a958d6c1
commit
610805aadd
@ -5,6 +5,7 @@ import { State } from 'reducers/rates';
|
||||
import { rateSymbols, TFetchCCRates } from 'actions/rates';
|
||||
import { TokenBalance } from 'selectors/wallet';
|
||||
import { Balance } from 'libs/wallet';
|
||||
import { ETH_DECIMAL, convertTokenBase } from 'libs/units';
|
||||
import Spinner from 'components/ui/Spinner';
|
||||
import UnitDisplay from 'components/ui/UnitDisplay';
|
||||
import './EquivalentValues.scss';
|
||||
@ -28,7 +29,8 @@ export default class EquivalentValues extends React.Component<Props, CmpState> {
|
||||
currency: ALL_OPTION
|
||||
};
|
||||
private balanceLookup: { [key: string]: Balance['wei'] | undefined } = {};
|
||||
private requestedCurrencies: string[] = [];
|
||||
private decimalLookup: { [key: string]: number } = {};
|
||||
private requestedCurrencies: string[] | null = null;
|
||||
|
||||
public constructor(props) {
|
||||
super(props);
|
||||
@ -41,10 +43,7 @@ export default class EquivalentValues extends React.Component<Props, CmpState> {
|
||||
|
||||
public componentWillReceiveProps(nextProps) {
|
||||
const { balance, tokenBalances } = this.props;
|
||||
if (
|
||||
nextProps.balance !== balance ||
|
||||
nextProps.tokenBalances !== tokenBalances
|
||||
) {
|
||||
if (nextProps.balance !== balance || nextProps.tokenBalances !== tokenBalances) {
|
||||
this.makeBalanceLookup(nextProps);
|
||||
this.fetchRates(nextProps);
|
||||
}
|
||||
@ -57,10 +56,7 @@ export default class EquivalentValues extends React.Component<Props, CmpState> {
|
||||
// There are a bunch of reasons why the incorrect balances might be rendered
|
||||
// while we have incomplete data that's being fetched.
|
||||
const isFetching =
|
||||
!balance ||
|
||||
balance.isPending ||
|
||||
!tokenBalances ||
|
||||
Object.keys(rates).length === 0;
|
||||
!balance || balance.isPending || !tokenBalances || Object.keys(rates).length === 0;
|
||||
|
||||
let valuesEl;
|
||||
if (!isFetching && (rates[currency] || currency === ALL_OPTION)) {
|
||||
@ -72,15 +68,9 @@ export default class EquivalentValues extends React.Component<Props, CmpState> {
|
||||
|
||||
return (
|
||||
<li className="EquivalentValues-values-currency" key={key}>
|
||||
<span className="EquivalentValues-values-currency-label">
|
||||
{key}:
|
||||
</span>{' '}
|
||||
<span className="EquivalentValues-values-currency-label">{key}:</span>{' '}
|
||||
<span className="EquivalentValues-values-currency-value">
|
||||
<UnitDisplay
|
||||
unit={'ether'}
|
||||
value={values[key]}
|
||||
displayShortBalance={3}
|
||||
/>
|
||||
<UnitDisplay unit={'ether'} value={values[key]} displayShortBalance={3} />
|
||||
</span>
|
||||
</li>
|
||||
);
|
||||
@ -137,10 +127,10 @@ export default class EquivalentValues extends React.Component<Props, CmpState> {
|
||||
const tokenBalances = props.tokenBalances || [];
|
||||
this.balanceLookup = tokenBalances.reduce(
|
||||
(prev, tk) => {
|
||||
return {
|
||||
...prev,
|
||||
[tk.symbol]: tk.balance
|
||||
};
|
||||
// Piggy-back off of this reduce to add to decimal lookup
|
||||
this.decimalLookup[tk.symbol] = tk.decimal;
|
||||
prev[tk.symbol] = tk.balance;
|
||||
return prev;
|
||||
},
|
||||
{ ETH: props.balance && props.balance.wei }
|
||||
);
|
||||
@ -159,7 +149,7 @@ export default class EquivalentValues extends React.Component<Props, CmpState> {
|
||||
.sort();
|
||||
|
||||
// If it's the same currencies as we have, skip it
|
||||
if (currencies.join() === this.requestedCurrencies.join()) {
|
||||
if (this.requestedCurrencies && currencies.join() === this.requestedCurrencies.join()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -175,12 +165,10 @@ export default class EquivalentValues extends React.Component<Props, CmpState> {
|
||||
} {
|
||||
// Recursively call on all currencies
|
||||
if (currency === ALL_OPTION) {
|
||||
return ['ETH'].concat(this.requestedCurrencies).reduce(
|
||||
return ['ETH'].concat(this.requestedCurrencies || []).reduce(
|
||||
(prev, curr) => {
|
||||
const currValues = this.getEquivalentValues(curr);
|
||||
rateSymbols.forEach(
|
||||
sym => (prev[sym] = prev[sym].add(currValues[sym] || new BN(0)))
|
||||
);
|
||||
rateSymbols.forEach(sym => (prev[sym] = prev[sym].add(currValues[sym] || new BN(0))));
|
||||
return prev;
|
||||
},
|
||||
rateSymbols.reduce((prev, sym) => {
|
||||
@ -197,8 +185,13 @@ export default class EquivalentValues extends React.Component<Props, CmpState> {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Tokens with non-ether like decimals need to be adjusted to match
|
||||
const decimal =
|
||||
this.decimalLookup[currency] === undefined ? ETH_DECIMAL : this.decimalLookup[currency];
|
||||
const adjustedBalance = convertTokenBase(balance, decimal, ETH_DECIMAL);
|
||||
|
||||
return rateSymbols.reduce((prev, sym) => {
|
||||
prev[sym] = balance ? balance.muln(rates[currency][sym]) : null;
|
||||
prev[sym] = adjustedBalance.muln(rates[currency][sym]);
|
||||
return prev;
|
||||
}, {});
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ type UnitKey = keyof typeof Units;
|
||||
type Wei = BN;
|
||||
type TokenValue = BN;
|
||||
|
||||
export const ETH_DECIMAL = 18;
|
||||
|
||||
const Units = {
|
||||
wei: '1',
|
||||
kwei: '1000',
|
||||
@ -33,9 +35,7 @@ const Units = {
|
||||
};
|
||||
const handleValues = (input: string | BN) => {
|
||||
if (typeof input === 'string') {
|
||||
return input.startsWith('0x')
|
||||
? new BN(stripHexPrefix(input), 16)
|
||||
: new BN(input);
|
||||
return input.startsWith('0x') ? new BN(stripHexPrefix(input), 16) : new BN(input);
|
||||
}
|
||||
if (typeof input === 'number') {
|
||||
return new BN(input);
|
||||
@ -92,12 +92,20 @@ const fromTokenBase = (value: TokenValue, decimal: number) =>
|
||||
const toTokenBase = (value: string, decimal: number) =>
|
||||
TokenValue(convertedToBaseUnit(value, decimal));
|
||||
|
||||
const convertTokenBase = (value: TokenValue, oldDecimal: number, newDecimal: number) => {
|
||||
if (oldDecimal === newDecimal) {
|
||||
return value;
|
||||
}
|
||||
return toTokenBase(fromTokenBase(value, oldDecimal), newDecimal);
|
||||
};
|
||||
|
||||
export {
|
||||
TokenValue,
|
||||
fromWei,
|
||||
toWei,
|
||||
toTokenBase,
|
||||
fromTokenBase,
|
||||
convertTokenBase,
|
||||
Wei,
|
||||
getDecimal,
|
||||
UnitKey
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
toWei,
|
||||
toTokenBase,
|
||||
fromTokenBase,
|
||||
convertTokenBase,
|
||||
getDecimal,
|
||||
TokenValue
|
||||
} from 'libs/units';
|
||||
@ -77,10 +78,10 @@ describe('Units', () => {
|
||||
const tokens = '732156.34592016';
|
||||
const decimal = 18;
|
||||
const tokenBase = toTokenBase(tokens, decimal);
|
||||
it('should equal 732156345920160000000000', () => {
|
||||
it('toTokenBase should equal 732156345920160000000000', () => {
|
||||
expect(tokenBase.toString()).toEqual('732156345920160000000000');
|
||||
});
|
||||
it('should equal 732156.34592016', () => {
|
||||
it('fromTokenBase should equal 732156.34592016', () => {
|
||||
expect(fromTokenBase(tokenBase, decimal)).toEqual(tokens);
|
||||
});
|
||||
});
|
||||
@ -88,12 +89,42 @@ describe('Units', () => {
|
||||
const tokens = '8000';
|
||||
const decimal = 8;
|
||||
const converted = fromTokenBase(TokenValue(tokens), decimal);
|
||||
it('should equal 0.00008', () => {
|
||||
it('fromTokenBase should equal 0.00008', () => {
|
||||
expect(converted).toEqual('0.00008');
|
||||
});
|
||||
it('should equal 8000', () => {
|
||||
it('toTokenBase should equal 8000', () => {
|
||||
expect(toTokenBase(converted, decimal));
|
||||
});
|
||||
});
|
||||
describe('convertTokenBase', () => {
|
||||
const conversions = [
|
||||
{
|
||||
oldDecimal: 0,
|
||||
newDecimal: 18,
|
||||
startValue: '42',
|
||||
endValue: '42000000000000000000'
|
||||
},
|
||||
{
|
||||
oldDecimal: 6,
|
||||
newDecimal: 12,
|
||||
startValue: '547834782',
|
||||
endValue: '547834782000000'
|
||||
},
|
||||
{
|
||||
oldDecimal: 18,
|
||||
newDecimal: 18,
|
||||
startValue: '311095801958902158012580',
|
||||
endValue: '311095801958902158012580'
|
||||
}
|
||||
];
|
||||
|
||||
conversions.forEach(c => {
|
||||
it(`should convert decimal ${c.oldDecimal} to decimal ${c.newDecimal}`, () => {
|
||||
const tokenValue = TokenValue(c.startValue);
|
||||
const converted = convertTokenBase(tokenValue, c.oldDecimal, c.newDecimal);
|
||||
expect(converted.toString()).toEqual(c.endValue);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user