Backporting to beta (#4418)

* v1.5.1

* Disable notifications (#4243)

* Fix wrong token handling (#4254)

* Fixing wrong token displayed

* Linting

* Revert filtering out

* Revert the revert

* Don't panic on uknown git commit hash (#4231)

* Additional logs for own transactions (#4278)

* Integration with zgp whitelist contract (#4215)

* zgp-transactions checker

* polishing

* rename + refactor

* refuse-service-transactions cl option

* fixed tests compilation

* Renaming signAndSendTransaction to sendTransaction (#4351)

* Fixed deadlock in external_url (#4354)

* Fixing web3 in console (#4382)

* Fixing estimate gas in case histogram is not available (#4387)

* Restarting fetch client every now and then (#4399)
This commit is contained in:
Arkadiy Paronyan
2017-02-03 13:57:04 +01:00
committed by Gav Wood
parent b09cfe1885
commit c7dbd87f8e
40 changed files with 1501 additions and 734 deletions

View File

@@ -34,9 +34,9 @@ export default class Personal {
.then(outAddress);
}
signAndSendTransaction (options, password) {
sendTransaction (options, password) {
return this._transport
.execute('personal_signAndSendTransaction', inOptions(options), password);
.execute('personal_sendTransaction', inOptions(options), password);
}
unlockAccount (account, password, duration = 1) {

View File

@@ -4,8 +4,7 @@
<meta charset="utf-8">
<title>JS Console dapp</title>
<link href="console.css" rel='stylesheet' type='text/css'>
<script src="/parity-utils/parity.js"></script>
<script src="/parity-utils/web3.js"></script>
<script src="/web3.js"></script>
</head>
<body>
<div id="full-screen">

View File

@@ -40,8 +40,8 @@ export default {
}
},
signAndSendTransaction: {
desc: 'Sends and signs a transaction given account passphrase. Does not require the account to be unlocked nor unlocks the account for future transactions. ',
sendTransaction: {
desc: 'Sends transaction and signs it in a single call. The account does not need to be unlocked to make this call, and will not be left unlocked after.',
params: [
{
type: Object,

View File

@@ -96,7 +96,7 @@ class TokenSelect extends Component {
return (
<MenuItem
key={ token.tag }
key={ `${index}_${token.tag}` }
value={ token.tag }
label={ label }>
{ label }

View File

@@ -31,7 +31,8 @@ const log = getLogger(LOG_KEYS.Balances);
const ETH = {
name: 'Ethereum',
tag: 'ETH',
image: imagesEthereum
image: imagesEthereum,
native: true
};
function setBalances (_balances, skipNotifications = false) {
@@ -39,10 +40,9 @@ function setBalances (_balances, skipNotifications = false) {
const state = getState();
const currentTokens = Object.values(state.balances.tokens || {});
const currentTags = [ 'eth' ]
.concat(currentTokens.map((token) => token.tag))
.filter((tag) => tag)
.map((tag) => tag.toLowerCase());
const tokensAddresses = currentTokens
.map((token) => token.address)
.filter((address) => address);
const accounts = state.personal.accounts;
const nextBalances = _balances;
@@ -61,50 +61,59 @@ function setBalances (_balances, skipNotifications = false) {
const prevTokens = balance.tokens.slice();
const nextTokens = [];
currentTags
.forEach((tag) => {
const prevToken = prevTokens.find((tok) => tok.token.tag.toLowerCase() === tag);
const nextToken = tokens.find((tok) => tok.token.tag.toLowerCase() === tag);
const handleToken = (prevToken, nextToken) => {
// If the given token is not in the current tokens, skip
if (!nextToken && !prevToken) {
return false;
}
// If the given token is not in the current tokens, skip
if (!nextToken && !prevToken) {
return false;
}
// No updates
if (!nextToken) {
return nextTokens.push(prevToken);
}
// No updates
if (!nextToken) {
return nextTokens.push(prevToken);
}
const { token, value } = nextToken;
// If it's a new token, push it
if (!prevToken) {
return nextTokens.push({
token, value
});
}
// Otherwise, update the value
const prevValue = prevToken.value;
// If received a token/eth (old value < new value), notify
if (prevValue.lt(value) && accounts[address] && !skipNotifications) {
const account = accounts[address];
const txValue = value.minus(prevValue);
const redirectToAccount = () => {
const route = `/accounts/${account.address}`;
dispatch(push(route));
};
notifyTransaction(account, token, txValue, redirectToAccount);
}
const { token, value } = nextToken;
// If it's a new token, push it
if (!prevToken) {
return nextTokens.push({
...prevToken,
value
token, value
});
}
// Otherwise, update the value
const prevValue = prevToken.value;
// If received a token/eth (old value < new value), notify
if (prevValue.lt(value) && accounts[address] && !skipNotifications) {
const account = accounts[address];
const txValue = value.minus(prevValue);
const redirectToAccount = () => {
const route = `/accounts/${account.address}`;
dispatch(push(route));
};
notifyTransaction(account, token, txValue, redirectToAccount);
}
return nextTokens.push({
...prevToken,
value
});
};
const prevEthToken = prevTokens.find((tok) => tok.token.native);
const nextEthToken = tokens.find((tok) => tok.token.native);
handleToken(prevEthToken, nextEthToken);
tokensAddresses
.forEach((address) => {
const prevToken = prevTokens.find((tok) => tok.token.address === address);
const nextToken = tokens.find((tok) => tok.token.address === address);
handleToken(prevToken, nextToken);
});
balances[address] = { txCount: txCount || new BigNumber(0), tokens: nextTokens };
@@ -176,6 +185,8 @@ export function fetchTokens (_tokenIds, options = {}) {
return Promise
.all(tokenIds.map((id) => fetchTokenInfo(tokenreg, id, api)))
// FIXME ; shouldn't have to filter out tokens...
.then((tokens) => tokens.filter((token) => token.tag && token.tag.toLowerCase() !== 'eth'))
.then((tokens) => {
// dispatch only the changed images
tokens

View File

@@ -41,7 +41,7 @@ class Balance extends Component {
let body = (balance.tokens || [])
.filter((balance) => new BigNumber(balance.value).gt(0))
.map((balance) => {
.map((balance, index) => {
const token = balance.token;
let value;
@@ -76,7 +76,8 @@ class Balance extends Component {
return (
<div
className={ styles.balance }
key={ token.tag }>
key={ `${index}_${token.tag}` }
>
<img
src={ imagesrc }
alt={ token.name } />

View File

@@ -124,7 +124,12 @@ export default class GasPriceEditor {
@action loadDefaults () {
Promise
.all([
this._api.parity.gasPriceHistogram(),
// NOTE fetching histogram may fail if there is not enough data.
// We fallback to empty histogram.
this._api.parity.gasPriceHistogram().catch(() => ({
bucket_bounds: [],
counts: []
})),
this._api.eth.gasPrice()
])
.then(([histogram, _price]) => {

View File

@@ -62,6 +62,31 @@ describe('ui/GasPriceEditor/store', () => {
});
});
describe('constructor (defaults) when histogram not available', () => {
const api = {
eth: {
gasPrice: sinon.stub().resolves(GASPRICE)
},
parity: {
gasPriceHistogram: sinon.stub().rejects('Data not available')
}
};
beforeEach(() => {
store = new Store(api, { gasLimit: GASLIMIT });
});
it('retrieves the histogram and gasPrice', done => {
expect(api.eth.gasPrice).to.have.been.called;
expect(api.parity.gasPriceHistogram).to.have.been.called;
setImmediate(() => {
expect(store.histogram).not.to.be.null;
done();
});
});
});
describe('setters', () => {
beforeEach(() => {
store = new Store(null, { gasLimit: GASLIMIT });

View File

@@ -21,8 +21,8 @@ export default function web3extensions (web3) {
property: 'personal',
methods: [
new Method({
name: 'signAndSendTransaction',
call: 'personal_signAndSendTransaction',
name: 'sendTransaction',
call: 'personal_sendTransaction',
params: 2,
inputFormatter: [formatters.inputTransactionFormatter, null]
}),

View File

@@ -829,7 +829,7 @@
"outputFormatter": null
},
{
"name": "personal_signAndSendTransaction",
"name": "personal_sendTransaction",
"desc": "Sends and signs a transaction given account passphrase. Does not require the account to be unlocked nor unlocks the account for future transactions. ",
"params": [
{