Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.2.6 #786

Merged
merged 5 commits into from
Sep 25, 2019
Merged

1.2.6 #786

Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hubii-core",
"version": "1.2.5",
"version": "1.2.6",
"author": {
"name": "hubii",
"email": "info@hubii.com",
Expand Down
7 changes: 3 additions & 4 deletions src/components/WalletItemCard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import { injectIntl } from 'react-intl';
import CopyToClipboard from 'react-copy-to-clipboard';

import { trimDecimals, isHardwareWallet, isAddressMatch } from 'utils/wallet';
import { isHardwareWallet } from 'utils/wallet';
import { formatFiat } from 'utils/numberFormats';
import WalletStatusIndicator from 'components/WalletStatusIndicator';
import DeletionModal from 'components/DeletionModal';
Expand Down Expand Up @@ -166,7 +166,7 @@ export class WalletItemCard extends React.PureComponent {
<AssetWrapper key={asset.currency}>
<AssetAmountBubble
name={asset.symbol}
amount={trimDecimals(asset.balance, asset.currency, this.props.priceInfo.find((c) => isAddressMatch(c.currency, asset.currency)))}
amount={asset.balance.toString()}
/>
</AssetWrapper>
));
Expand All @@ -185,7 +185,7 @@ export class WalletItemCard extends React.PureComponent {
<AssetWrapper key={asset.currency}>
<AssetAmountBubble
name={asset.symbol}
amount={trimDecimals(asset.balance, asset.currency, this.props.priceInfo.find((c) => isAddressMatch(c.currency, asset.currency)))}
amount={asset.balance.toString()}
/>
</AssetWrapper>
));
Expand Down Expand Up @@ -378,7 +378,6 @@ WalletItemCard.propTypes = {
isDecrypted: PropTypes.bool.isRequired,
mnemonic: PropTypes.string,
privateKey: PropTypes.string,
priceInfo: PropTypes.arrayOf(PropTypes.object),
intl: PropTypes.object,
};

Expand Down
6 changes: 6 additions & 0 deletions src/containers/NahmiiHoc/saga.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import {

function waitForTransaction(provider, ...args) { return provider.waitForTransaction(...args); }
function getTransactionReceipt(provider, ...args) { return provider.getTransactionReceipt(...args); }
function getTransactionCount(provider, ...args) { return provider.getTransactionCount(...args); }

export function* deposit({ address, symbol, amount, options }) {
try {
Expand Down Expand Up @@ -827,6 +828,11 @@ export function* reloadSettlementStates({ address, currency }) {

export function* wrapProcessTxForNewSettlements(nahmiiProvider, tx, address, currency) {
try {
const latestNonce = yield call(getTransactionCount, nahmiiProvider, address);
if (tx.nonce <= latestNonce) {
yield put(actions.loadTxReceiptForPaymentChallengeError(address, currency, { transactionHash: tx.hash }));
throw new Error(getIntl().formatMessage({ id: 'settlement_tx_override' }));
}
yield processTx('start-challenge', nahmiiProvider, tx, address, currency);
} catch (error) {
const errorMessage = logErrorMsg(error);
Expand Down
38 changes: 36 additions & 2 deletions src/containers/NahmiiHoc/tests/saga.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('nahmiiHocSaga', () => {
.put(actions.loadBalancesError(address))
.run({ silenceTimeout: true }));
});
describe.only('#listenReceiptEvent()', () => {
describe('#listenReceiptEvent()', () => {
const currency = '0x0000000000000000000000000000000000000000';
const receipt = new nahmii.Receipt(nahmii.Payment.from({
amount: '1',
Expand Down Expand Up @@ -538,7 +538,7 @@ describe('nahmiiHocSaga', () => {
const options = { gasLimit: 1, gasPrice: 1 };
const currency = '0x0000000000000000000000000000000000000001';
const stageAmount = new BigNumber(10000000000000000000000);
const fakeTxs = [{ chainId: 3, hash: 'hash1' }, { chainId: 3, hash: 'hash2' }];
const fakeTxs = [{ chainId: 3, hash: 'hash1', nonce: 1 }, { chainId: 3, hash: 'hash2', nonce: 2 }];
const fakeTxReceipts = [{ transactionHash: 'hash1', status: 1 }, { transactionHash: 'hash2', status: 1 }];

describe('load settlement states', () => {
Expand Down Expand Up @@ -1328,6 +1328,9 @@ describe('nahmiiHocSaga', () => {
)
.provide({
call(effect, next) {
if (effect.fn.name === 'getTransactionCount') {
return 0;
}
if (effect.fn.name === 'waitForTransaction') {
return new Promise((resolve) => {
setTimeout(() => {
Expand Down Expand Up @@ -1358,6 +1361,9 @@ describe('nahmiiHocSaga', () => {
)
.provide({
call(effect, next) {
if (effect.fn.name === 'getTransactionCount') {
return 0;
}
if (effect.fn.name === 'waitForTransaction') {
return new Promise((resolve) => {
setTimeout(() => {
Expand Down Expand Up @@ -1391,6 +1397,9 @@ describe('nahmiiHocSaga', () => {
)
.provide({
call(effect, next) {
if (effect.fn.name === 'getTransactionCount') {
return 0;
}
if (effect.fn.name === 'waitForTransaction') {
return { transactionHash: fakeTxsWithTimestamp[0].hash };
}
Expand All @@ -1411,6 +1420,28 @@ describe('nahmiiHocSaga', () => {
expect(tx).toEqual(undefined);
});
});
it('should remove pending tx from store if pending tx has been overridden', () => expectSaga(processPendingSettlementTransactions)
.withReducer(
withReducer,
storeMock.setIn(
['nahmiiHoc', 'newSettlementPendingTxs', signerMock.address, currency, fakeTxsWithTimestamp[0].hash], fromJS(fakeTxsWithTimestamp[0]))
)
.provide({
call(effect, next) {
if (effect.fn.name === 'getTransactionCount') {
return 1;
}
return next();
},
})
.put(actions.startChallengeError(signerMock.address, currency))
.run({ silenceTimeout: true })
.then((result) => {
const status = result.storeState.getIn(['nahmiiHoc', 'ongoingChallenges', signerMock.address, currency, 'status']);
const tx = result.storeState.getIn(['nahmiiHoc', 'newSettlementPendingTxs', signerMock.address, currency, fakeTxsWithTimestamp[0].hash]);
expect(status).toEqual('failed');
expect(tx).toEqual(undefined);
}));
it('should not remove pending tx from store when the error is not caused by mining failure', () => expectSaga(processPendingSettlementTransactions)
.withReducer(
withReducer,
Expand All @@ -1419,6 +1450,9 @@ describe('nahmiiHocSaga', () => {
)
.provide({
call(effect, next) {
if (effect.fn.name === 'getTransactionCount') {
return 0;
}
if (effect.fn.name === 'waitForTransaction') {
throw new Error();
}
Expand Down
1 change: 1 addition & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@
"challenge_period": "Challenge period",
"settlement_qualified": "Settlement qualified",
"settlements_disabled": "Settlements are currently disabled",
"settlement_tx_override": "The settlement transaction has been overridden (canceled).",
"withdrawable": "Withdrawable",
"synchronising_settlement_status": "Synchronising settlement status...",
"i_agree": "I agree with the ",
Expand Down
1 change: 1 addition & 0 deletions src/translations/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@
"challenge_period": "结算验证中",
"settlement_qualified": "结算验证成功",
"settlements_disabled": "当前结算功能被临时禁止",
"settlement_tx_override": "结算事务失败(被新的事务覆盖)",
"withdrawable": "可取款",
"synchronising_settlement_status": "同步结算状态...",
"i_agree": "我同意",
Expand Down
38 changes: 1 addition & 37 deletions src/utils/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,38 +36,6 @@ export const findWalletIndex = (state, address, scopedFatalError = fatalError) =
}
};

/*
* Trims the amount of decimals on 'amount' so that it is accurate up to 0.01 usd equivilent value
*/
export const trimDecimals = (amount, currency, currencyPrices) => {
if (!currencyPrices) {
return '0';
}
// check to see if this currency is a test token, in which case give it an arbitrary price of $100
const usdPrice = currencyPrices.usd === '0' ? '100' : currencyPrices.usd;

// find what 0.01 usd is in the relevant currency. force ratio to be a decimal.
let ratio = new BigNumber(0.01).dividedBy(usdPrice).toString();
if (!ratio.includes('.')) ratio += '0.0001';
const ratioSplitByDot = ratio.split('.');
const amountSplitByDot = amount.toString().split('.');

// check to see if the amount was a whole value, in which case just return as there is no need for decimal alteration
if (amountSplitByDot.length === 1) {
return amount.toString();
}

// otherwise, find how many 0's there are after the decimal place on the ratio + 1, and minus that with the length of the
// number of digits after the decimal place on the ratio.
let decimalPlacement = (ratioSplitByDot[1].toString().length - parseFloat(ratioSplitByDot[1]).toString().length) + 1;
let trimmedAmount = `${amountSplitByDot[0]}.${amountSplitByDot[1].substr(0, decimalPlacement)}`;
while (new BigNumber(trimmedAmount).eq('0')) {
decimalPlacement += 1;
trimmedAmount = `${amountSplitByDot[0]}.${amountSplitByDot[1].substr(0, decimalPlacement)}`;
}
return new BigNumber(trimmedAmount).toString(); // remove any trailing 0s and return
};

export const getBreakdown = (balances, supportedAssets) => {
// convert balances to Map if they're in array form
let formattedBalances = balances;
Expand All @@ -93,11 +61,7 @@ export const getBreakdown = (balances, supportedAssets) => {
return ({
label: getCurrencySymbol(supportedAssets, asset),
value: usdValue.toString(),
amount: trimDecimals(
amount,
asset,
{ usd: usdValue.div(amount).toString() }
),
amount: amount.toString(),
percentage,
color: supportedAssets.get('assets').find((a) => a.get('currency') === asset).get('color'),
});
Expand Down