Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Load network apps manifests as contentHash (no coding) (#3235)
Browse files Browse the repository at this point in the history
* Add mobx

* Use mobx store for dapps

* Cleanup hidden reads

* Remove (now) unused hidden.js

* _ denotes internal functions

* s/visibleApps/visible/

* AddDapps now use the mobx store as well

* Move modalOpen state to store

* Simplify

* Complete master merge

* Remove extra indirection

* Remove unneeded check

* Readability improvements

* Remove final debug info

* Load network manifests from the network

* Swallow manifest errors

* introduce fetchManifest
  • Loading branch information
jacogr authored and arkpar committed Nov 7, 2016
1 parent 34998a7 commit 399748f
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 86 deletions.
4 changes: 4 additions & 0 deletions js/src/contracts/dappreg.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@ export default class DappReg {
getContent (id) {
return this.meta(id, 'CONTENT');
}

getManifest (id) {
return this.meta(id, 'MANIFEST');
}
}
11 changes: 4 additions & 7 deletions js/src/views/Dapp/dapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,17 @@ export default class Dapp extends Component {

let src = null;
switch (app.type) {
case 'builtin':
const dapphost = process.env.NODE_ENV === 'production' && !app.secure
? `${dappsUrl}/ui`
: '';
src = `${dapphost}/${app.url}.html`;
break;
case 'local':
src = `${dappsUrl}/${app.id}/`;
break;
case 'network':
src = `${dappsUrl}/${app.contentHash}/`;
break;
default:
console.error('unknown type', app.type);
const dapphost = process.env.NODE_ENV === 'production' && !app.secure
? `${dappsUrl}/ui`
: '';
src = `${dapphost}/${app.url}.html`;
break;
}

Expand Down
192 changes: 113 additions & 79 deletions js/src/views/Dapps/dappsStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import BigNumber from 'bignumber.js';
import { action, computed, observable } from 'mobx';

import Contracts from '../../contracts';
Expand Down Expand Up @@ -63,21 +62,6 @@ const builtinApps = [
}
];

// TODO: This is just since we are moving gavcoin to its own repo, for a proper network solution
// we need to pull the network apps from the dapp registry. (Builtins & local apps unaffected)
// TODO: Manifest needs to be pulled from the content as well, however since the content may or may
// not be available locally (and refreshes work for index, and will give a 503), we are putting it
// in here. This part needs to be cleaned up.
const networkApps = [
{
id: '0xd798a48831b4ccdbc71de206a1d6a4aa73546c7b6f59c22a47452af414dc64d6',
name: 'GAVcoin',
description: 'Manage your GAVcoins, the hottest new property in crypto',
author: 'Gavin Wood',
version: '1.0.0'
}
];

export default class DappsStore {
@observable apps = [];
@observable hidden = [];
Expand Down Expand Up @@ -118,93 +102,143 @@ export default class DappsStore {
: '';
}

@action _fetch () {
const { dappReg } = Contracts.get();

return fetch(`${this._getHost()}/api/apps`)
.then((response) => {
return response.ok
? response.json()
: [];
_fetch () {
Promise
.all([
this._fetchLocal(),
this._fetchRegistry()
])
.then(([localApps, registryApps]) => {
this.apps = []
.concat(localApps)
.concat(registryApps)
.filter((app) => app.id)
.sort((a, b) => (a.name || '').localeCompare(b.name || ''));
})
.catch((error) => {
console.warn('DappsStore:fetch', error);
return [];
console.warn('DappStore:fetch', error);
});
}

_fetchRegistry () {
const { dappReg } = Contracts.get();

return dappReg
.count()
.then((_count) => {
const count = _count.toNumber();
const promises = [];

for (let index = 0; index < count; index++) {
promises.push(dappReg.at(index));
}

return Promise.all(promises);
})
.then((_localApps) => {
const localApps = _localApps
.filter((app) => !['ui'].includes(app.id))
.map((app) => {
app.type = 'local';
return app;
});
.then((appsInfo) => {
const appIds = appsInfo.map(([appId, owner]) => {
return this._api.util.bytesToHex(appId);
});

return this._api.parity
.registryAddress()
.then((registryAddress) => {
if (new BigNumber(registryAddress).eq(0)) {
return [];
}

const _builtinApps = builtinApps
.map((app) => {
app.type = 'builtin';
return app;
});

return networkApps
.map((app) => {
app.type = 'network';
return app;
})
.concat(_builtinApps);
})
.then((registryApps) => {
return registryApps
.concat(localApps)
.sort((a, b) => (a.name || '').localeCompare(b.name || ''));
return Promise
.all([
Promise.all(appIds.map((appId) => dappReg.getImage(appId))),
Promise.all(appIds.map((appId) => dappReg.getContent(appId))),
Promise.all(appIds.map((appId) => dappReg.getManifest(appId)))
])
.then(([imageIds, contentIds, manifestIds]) => {
return appIds.map((appId, index) => {
const app = builtinApps.find((ba) => ba.id === appId) || {
id: appId,
contentHash: this._api.util.bytesToHex(contentIds[index]).substr(2),
manifestHash: this._api.util.bytesToHex(manifestIds[index]).substr(2),
type: 'network'
};

app.image = hashToImageUrl(imageIds[index]);
app.type = app.type || 'builtin';

return app;
});
});
})
.then((apps) => {
return Promise
.all([
Promise.all(apps.map((app) => dappReg.getImage(app.id))),
Promise.all(apps.map((app) => dappReg.getContent(app.id)))
])
.then(([images, content]) => {
this.apps = apps.map((app, index) => {
return Object.assign(app, {
image: hashToImageUrl(images[index]),
contentHash: this._api.util.bytesToHex(content[index]).substr(2)
});
.all(apps.map((app) => {
return app.manifestHash
? this._fetchManifest(app.manifestHash)
: null;
}))
.then((manifests) => {
return apps.map((app, index) => {
const manifest = manifests[index];

if (manifest) {
app.manifestHash = null;
Object.keys(manifest)
.filter((key) => key !== 'id')
.forEach((key) => {
app[key] = manifest[key];
});
}

return app;
});
})
.then((apps) => {
return apps.filter((app) => {
return !app.manifestHash && app.id;
});
});
})
.catch((error) => {
console.warn('DappsStore:fetch', error);
console.warn('DappsStore:fetchRegistry', error);
});
}

_fetchManifest (manifestHash, count = 0) {
return fetch(`${this._getHost()}/api/content/${manifestHash}/`)
.then((response) => {
if (response.ok) {
return response.json();
}

if (count < 1) {
return this._fetchManifest(manifestHash, count + 1);
}

return null;
})
.catch(() => {
if (count < 1) {
return this._fetchManifest(manifestHash, count + 1);
}

return null;
});
}

_manifest (app, contentHash) {
fetch(`${this.getHost()}/${contentHash}/manifest.json`)
_fetchLocal () {
return fetch(`${this._getHost()}/api/apps`)
.then((response) => {
return response.ok
? response.json()
: {};
: [];
})
.then((manifest) => {
Object.keys.forEach((key) => {
app[key] = manifest[key];
});

return app;
.then((localApps) => {
return localApps
.filter((app) => app && app.id && !['ui'].includes(app.id))
.map((app) => {
app.type = 'local';
return app;
});
})
.catch((error) => {
console.warn('DappsStore:manifest', error);
console.warn('DappsStore:fetchLocal', error);
});
}

@action _readHiddenApps () {
_readHiddenApps () {
const stored = localStorage.getItem('hiddenApps');

if (stored) {
Expand Down

0 comments on commit 399748f

Please sign in to comment.