[stable] Token filter balances (throttle) (backport #7742) (#7755)

This commit is contained in:
Jaco Greeff 2018-01-31 20:27:06 +01:00 committed by Afri Schoedon
parent efb310f251
commit 346c80ef11
2 changed files with 65 additions and 37 deletions

View File

@ -105,7 +105,7 @@ export function loadTokens (options = {}) {
} }
export function loadTokensBasics (tokenIndexes, options) { export function loadTokensBasics (tokenIndexes, options) {
const limit = 64; const limit = 128;
return (dispatch, getState) => { return (dispatch, getState) => {
const { api } = getState(); const { api } = getState();
@ -154,7 +154,7 @@ export function loadTokensBasics (tokenIndexes, options) {
export function fetchTokens (_tokenIndexes) { export function fetchTokens (_tokenIndexes) {
const tokenIndexes = uniq(_tokenIndexes || []); const tokenIndexes = uniq(_tokenIndexes || []);
const tokenChunks = chunk(tokenIndexes, 64); const tokenChunks = chunk(tokenIndexes, 128);
return (dispatch, getState) => { return (dispatch, getState) => {
const { tokenReg } = Contracts.get(); const { tokenReg } = Contracts.get();

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
import { range } from 'lodash'; import { chunk, range } from 'lodash';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { hashToImageUrl } from '~/redux/util'; import { hashToImageUrl } from '~/redux/util';
@ -58,23 +58,17 @@ export function fetchTokensBasics (api, tokenReg, start = 0, limit = 100) {
return decodeArray(api, 'address[]', result); return decodeArray(api, 'address[]', result);
}) })
.then((tokenAddresses) => { .then((tokenAddresses) => {
return tokenAddresses.map((tokenAddress, index) => { return tokenAddresses.map((address, index) => {
if (/^0x0*$/.test(tokenAddress)) {
return null;
}
const tokenIndex = start + index; const tokenIndex = start + index;
return { return {
address: tokenAddress,
id: getTokenId(tokenAddress, tokenIndex), id: getTokenId(tokenAddress, tokenIndex),
address,
index: tokenIndex, index: tokenIndex,
fetched: false fetched: false
}; };
}); });
}) })
.then((tokens) => tokens.filter((token) => token))
.then((tokens) => { .then((tokens) => {
const randomAddress = sha3(`${Date.now()}`).substr(0, 42); const randomAddress = sha3(`${Date.now()}`).substr(0, 42);
@ -82,8 +76,19 @@ export function fetchTokensBasics (api, tokenReg, start = 0, limit = 100) {
.then((_balances) => { .then((_balances) => {
const balances = _balances[randomAddress]; const balances = _balances[randomAddress];
return tokens.filter(({ id }) => balances[id].eq(0)); return tokens.map((token) => {
if (balances[token.id] && balances[token.id].gt(0)) {
token.address = null;
}
return token;
});
}); });
})
.then((tokens) => {
return tokens.filter(({ address }) => {
return address && !/^0x0*$/.test(address);
});
}); });
} }
@ -193,19 +198,22 @@ export function fetchAccountsBalances (api, tokens, updates) {
}); });
const tokenPromise = Object.keys(tokenUpdates) const tokenPromise = Object.keys(tokenUpdates)
.reduce((tokenPromise, accountAddress) => { .reduce((promises, accountAddress) => {
const tokenIds = tokenUpdates[accountAddress]; const tokenIds = tokenUpdates[accountAddress];
const updateTokens = tokens const updateTokens = tokens
.filter((t) => tokenIds.includes(t.id)); .filter((t) => tokenIds.includes(t.id));
return tokenPromise promises.push(
.then(() => fetchTokensBalances(api, updateTokens, [ accountAddress ])) fetchTokensBalances(api, updateTokens, [ accountAddress ])
.then((balances) => { .then((balances) => {
tokensBalances[accountAddress] = balances[accountAddress]; tokensBalances[accountAddress] = balances[accountAddress];
}); })
}, Promise.resolve()); );
return Promise.all([ ethPromise, tokenPromise ]) return promises;
}, []);
return Promise.all([ ethPromise, Promise.all(tokenPromise) ])
.then(() => { .then(() => {
const balances = Object.assign({}, tokensBalances); const balances = Object.assign({}, tokensBalances);
@ -241,29 +249,24 @@ function fetchEthBalances (api, accountAddresses) {
}); });
} }
function fetchTokensBalances (api, tokens, accountAddresses) { function fetchTokensBalances (api, _tokens, accountAddresses) {
const tokenAddresses = tokens.map((t) => t.address); const promises = chunk(_tokens, 128).map((tokens) => {
const tokensBalancesCallData = encode( const data = tokensBalancesBytecode + encode(
api, api,
[ 'address[]', 'address[]' ], [ 'address[]', 'address[]' ],
[ accountAddresses, tokenAddresses ] [ accountAddresses, tokens.map(({ address }) => address) ]
); );
return api.eth return api.eth.call({ data }).then((result) => {
.call({ data: tokensBalancesBytecode + tokensBalancesCallData })
.then((result) => {
const rawBalances = decodeArray(api, 'uint[]', result);
const balances = {}; const balances = {};
const rawBalances = decodeArray(api, 'uint[]', result);
accountAddresses.forEach((accountAddress, accountIndex) => { accountAddresses.forEach((accountAddress, accountIndex) => {
const preIndex = accountIndex * tokens.length;
const balance = {}; const balance = {};
const preIndex = accountIndex * tokenAddresses.length;
tokenAddresses.forEach((tokenAddress, tokenIndex) => { tokens.forEach((token, tokenIndex) => {
const index = preIndex + tokenIndex; balance[token.id] = rawBalances[preIndex + tokenIndex];
const token = tokens[tokenIndex];
balance[token.id] = rawBalances[index];
}); });
balances[accountAddress] = balance; balances[accountAddress] = balance;
@ -271,6 +274,31 @@ function fetchTokensBalances (api, tokens, accountAddresses) {
return balances; return balances;
}); });
});
return Promise.all(promises).then((results) => {
return results.reduce((combined, result) => {
Object
.keys(result)
.forEach((address) => {
if (!combined[address]) {
combined[address] = {};
}
Object
.keys(result[address])
.forEach((token) => {
const value = result[address][token];
if (value && value.gt(0)) {
combined[address][token] = result[address][token];
}
});
});
return combined;
}, {});
});
} }
function getTokenId (...args) { function getTokenId (...args) {