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:
committed by
Gav Wood
parent
b09cfe1885
commit
c7dbd87f8e
@@ -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) {
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -96,7 +96,7 @@ class TokenSelect extends Component {
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
key={ token.tag }
|
||||
key={ `${index}_${token.tag}` }
|
||||
value={ token.tag }
|
||||
label={ label }>
|
||||
{ label }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 } />
|
||||
|
||||
@@ -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]) => {
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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]
|
||||
}),
|
||||
|
||||
@@ -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": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user