From 62607b0a3b8906817b3467ab75c07b4aa2e8845a Mon Sep 17 00:00:00 2001
From: Vyom Sharma <vyomshm@gmail.com>
Date: Tue, 6 Nov 2018 15:29:47 +0530
Subject: [PATCH] feat: adds support for swarm imports in Solidity

This commit enables users of Embark to import any Solidity contract using
the swarm protocol.

Example:

```
import "bzz:/someensdomain.eth/ERC725.sol";
```

Closes #766
---
 README.md                     |  4 +-
 lib/core/config.js            |  8 +--
 lib/core/file.js              |  6 +--
 lib/modules/solidity/index.js |  8 +--
 lib/modules/solidity/solcP.js |  4 +-
 lib/modules/solidity/solcW.js |  4 +-
 lib/utils/utils.js            | 22 ++++++--
 npm-shrinkwrap.json           | 97 ++++++++++++++++-------------------
 test/config.js                | 27 +++++++---
 test/utils.js                 | 35 +++++++++++++
 10 files changed, 137 insertions(+), 78 deletions(-)

diff --git a/README.md b/README.md
index 25290ef66..bea0f06b2 100644
--- a/README.md
+++ b/README.md
@@ -27,9 +27,10 @@ With Embark you can:
 * Manage different chains (e.g testnet, private net, livenet)
 * Easily manage complex systems of interdependent contracts.
 
-**Decentralized Storage (IPFS)**
+**Decentralized Storage (IPFS, Swarm)**
 * Easily Store & Retrieve Data on the DApp through EmbarkJS. Including uploading and retrieving files.
 * Deploy the full application to IPFS or Swarm.
+* Import and deploy contracts hosted on Swarm.
 
 
 **Decentralized Communication (Whisper, Orbit)**
@@ -44,4 +45,3 @@ $ npm -g install embark
 ```
 
 See [Complete Documentation](https://embark.status.im/docs/).
-
diff --git a/lib/core/config.js b/lib/core/config.js
index d9bdb8600..05036d070 100644
--- a/lib/core/config.js
+++ b/lib/core/config.js
@@ -31,7 +31,7 @@ var Config = function(options) {
   this.context = options.context || [constants.contexts.any];
   this.shownNoAccountConfigMsg = false; // flag to ensure "no account config" message is only displayed once to the user
   this.corsParts = [];
-  this.ipfsUrl = null;
+  this.providerUrl = null;
   this.events.setCommandHandler("config:cors:add", (url) => {
     this.corsParts.push(url);
     this._updateBlockchainCors();
@@ -320,15 +320,15 @@ Config.prototype.loadExternalContractsFiles = function() {
   let contracts = this.contractsConfig.contracts;
   let storageConfig = this.storageConfig;
   if (storageConfig && storageConfig.upload && storageConfig.upload.getUrl) {
-      this.ipfsUrl = storageConfig.upload.getUrl;
+      this.providerUrl = storageConfig.upload.getUrl;
   }
   for (let contractName in contracts) {
     let contract = contracts[contractName];
     if (!contract.file) {
       continue;
     }
-    if (contract.file.startsWith('http') || contract.file.startsWith('git') || contract.file.startsWith('ipfs')) {
-      const fileObj = utils.getExternalContractUrl(contract.file,this.ipfsUrl);
+    if (contract.file.startsWith('http') || contract.file.startsWith('git') || contract.file.startsWith('ipfs') || contract.file.startsWith('bzz')) {
+      const fileObj = utils.getExternalContractUrl(contract.file,this.providerUrl);
       if (!fileObj) {
         return this.logger.error(__("HTTP contract file not found") + ": " + contract.file);
       }
diff --git a/lib/core/file.js b/lib/core/file.js
index f6a5d7f7b..75942e4ac 100644
--- a/lib/core/file.js
+++ b/lib/core/file.js
@@ -16,7 +16,7 @@ class File {
     this.downloadedImports = false;
     this.importRemappings = []; // mapping downloaded imports to local file
     this.storageConfig = options.storageConfig;
-    this.ipfsUrl = null;
+    this.providerUrl = null;
   }
 
   parseFileForImport(content, isHttpContract, callback) {
@@ -36,10 +36,10 @@ class File {
     let newContent = content;
     let storageConfig = self.storageConfig;
     if (storageConfig && storageConfig.upload && storageConfig.upload.getUrl) {
-        self.ipfsUrl = storageConfig.upload.getUrl;
+        self.providerUrl = storageConfig.upload.getUrl;
     }
     while ((matches = regex.exec(content))) {
-      const httpFileObj = utils.getExternalContractUrl(matches[1],self.ipfsUrl);
+      const httpFileObj = utils.getExternalContractUrl(matches[1],self.providerUrl);
       const fileObj = {
         fileRelativePath: path.join(path.dirname(self.filename), matches[1]),
         url: `${pathWithoutFile}/${matches[1]}`
diff --git a/lib/modules/solidity/index.js b/lib/modules/solidity/index.js
index 82de63dc8..ac2f2d706 100644
--- a/lib/modules/solidity/index.js
+++ b/lib/modules/solidity/index.js
@@ -14,7 +14,7 @@ class Solidity {
     this.useDashboard = options.useDashboard;
     this.options = embark.config.embarkConfig.options.solc;
     this.storageConfig = embark.config.storageConfig;
-    this.ipfsUrl = null;
+    this.providerUrl = null;
 
     embark.registerCompiler(".sol", this.compile_solidity.bind(this));
 
@@ -71,12 +71,12 @@ class Solidity {
         if (self.solcAlreadyLoaded) {
           return callback();
         }
+        
         let storageConfig = self.storageConfig;
         if (storageConfig && storageConfig.upload && storageConfig.upload.getUrl) {
-            self.ipfsUrl = storageConfig.upload.getUrl;
+            self.providerUrl = storageConfig.upload.getUrl;
         }
-        self.solcW = new SolcW(self.embark, {logger: self.logger, events: self.events, ipc: self.ipc, useDashboard: self.useDashboard, ipfsUrl: self.ipfsUrl});
-
+        self.solcW = new SolcW(self.embark, {logger: self.logger, events: self.events, ipc: self.ipc, useDashboard: self.useDashboard, providerUrl: self.providerUrl});
 
         self.logger.info(__("loading solc compiler") + "..");
         self.solcW.load_compiler(function (err) {
diff --git a/lib/modules/solidity/solcP.js b/lib/modules/solidity/solcP.js
index 0fc13269a..9f7b6547f 100644
--- a/lib/modules/solidity/solcP.js
+++ b/lib/modules/solidity/solcP.js
@@ -13,12 +13,12 @@ class SolcProcess extends ProcessWrapper {
     super({pingParent: false});
     this._logger = options.logger;
     this._showSpinner = options.showSpinner === true;
-    this._ipfsUrl = options.ipfsUrl;
+    this._providerUrl = options.providerUrl;
   }
 
   findImports(filename) {
     if (filename.startsWith('http') || filename.startsWith('git')) {
-      const fileObj = Utils.getExternalContractUrl(filename,this._ipfsUrl);
+      const fileObj = Utils.getExternalContractUrl(filename, this._providerUrl);
       filename = fileObj.filePath;
     }
     if (fs.existsSync(filename)) {
diff --git a/lib/modules/solidity/solcW.js b/lib/modules/solidity/solcW.js
index 9d96df62b..c1c9f7d8c 100644
--- a/lib/modules/solidity/solcW.js
+++ b/lib/modules/solidity/solcW.js
@@ -14,7 +14,7 @@ class SolcW {
     this.compilerLoaded = false;
     this.solcProcess = null;
     this.useDashboard = options.useDashboard;
-    this.ipfsUrl = options.ipfsUrl;
+    this.providerUrl = options.providerUrl;
   }
 
   load_compiler(done) {
@@ -46,7 +46,7 @@ class SolcW {
       modulePath: utils.joinPath(__dirname, 'solcP.js'),
       logger: self.logger,
       events: self.events,
-      ipfsUrl: self.ipfsUrl,
+      providerUrl: self.providerUrl,
       silent: false
     });
 
diff --git a/lib/utils/utils.js b/lib/utils/utils.js
index 69e8d8fd4..ac36205ae 100644
--- a/lib/utils/utils.js
+++ b/lib/utils/utils.js
@@ -224,10 +224,12 @@ function proposeAlternative(word, _dictionary, _exceptions) {
   return propose(word, dictionary, {threshold: 0.3});
 }
 
-function getExternalContractUrl(file,ipfsUrl) {
+function getExternalContractUrl(file,providerUrl) {
   const constants = require('../constants');
   let url;
   const RAW_URL = 'https://raw.githubusercontent.com/';
+  const DEFAULT_SWARM_GATEWAY = 'https://swarm-gateways.net/';
+  const MALFORMED_SWARM_ERROR = 'Malformed Swarm gateway URL for ';
   const MALFORMED_ERROR = 'Malformed Github URL for ';
   const MALFORMED_IPFS_ERROR = 'Malformed IPFS URL for ';
   const IPFS_GETURL_NOTAVAILABLE = 'IPFS getUrl is not available. Please set it in your storage config. For more info: https://embark.status.im/docs/storage_configuration.html';
@@ -239,7 +241,7 @@ function getExternalContractUrl(file,ipfsUrl) {
     }
     url = `${RAW_URL}${match[1].replace('blob/', '')}`;
   } else if (file.startsWith('ipfs')) {
-    if(!ipfsUrl) {
+    if(!providerUrl) {
       console.error(IPFS_GETURL_NOTAVAILABLE);
       return null;
     }
@@ -255,7 +257,7 @@ function getExternalContractUrl(file,ipfsUrl) {
     if(match[2]) {
       matchResult += '/' + match[2];
     }
-    url = `${ipfsUrl}${matchResult}`;
+    url = `${providerUrl}${matchResult}`;
     return {
       url,
       filePath: constants.httpContractsDirectory + matchResult
@@ -282,6 +284,20 @@ function getExternalContractUrl(file,ipfsUrl) {
     url = `${RAW_URL}${match[2]}/${match[3]}/${branch}/${match[4]}`;
   } else if (file.startsWith('http')) {
     url = file;
+  } else if(file.startsWith('bzz')){
+    if(!providerUrl) {
+      url = DEFAULT_SWARM_GATEWAY + file;
+    } else {
+      let match = file.match(/bzz:\/([-a-zA-Z0-9]+)\/(.*)/);
+      if(!match){
+        match = file.match(/bzz:\/([-a-zA-Z0-9]+)/);
+        if(!match){
+          console.log(MALFORMED_SWARM_ERROR + file);
+          return null;
+        }
+      }
+      url = providerUrl + '/' + file;
+    }
   } else {
     return null;
   }
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index fa85f1b6a..4e3108eff 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -10839,8 +10839,7 @@
         "pem-jwk": "^1.5.1",
         "protons": "^1.0.1",
         "rsa-pem-to-jwk": "^1.1.3",
-        "tweetnacl": "^1.0.0",
-        "webcrypto-shim": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8"
+        "tweetnacl": "^1.0.0"
       },
       "dependencies": {
         "base-x": {
@@ -10858,6 +10857,10 @@
           "requires": {
             "base-x": "^3.0.2"
           }
+        },
+        "webcrypto-shim": {
+          "version": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8",
+          "from": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8"
         }
       }
     },
@@ -12572,12 +12575,12 @@
         },
         "minimist": {
           "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+          "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
           "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
         },
         "node-notifier": {
           "version": "4.6.1",
-          "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-4.6.1.tgz",
+          "resolved": "http://registry.npmjs.org/node-notifier/-/node-notifier-4.6.1.tgz",
           "integrity": "sha1-BW0UJE89zBzq3+aK+c/wxUc6M/M=",
           "requires": {
             "cli-usage": "^0.1.1",
@@ -15698,7 +15701,6 @@
           "resolved": "https://registry.npmjs.org/web3/-/web3-0.20.6.tgz",
           "integrity": "sha1-PpcwauAk+yThCj11yIQwJWIhUSA=",
           "requires": {
-            "bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934",
             "crypto-js": "^3.1.4",
             "utf8": "^2.1.1",
             "xhr2": "*",
@@ -15707,7 +15709,7 @@
           "dependencies": {
             "bignumber.js": {
               "version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934",
-              "from": "git+https://github.com/frozeman/bignumber.js-nolookahead.git"
+              "from": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934"
             }
           }
         }
@@ -15739,7 +15741,7 @@
       "dependencies": {
         "acorn": {
           "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+          "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
           "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
         },
         "ajv": {
@@ -15758,7 +15760,7 @@
         },
         "ansi-escapes": {
           "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
+          "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz",
           "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4="
         },
         "ansi-styles": {
@@ -15768,7 +15770,7 @@
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "requires": {
             "ansi-styles": "^2.2.1",
@@ -15805,7 +15807,7 @@
         },
         "eslint": {
           "version": "2.10.2",
-          "resolved": "https://registry.npmjs.org/eslint/-/eslint-2.10.2.tgz",
+          "resolved": "http://registry.npmjs.org/eslint/-/eslint-2.10.2.tgz",
           "integrity": "sha1-sjCUgv7wQ9MgM2WjIShebM4Bw9c=",
           "requires": {
             "chalk": "^1.1.3",
@@ -15844,7 +15846,7 @@
         },
         "eslint-plugin-react": {
           "version": "5.2.2",
-          "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz",
+          "resolved": "http://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz",
           "integrity": "sha1-fbBo4fVIf2hx5N7vNqOBwwPqwWE=",
           "requires": {
             "doctrine": "^1.2.2",
@@ -15853,7 +15855,7 @@
         },
         "espree": {
           "version": "3.1.4",
-          "resolved": "https://registry.npmjs.org/espree/-/espree-3.1.4.tgz",
+          "resolved": "http://registry.npmjs.org/espree/-/espree-3.1.4.tgz",
           "integrity": "sha1-BybXrIOvl6fISY2ps2OjYJ0qaKE=",
           "requires": {
             "acorn": "^3.1.0",
@@ -15899,7 +15901,7 @@
         },
         "inquirer": {
           "version": "0.12.0",
-          "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
+          "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz",
           "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=",
           "requires": {
             "ansi-escapes": "^1.1.0",
@@ -15924,7 +15926,7 @@
         },
         "onetime": {
           "version": "1.1.0",
-          "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
+          "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
           "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k="
         },
         "pluralize": {
@@ -15934,7 +15936,7 @@
         },
         "progress": {
           "version": "1.1.8",
-          "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
+          "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
           "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74="
         },
         "restore-cursor": {
@@ -15966,12 +15968,12 @@
         },
         "slice-ansi": {
           "version": "0.0.4",
-          "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
+          "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
           "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU="
         },
         "standard": {
           "version": "7.1.2",
-          "resolved": "https://registry.npmjs.org/standard/-/standard-7.1.2.tgz",
+          "resolved": "http://registry.npmjs.org/standard/-/standard-7.1.2.tgz",
           "integrity": "sha1-QBZu7sJAUGXRpPDj8VurxuJ0YH4=",
           "requires": {
             "eslint": "~2.10.2",
@@ -15995,7 +15997,7 @@
         },
         "table": {
           "version": "3.8.3",
-          "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz",
+          "resolved": "http://registry.npmjs.org/table/-/table-3.8.3.tgz",
           "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=",
           "requires": {
             "ajv": "^4.7.0",
@@ -16032,7 +16034,7 @@
         },
         "web3": {
           "version": "0.20.6",
-          "resolved": "https://registry.npmjs.org/web3/-/web3-0.20.6.tgz",
+          "resolved": "http://registry.npmjs.org/web3/-/web3-0.20.6.tgz",
           "integrity": "sha1-PpcwauAk+yThCj11yIQwJWIhUSA=",
           "requires": {
             "bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934",
@@ -16741,6 +16743,14 @@
           "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz",
           "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU="
         },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "eth-lib": {
           "version": "0.1.27",
           "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz",
@@ -16993,28 +17003,17 @@
           "integrity": "sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM=",
           "requires": {
             "underscore": "1.8.3",
-            "web3-core-helpers": "1.0.0-beta.34",
-            "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2"
+            "web3-core-helpers": "1.0.0-beta.34"
           },
           "dependencies": {
             "websocket": {
               "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
-              "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
+              "from": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
               "requires": {
                 "debug": "^2.2.0",
                 "nan": "^2.3.3",
                 "typedarray-to-buffer": "^3.1.2",
                 "yaeti": "^0.0.6"
-              },
-              "dependencies": {
-                "debug": {
-                  "version": "2.6.9",
-                  "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-                  "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-                  "requires": {
-                    "ms": "2.0.0"
-                  }
-                }
               }
             }
           }
@@ -17048,6 +17047,7 @@
           "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
           "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
           "requires": {
+            "debug": "^2.2.0",
             "nan": "^2.3.3",
             "typedarray-to-buffer": "^3.1.2",
             "yaeti": "^0.0.6"
@@ -20587,6 +20587,14 @@
           "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz",
           "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU="
         },
+        "debug": {
+          "version": "2.6.9",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+          "requires": {
+            "ms": "2.0.0"
+          }
+        },
         "eth-lib": {
           "version": "0.1.27",
           "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz",
@@ -20825,28 +20833,17 @@
           "integrity": "sha1-fecPG4Py3jZHZ3IVa+z+9uNRbrM=",
           "requires": {
             "underscore": "1.8.3",
-            "web3-core-helpers": "1.0.0-beta.34",
-            "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2"
+            "web3-core-helpers": "1.0.0-beta.34"
           },
           "dependencies": {
             "websocket": {
               "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
-              "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
+              "from": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
               "requires": {
                 "debug": "^2.2.0",
                 "nan": "^2.3.3",
                 "typedarray-to-buffer": "^3.1.2",
                 "yaeti": "^0.0.6"
-              },
-              "dependencies": {
-                "debug": {
-                  "version": "2.6.9",
-                  "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-                  "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-                  "requires": {
-                    "ms": "2.0.0"
-                  }
-                }
               }
             }
           }
@@ -20880,6 +20877,7 @@
           "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
           "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
           "requires": {
+            "debug": "^2.2.0",
             "nan": "^2.3.3",
             "typedarray-to-buffer": "^3.1.2",
             "yaeti": "^0.0.6"
@@ -21191,8 +21189,7 @@
       "integrity": "sha1-bUZ4Geoi3foba6FJjTHZVU4rBt0=",
       "requires": {
         "underscore": "1.8.3",
-        "web3-core-helpers": "1.0.0-beta.27",
-        "websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2"
+        "web3-core-helpers": "1.0.0-beta.27"
       },
       "dependencies": {
         "debug": {
@@ -21210,7 +21207,7 @@
         },
         "websocket": {
           "version": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
-          "from": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
+          "from": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
           "requires": {
             "debug": "^2.2.0",
             "nan": "^2.3.3",
@@ -21276,10 +21273,6 @@
         }
       }
     },
-    "webcrypto-shim": {
-      "version": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8",
-      "from": "github:dignifiedquire/webcrypto-shim#master"
-    },
     "webidl-conversions": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
diff --git a/test/config.js b/test/config.js
index 9f059baa1..febc19731 100644
--- a/test/config.js
+++ b/test/config.js
@@ -141,6 +141,9 @@ describe('embark.Config', function () {
         },
         {
           file: 'github.com/status-im/contracts/contracts/identity/ERC725.sol'
+        },
+        {
+          file: 'bzz:/1ffe993abc835f480f688d07ad75ad1dbdbd1ddb368a08b7ed4d3e400771dd63'
         }
       ];
       const expected = [
@@ -152,9 +155,9 @@ describe('embark.Config', function () {
           "importRemappings": [],
           "basedir": "",
           "resolver": undefined,
-          "downloadedImports": false,
-          "storageConfig": null,
-          "ipfsUrl": null
+          "storageConfig": undefined,
+          "providerUrl": undefined,
+          "downloadedImports": false
         },
         {
           "filename": ".embark/contracts/status-im/contracts/master/contracts/identity/ERC725.sol",
@@ -164,9 +167,21 @@ describe('embark.Config', function () {
           "importRemappings": [],
           "basedir": "",
           "resolver": undefined,
-          "downloadedImports": false,
-          "storageConfig": null,
-          "ipfsUrl": null
+          "storageConfig": undefined,
+          "providerUrl": undefined,
+          "downloadedImports": false
+        },
+        {
+          "filename": ".embark/contracts/bzz:/1ffe993abc835f480f688d07ad75ad1dbdbd1ddb368a08b7ed4d3e400771dd63",
+          "type": "http",
+          "path": "https://swarm-gateways.net/bzz:/1ffe993abc835f480f688d07ad75ad1dbdbd1ddb368a08b7ed4d3e400771dd63",
+          "pluginPath": '',
+          "importRemappings": [],
+          "basedir": "",
+          "resolver": undefined,
+          "storageConfig": undefined,
+          "providerUrl": undefined,
+          "downloadedImports": false
         }
       ];
       config.loadExternalContractsFiles();
diff --git a/test/utils.js b/test/utils.js
index e2d0ead77..0fae294ab 100644
--- a/test/utils.js
+++ b/test/utils.js
@@ -90,5 +90,40 @@ describe('embark.utils', function () {
         url: 'http://myurl.com/myFile.sol'
       });
     });
+
+    it('should get the correct default url for a correct bzz:/ swarm file', function () {
+      const swarmFile = 'bzz:/someensdomain.eth/ERC725.sol'
+      const fileObj = Utils.getExternalContractUrl(
+        swarmFile
+      );
+      assert.deepEqual(fileObj, {
+        filePath: constants.httpContractsDirectory + swarmFile,
+        url: 'https://swarm-gateways.net/' + swarmFile
+      });
+    });
+
+    it('should get the correct url for a correct bzz:/ swarm file when a http swarm gateway is explicitly provided', function () {
+      const swarmFile = 'bzz:/someensdomain.eth/ERC725.sol'
+      const fileObj = Utils.getExternalContractUrl(
+        swarmFile,
+        'http://localhost:8500'
+      );
+      assert.deepEqual(fileObj, {
+        filePath: constants.httpContractsDirectory + 'ERC725.sol',
+        url: 'http://localhost:8500/' + swarmFile
+      });
+    });
+
+    it('should get the correct url for a correct bzz:/ swarm file when a https swarm gateway is provided', function () {
+      const swarmFile = 'bzz:/1ffe993abc835f480f688d07ad75ad1dbdbd1ddb368a08b7ed4d3e400771dd63'
+      const fileObj = Utils.getExternalContractUrl(
+        swarmFile,
+        'https://swarm-gateways.net'
+      );
+      assert.deepEqual(fileObj, {
+        filePath: constants.httpContractsDirectory + swarmFile,
+        url: 'https://swarm-gateways.net/' + swarmFile
+      });
+    });
   });
 });