From 77929cefabfb97a6b95c558f32c4b7d0789dfaa6 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 12 Sep 2018 08:21:40 +0200 Subject: [PATCH 1/6] fix publish to swarm --- src/app/compiler/compiler-imports.js | 2 +- src/app/contract/publishOnSwarm.js | 31 +++++++++++++++++++--------- src/app/tabs/compile-tab.js | 7 +++++-- src/lib/cmdInterpreterAPI.js | 2 +- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/app/compiler/compiler-imports.js b/src/app/compiler/compiler-imports.js index 9be0ea60f4..adb09338eb 100644 --- a/src/app/compiler/compiler-imports.js +++ b/src/app/compiler/compiler-imports.js @@ -68,7 +68,7 @@ module.exports = class CompilerImports { { type: 'github', match: /^(https?:\/\/)?(www.)?github.com\/([^/]*\/[^/]*)\/(.*)/, handler: (match, cb) => { this.handleGithubCall(match[3], match[4], cb) } }, { type: 'http', match: /^(http?:\/\/?(.*))$/, handler: (match, cb) => { this.handleHttpCall(match[1], match[2], cb) } }, { type: 'https', match: /^(https?:\/\/?(.*))$/, handler: (match, cb) => { this.handleHttpCall(match[1], match[2], cb) } }, - { type: 'swarm', match: /^(bzz[ri]?:\/\/?(.*))$/, handler: (match, cb) => { this.handleSwarmImport(match[1], match[2], cb) } }, + { type: 'swarm', match: /^(bzz-raw?:\/\/?(.*))$/, handler: (match, cb) => { this.handleSwarmImport(match[1], match[2], cb) } }, { type: 'ipfs', match: /^(ipfs:\/\/?.+)/, handler: (match, cb) => { this.handleIPFS(match[1], cb) } } ] } diff --git a/src/app/contract/publishOnSwarm.js b/src/app/contract/publishOnSwarm.js index a3d044cc7d..cd4bdb3bac 100644 --- a/src/app/contract/publishOnSwarm.js +++ b/src/app/contract/publishOnSwarm.js @@ -7,11 +7,6 @@ module.exports = (contract, fileManager, cb, swarmVerifiedPublishCallBack) => { // gather list of files to publish var sources = [] - sources.push({ - content: contract.metadata, - hash: contract.metadataHash - }) - var metadata try { metadata = JSON.parse(contract.metadata) @@ -38,7 +33,8 @@ module.exports = (contract, fileManager, cb, swarmVerifiedPublishCallBack) => { } else { sources.push({ content: content, - hash: hash + hash: hash, + filename: fileName }) } cb() @@ -48,12 +44,27 @@ module.exports = (contract, fileManager, cb, swarmVerifiedPublishCallBack) => { cb(error) } else { // publish the list of sources in order, fail if any failed + var uploaded = [] async.eachSeries(sources, function (item, cb) { - swarmVerifiedPublish(item.content, item.hash, (error) => { + swarmVerifiedPublish(item.content, item.hash, (error, result) => { if (!error && swarmVerifiedPublishCallBack) swarmVerifiedPublishCallBack(item) + item.output = result + uploaded.push(item) + // TODO this is a fix cause Solidity metadata does not contain the right swarm hash (poc 0.3) + metadata.sources[item.filename].urls[0] = result.url cb(error) }) - }, cb) + }, () => { + swarmVerifiedPublish(JSON.stringify(metadata), '', (error, result) => { + uploaded.push({ + content: contract.metadata, + hash: contract.metadataHash, + filename: 'metadata.json', + output: result + }) + cb(error, uploaded) + }) + }) } }) } @@ -63,9 +74,9 @@ function swarmVerifiedPublish (content, expectedHash, cb) { if (err) { cb(err) } else if (ret !== expectedHash) { - cb('Hash mismatch') + cb(null, { message: 'hash mismatch between solidity bytecode and uploaded content.', url: 'bzz-raw://' + ret, hash: ret }) } else { - cb() + cb(null, { message: 'ok', url: 'bzz-raw://' + ret, hash: ret }) } }) } diff --git a/src/app/tabs/compile-tab.js b/src/app/tabs/compile-tab.js index 68464d5587..e4a90efa85 100644 --- a/src/app/tabs/compile-tab.js +++ b/src/app/tabs/compile-tab.js @@ -365,7 +365,7 @@ module.exports = class CompileTab { if (contract.metadata === undefined || contract.metadata.length === 0) { modalDialogCustom.alert('This contract does not implement all functions and thus cannot be published.') } else { - publishOnSwarm(contract, self._deps.fileManager, function (err) { + publishOnSwarm(contract, self._deps.fileManager, function (err, uploaded) { if (err) { try { err = JSON.stringify(err) @@ -373,7 +373,10 @@ module.exports = class CompileTab { modalDialogCustom.alert(yo`Failed to publish metadata file to swarm, please check the Swarm gateways is available ( swarm-gateways.net ).
${err}
`) } else { - modalDialogCustom.alert(yo`Metadata published successfully.
The Swarm address of the metadata file is available in the contract details.
`) + var result = yo`
${uploaded.map((value) => { + return yo`
${value.filename} :
${value.output.url}
` + })}
` + modalDialogCustom.alert(yo`Metadata published successfully.
${result}
`) } }, function (item) { // triggered each time there's a new verified publish (means hash correspond) self._deps.swarmfileProvider.addReadOnly(item.hash, item.content) diff --git a/src/lib/cmdInterpreterAPI.js b/src/lib/cmdInterpreterAPI.js index f0923d05ff..cef5a05579 100644 --- a/src/lib/cmdInterpreterAPI.js +++ b/src/lib/cmdInterpreterAPI.js @@ -30,7 +30,7 @@ class CmdInterpreterAPI { self.commandHelp = { 'remix.debug(hash)': 'Start debugging a transaction.', 'remix.loadgist(id)': 'Load a gist in the file explorer.', - 'remix.loadurl(url)': 'Load the given url in the file explorer. The url can be of type github, swarm or ipfs.', + 'remix.loadurl(url)': 'Load the given url in the file explorer. The url can be of type github, swarm, ipfs or raw http', 'remix.setproviderurl(url)': 'Change the current provider to Web3 provider and set the url endpoint.', 'remix.execute(filepath)': 'Run the script specified by file path. If filepath is empty, script currently displayed in the editor is executed.', 'remix.exeCurrent()': 'Run the script currently displayed in the editor', From e78ed7e680463e656fae22d1c6ed765a7c63b5ec Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 12 Sep 2018 09:10:44 +0200 Subject: [PATCH 2/6] add callback to provider set --- src/app/files/browser-files-tree.js | 4 +++- src/app/files/browser-files.js | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/app/files/browser-files-tree.js b/src/app/files/browser-files-tree.js index b9bde21c2d..16ce5a60c2 100644 --- a/src/app/files/browser-files-tree.js +++ b/src/app/files/browser-files-tree.js @@ -53,11 +53,12 @@ function FilesTree (name, storage) { return content } - this.set = function (path, content) { + this.set = function (path, content, cb) { var unprefixedpath = this.removePrefix(path) updateRefs(unprefixedpath, 'add') var exists = storage.exists(unprefixedpath) if (!storage.set(unprefixedpath, content)) { + if (cb) cb('error updating ' + path) return false } if (!exists) { @@ -65,6 +66,7 @@ function FilesTree (name, storage) { } else { event.trigger('fileChanged', [this.type + '/' + unprefixedpath]) } + if (cb) cb() return true } diff --git a/src/app/files/browser-files.js b/src/app/files/browser-files.js index e0a25e6db8..8179622f02 100644 --- a/src/app/files/browser-files.js +++ b/src/app/files/browser-files.js @@ -38,16 +38,18 @@ function Files (storage) { return content } - this.set = function (path, content) { + this.set = function (path, content, cb) { var unprefixedpath = this.removePrefix(path) // NOTE: ignore the config file if (path === '.remix.config') { + if (cb) cb('change not allowed') return false } if (!this.isReadOnly(unprefixedpath)) { var exists = storage.exists(unprefixedpath) if (!storage.set(unprefixedpath, content)) { + if (cb) cb('error updating ' + path) return false } if (!exists) { @@ -55,9 +57,10 @@ function Files (storage) { } else { event.trigger('fileChanged', [this.type + '/' + unprefixedpath]) } + if (cb) cb() return true } - + if (cb) cb('is read only') return false } From 840899b41c6e543eccd240ef5628beba83020b6c Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 12 Sep 2018 09:12:23 +0200 Subject: [PATCH 3/6] sync editor to current saved content --- src/app/files/fileManager.js | 16 ++++++++++++++++ src/app/plugin/pluginAPI.js | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/app/files/fileManager.js b/src/app/files/fileManager.js index eea9461749..3bcdf045f3 100644 --- a/src/app/files/fileManager.js +++ b/src/app/files/fileManager.js @@ -195,6 +195,22 @@ class FileManager { } } } + + syncEditor (path) { + var self = this + var currentFile = this._deps.config.get('currentFile') + if (path !== currentFile) return + + var provider = this.fileProviderOf(currentFile) + if (provider) { + provider.get(currentFile, (error, content) => { + if (error) console.log(error) + self._deps.editor.setText(content) + }) + } else { + console.log('cannot save ' + currentFile + '. Does not belong to any explorer') + } + } } module.exports = FileManager diff --git a/src/app/plugin/pluginAPI.js b/src/app/plugin/pluginAPI.js index ce7f355c0e..80038812fa 100644 --- a/src/app/plugin/pluginAPI.js +++ b/src/app/plugin/pluginAPI.js @@ -97,7 +97,8 @@ module.exports = (pluginManager, fileProviders, fileManager, compiler, udapp) => if (provider) { // TODO add approval to user for external plugin to set the content of the given `path` provider.set(path, content, (error) => { - cb(error) + if (error) return cb(error) + fileManager.syncEditor(path) }) } else { cb(path + ' not available') From dc4a1941c60cc66a87331235f6381d0c34eb805c Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 12 Sep 2018 09:12:40 +0200 Subject: [PATCH 4/6] add getFilesFromPath --- src/app/plugin/pluginAPI.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/plugin/pluginAPI.js b/src/app/plugin/pluginAPI.js index 80038812fa..81bd2e00cb 100644 --- a/src/app/plugin/pluginAPI.js +++ b/src/app/plugin/pluginAPI.js @@ -73,6 +73,9 @@ module.exports = (pluginManager, fileProviders, fileManager, compiler, udapp) => } }, editor: { + getFilesFromPath: (mod, path, cb) => { + fileManager.filesFromPath(path, cb) + }, getCurrentFile: (mod, cb) => { var path = fileManager.currentFile() if (!path) { From 173a43ab1600f5a9efd1ead6a690e07d45e20974 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 12 Sep 2018 09:13:55 +0200 Subject: [PATCH 5/6] API: execute runTx and getAccounts for all network except mainnet --- src/app/plugin/pluginAPI.js | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/app/plugin/pluginAPI.js b/src/app/plugin/pluginAPI.js index 81bd2e00cb..a6c8f8dd54 100644 --- a/src/app/plugin/pluginAPI.js +++ b/src/app/plugin/pluginAPI.js @@ -48,22 +48,32 @@ module.exports = (pluginManager, fileProviders, fileManager, compiler, udapp) => }, udapp: { runTx: (mod, tx, cb) => { - if (executionContext.getProvider() !== 'vm') return cb('plugin API does not allow sending a transaction through a web3 connection. Only vm mode is allowed') - udapp.silentRunTx(tx, (error, result) => { + executionContext.detectNetwork((error, network) => { if (error) return cb(error) - cb(null, { - transactionHash: result.transactionHash, - status: result.result.status, - gasUsed: '0x' + result.result.gasUsed.toString('hex'), - error: result.result.vm.exceptionError, - return: result.result.vm.return ? '0x' + result.result.vm.return.toString('hex') : '0x', - createdAddress: result.result.createdAddress ? '0x' + result.result.createdAddress.toString('hex') : undefined + if (network.name === 'Main' && network.id === '1') { + return cb('It is not allowed to make this action against mainnet') + } + udapp.silentRunTx(tx, (error, result) => { + if (error) return cb(error) + cb(null, { + transactionHash: result.transactionHash, + status: result.result.status, + gasUsed: '0x' + result.result.gasUsed.toString('hex'), + error: result.result.vm.exceptionError, + return: result.result.vm.return ? '0x' + result.result.vm.return.toString('hex') : '0x', + createdAddress: result.result.createdAddress ? '0x' + result.result.createdAddress.toString('hex') : undefined + }) }) }) }, getAccounts: (mod, cb) => { - if (executionContext.getProvider() !== 'vm') return cb('plugin API does not allow retrieving accounts through a web3 connection. Only vm mode is allowed') - udapp.getAccounts(cb) + executionContext.detectNetwork((error, network) => { + if (error) return cb(error) + if (network.name === 'Main' && network.id === '1') { + return cb('It is not allowed to make this action against mainnet') + } + udapp.getAccounts(cb) + }) }, createVMAccount: (mod, privateKey, balance, cb) => { if (executionContext.getProvider() !== 'vm') return cb('plugin API does not allow creating a new account through web3 connection. Only vm mode is allowed') From 81780e8cb0f9c059aedfcfdad89af6a590615e78 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 12 Sep 2018 09:14:12 +0200 Subject: [PATCH 6/6] manual test fetFilesFromPath --- test-browser/plugin/index.html | 1 + test-browser/plugin/plugin.js | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/test-browser/plugin/index.html b/test-browser/plugin/index.html index f81dc19b70..d5bcaa2202 100644 --- a/test-browser/plugin/index.html +++ b/test-browser/plugin/index.html @@ -48,6 +48,7 @@ getcontentof
getcurrent
sethighlight
+ getfilesfrompath

diff --git a/test-browser/plugin/plugin.js b/test-browser/plugin/plugin.js index 27e1305de3..d09e39bc72 100644 --- a/test-browser/plugin/plugin.js +++ b/test-browser/plugin/plugin.js @@ -73,4 +73,9 @@ window.onload = function () { extension.call('editor', 'highlight', [document.getElementById('filename').value, document.getElementById('valuetosend').value, document.getElementById('valuetosend2').value], function (error, result) { console.log(error, result) }) }) + + document.querySelector('input#getfilesfrompath').addEventListener('click', function () { + extension.call('editor', 'getFilesFromPath', [document.getElementById('filename').value], + function (error, result) { console.log(error, result) }) + }) }