Fetch certifiers only when needed (#3978)
* Fetch certifiers once + on new Logs * Linting * BadgeReg First Query * Rightly fetching badges on page change * PR Grumbles * Only fetch certifiers onces
This commit is contained in:
parent
b27c809c64
commit
7581ac635f
@ -1 +1 @@
|
|||||||
[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"fromName","outputs":[{"name":"id","type":"uint256"},{"name":"addr","type":"address"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"badgeCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"}],"name":"meta","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"}],"name":"unregister","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"fromAddress","outputs":[{"name":"id","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"badge","outputs":[{"name":"addr","type":"address"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"},{"name":"_value","type":"bytes32"}],"name":"setMeta","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"},{"name":"_owner","type":"address"}],"name":"registerAs","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"}],"name":"Unregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"key","type":"bytes32"},{"indexed":false,"name":"value","type":"bytes32"}],"name":"MetaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}]
|
[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"fromName","outputs":[{"name":"id","type":"uint256"},{"name":"addr","type":"address"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"badgeCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"}],"name":"meta","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"}],"name":"unregister","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_newAddr","type":"address"}],"name":"setAddress","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"fromAddress","outputs":[{"name":"id","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"badge","outputs":[{"name":"addr","type":"address"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"},{"name":"_value","type":"bytes32"}],"name":"setMeta","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"},{"name":"_owner","type":"address"}],"name":"registerAs","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"}],"name":"Unregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"key","type":"bytes32"},{"indexed":false,"name":"value","type":"bytes32"}],"name":"MetaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}]
|
||||||
|
@ -31,9 +31,13 @@ export default class BadgeReg {
|
|||||||
this.contracts = {}; // by name
|
this.contracts = {}; // by name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getContract () {
|
||||||
|
return this._registry.getContract('badgereg');
|
||||||
|
}
|
||||||
|
|
||||||
certifierCount () {
|
certifierCount () {
|
||||||
return this._registry
|
return this
|
||||||
.getContract('badgereg')
|
.getContract()
|
||||||
.then((badgeReg) => {
|
.then((badgeReg) => {
|
||||||
return badgeReg.instance.badgeCount.call({}, [])
|
return badgeReg.instance.badgeCount.call({}, [])
|
||||||
.then((count) => count.valueOf());
|
.then((count) => count.valueOf());
|
||||||
@ -45,8 +49,8 @@ export default class BadgeReg {
|
|||||||
return Promise.resolve(this.certifiers[id]);
|
return Promise.resolve(this.certifiers[id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._registry
|
return this
|
||||||
.getContract('badgereg')
|
.getContract()
|
||||||
.then((badgeReg) => {
|
.then((badgeReg) => {
|
||||||
return badgeReg.instance.badge.call({}, [ id ]);
|
return badgeReg.instance.badge.call({}, [ id ]);
|
||||||
})
|
})
|
||||||
@ -70,8 +74,8 @@ export default class BadgeReg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fetchMeta (id) {
|
fetchMeta (id) {
|
||||||
return this._registry
|
return this
|
||||||
.getContract('badgereg')
|
.getContract()
|
||||||
.then((badgeReg) => {
|
.then((badgeReg) => {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
badgeReg.instance.meta.call({}, [id, 'TITLE']),
|
badgeReg.instance.meta.call({}, [id, 'TITLE']),
|
||||||
|
@ -14,10 +14,9 @@
|
|||||||
// 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 { uniq } from 'lodash';
|
import { uniq, range, debounce } from 'lodash';
|
||||||
import debounce from 'debounce';
|
|
||||||
|
|
||||||
import ABI from '~/contracts/abi/certifier.json';
|
import CertifierABI from '~/contracts/abi/certifier.json';
|
||||||
import Contract from '~/api/contract';
|
import Contract from '~/api/contract';
|
||||||
import Contracts from '~/contracts';
|
import Contracts from '~/contracts';
|
||||||
import { addCertification, removeCertification } from './actions';
|
import { addCertification, removeCertification } from './actions';
|
||||||
@ -32,6 +31,7 @@ const updatableFilter = (api, onFilter) => {
|
|||||||
api.eth.uninstallFilter(filterId);
|
api.eth.uninstallFilter(filterId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
filter = (filter || Promise.resolve())
|
filter = (filter || Promise.resolve())
|
||||||
.then(() => api.eth.newFilter({
|
.then(() => api.eth.newFilter({
|
||||||
fromBlock: 0,
|
fromBlock: 0,
|
||||||
@ -46,7 +46,10 @@ const updatableFilter = (api, onFilter) => {
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('Failed to create certifications filter:', err);
|
console.error('Failed to create certifications filter:', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
return update;
|
return update;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,12 +57,52 @@ export default class CertificationsMiddleware {
|
|||||||
toMiddleware () {
|
toMiddleware () {
|
||||||
const api = Contracts.get()._api;
|
const api = Contracts.get()._api;
|
||||||
const badgeReg = Contracts.get().badgeReg;
|
const badgeReg = Contracts.get().badgeReg;
|
||||||
const contract = new Contract(api, ABI);
|
|
||||||
|
const contract = new Contract(api, CertifierABI);
|
||||||
const Confirmed = contract.events.find((e) => e.name === 'Confirmed');
|
const Confirmed = contract.events.find((e) => e.name === 'Confirmed');
|
||||||
const Revoked = contract.events.find((e) => e.name === 'Revoked');
|
const Revoked = contract.events.find((e) => e.name === 'Revoked');
|
||||||
|
|
||||||
return (store) => {
|
return (store) => {
|
||||||
const onLogs = (logs) => {
|
let certifiers = [];
|
||||||
|
let addresses = [];
|
||||||
|
let filterChanged = false;
|
||||||
|
let filter = null;
|
||||||
|
let badgeRegFilter = null;
|
||||||
|
let fetchCertifiersPromise = null;
|
||||||
|
|
||||||
|
const updateFilter = updatableFilter(api, (filterId) => {
|
||||||
|
filterChanged = true;
|
||||||
|
filter = filterId;
|
||||||
|
});
|
||||||
|
|
||||||
|
const badgeRegUpdateFilter = updatableFilter(api, (filterId) => {
|
||||||
|
filterChanged = true;
|
||||||
|
badgeRegFilter = filterId;
|
||||||
|
});
|
||||||
|
|
||||||
|
badgeReg
|
||||||
|
.getContract()
|
||||||
|
.then((badgeRegContract) => {
|
||||||
|
return badgeRegUpdateFilter(badgeRegContract.address, [
|
||||||
|
badgeRegContract.instance.Registered.signature,
|
||||||
|
badgeRegContract.instance.Unregistered.signature,
|
||||||
|
badgeRegContract.instance.MetaChanged.signature,
|
||||||
|
badgeRegContract.instance.AddressChanged.signature
|
||||||
|
]);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
shortFetchChanges();
|
||||||
|
|
||||||
|
api.subscribe('eth_blockNumber', (err) => {
|
||||||
|
if (err) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchChanges();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function onLogs (logs) {
|
||||||
logs = contract.parseEventLogs(logs);
|
logs = contract.parseEventLogs(logs);
|
||||||
logs.forEach((log) => {
|
logs.forEach((log) => {
|
||||||
const certifier = certifiers.find((c) => c.address === log.address);
|
const certifier = certifiers.find((c) => c.address === log.address);
|
||||||
@ -74,81 +117,106 @@ export default class CertificationsMiddleware {
|
|||||||
store.dispatch(addCertification(log.params.who.value, id, name, title, icon));
|
store.dispatch(addCertification(log.params.who.value, id, name, title, icon));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
let filter = null;
|
function onBadgeRegLogs (logs) {
|
||||||
|
const ids = logs.map((log) => log.params.id.value.toNumber());
|
||||||
|
return fetchCertifiers(uniq(ids));
|
||||||
|
}
|
||||||
|
|
||||||
const onFilter = (filterId) => {
|
function _fetchChanges () {
|
||||||
filter = filterId;
|
const method = filterChanged
|
||||||
api.eth.getFilterLogs(filterId)
|
? 'getFilterLogs'
|
||||||
.then(onLogs)
|
: 'getFilterChanges';
|
||||||
|
|
||||||
|
filterChanged = false;
|
||||||
|
|
||||||
|
api.eth[method](badgeRegFilter)
|
||||||
|
.then(onBadgeRegLogs)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('Failed to fetch certifier events:', err);
|
console.error('Failed to fetch badge reg events:', err);
|
||||||
});
|
})
|
||||||
};
|
.then(() => api.eth[method](filter))
|
||||||
|
|
||||||
const fetchChanges = debounce(() => {
|
|
||||||
api.eth.getFilterChanges(filter)
|
|
||||||
.then(onLogs)
|
.then(onLogs)
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('Failed to fetch new certifier events:', err);
|
console.error('Failed to fetch new certifier events:', err);
|
||||||
});
|
});
|
||||||
}, 10 * 1000, true);
|
}
|
||||||
|
|
||||||
api.subscribe('eth_blockNumber', (err) => {
|
const shortFetchChanges = debounce(_fetchChanges, 0.5 * 1000, { leading: true });
|
||||||
if (err) {
|
const fetchChanges = debounce(shortFetchChanges, 10 * 1000, { leading: true });
|
||||||
return;
|
|
||||||
|
function fetchConfirmedEvents () {
|
||||||
|
return updateFilter(certifiers.map((c) => c.address), [
|
||||||
|
[ Confirmed.signature, Revoked.signature ],
|
||||||
|
addresses
|
||||||
|
]).then(() => shortFetchChanges());
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchCertifiers (ids = []) {
|
||||||
|
if (fetchCertifiersPromise) {
|
||||||
|
return fetchCertifiersPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchChanges();
|
let fetchEvents = false;
|
||||||
});
|
|
||||||
|
|
||||||
const updateFilter = updatableFilter(api, onFilter);
|
const idsPromise = (certifiers.length === 0)
|
||||||
let certifiers = [];
|
? badgeReg.certifierCount().then((count) => {
|
||||||
let accounts = []; // these are addresses
|
return range(count);
|
||||||
|
})
|
||||||
|
: Promise.resolve(ids);
|
||||||
|
|
||||||
const fetchConfirmedEvents = () => {
|
fetchCertifiersPromise = idsPromise
|
||||||
updateFilter(certifiers.map((c) => c.address), [
|
.then((ids) => {
|
||||||
[ Confirmed.signature, Revoked.signature ],
|
const promises = ids.map((id) => {
|
||||||
accounts
|
return badgeReg.fetchCertifier(id)
|
||||||
]);
|
.then((cert) => {
|
||||||
};
|
if (!certifiers.some((c) => c.id === cert.id)) {
|
||||||
|
certifiers = certifiers.concat(cert);
|
||||||
|
fetchEvents = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (/does not exist/.test(err.toString())) {
|
||||||
|
return console.warn(err.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(`Could not fetch certifier ${id}:`, err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise
|
||||||
|
.all(promises)
|
||||||
|
.then(() => {
|
||||||
|
fetchCertifiersPromise = null;
|
||||||
|
|
||||||
|
if (fetchEvents) {
|
||||||
|
return fetchConfirmedEvents();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return fetchCertifiersPromise;
|
||||||
|
}
|
||||||
|
|
||||||
return (next) => (action) => {
|
return (next) => (action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'fetchCertifiers':
|
case 'fetchCertifiers':
|
||||||
badgeReg.certifierCount().then((count) => {
|
fetchConfirmedEvents();
|
||||||
new Array(+count).fill(null).forEach((_, id) => {
|
|
||||||
badgeReg.fetchCertifier(id)
|
|
||||||
.then((cert) => {
|
|
||||||
if (!certifiers.some((c) => c.id === cert.id)) {
|
|
||||||
certifiers = certifiers.concat(cert);
|
|
||||||
fetchConfirmedEvents();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
if (/does not exist/.test(err.toString())) {
|
|
||||||
return console.warn(err.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
console.warn(`Could not fetch certifier ${id}:`, err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'fetchCertifications':
|
case 'fetchCertifications':
|
||||||
const { address } = action;
|
const { address } = action;
|
||||||
|
|
||||||
if (!accounts.includes(address)) {
|
if (!addresses.includes(address)) {
|
||||||
accounts = accounts.concat(address);
|
addresses = addresses.concat(address);
|
||||||
fetchConfirmedEvents();
|
fetchConfirmedEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'setVisibleAccounts':
|
case 'setVisibleAccounts':
|
||||||
const { addresses } = action;
|
const _addresses = action.addresses || [];
|
||||||
accounts = uniq(accounts.concat(addresses));
|
addresses = uniq(addresses.concat(_addresses));
|
||||||
fetchConfirmedEvents();
|
fetchConfirmedEvents();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user