diff --git a/pom.xml b/pom.xml
index 1a37142e64dcde75bec6b23cb852f4fcb0089deb..05d1ca3a064ed4aec8cf691471fb7f6185e84c04 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,5 +56,12 @@
             <artifactId>reflections</artifactId>
             <version>0.9.10</version>
         </dependency>
+        <!-- https://mvnrepository.com/artifact/org.gephi/gephi-toolkit -->
+        <dependency>
+            <groupId>org.gephi</groupId>
+            <artifactId>gephi-toolkit</artifactId>
+            <version>0.9.1</version>
+        </dependency>
+
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/src/main/java/fucoin/actions/control/ActionAddOverlayNeighbours.java b/src/main/java/fucoin/actions/control/ActionAddOverlayNeighbours.java
new file mode 100644
index 0000000000000000000000000000000000000000..890b6ec06ec9a938bc086a79047d4c8973df6b19
--- /dev/null
+++ b/src/main/java/fucoin/actions/control/ActionAddOverlayNeighbours.java
@@ -0,0 +1,26 @@
+package fucoin.actions.control;
+
+import akka.actor.ActorRef;
+import akka.actor.UntypedActorContext;
+import fucoin.actions.ClientAction;
+import fucoin.wallet.AbstractWallet;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author davidbohn
+ */
+public class ActionAddOverlayNeighbours extends ClientAction {
+
+    protected List<ActorRef> neighbours;
+
+    public ActionAddOverlayNeighbours(List<ActorRef> neighbours) {
+        this.neighbours = neighbours;
+    }
+
+    @Override
+    protected void onAction(ActorRef sender, ActorRef self, UntypedActorContext context, AbstractWallet abstractNode) {
+        neighbours.stream().forEach(abstractNode::addOverlayNeighbour);
+    }
+}
diff --git a/src/main/java/fucoin/actions/join/ActionJoinAnswer.java b/src/main/java/fucoin/actions/join/ActionJoinAnswer.java
index 89c4aadba026ce04ef9b2190b21566fdb7e68874..4b6cdd2f96bed048e45ba74ed5e81927f4e6f29b 100644
--- a/src/main/java/fucoin/actions/join/ActionJoinAnswer.java
+++ b/src/main/java/fucoin/actions/join/ActionJoinAnswer.java
@@ -28,7 +28,7 @@ public class ActionJoinAnswer extends ClientAction {
     protected void onAction(ActorRef sender, ActorRef self,
                             UntypedActorContext context, AbstractWallet wallet) {
 
-        wallet.addLogMsg("Addressed to " + self.path().name() + " from " + sender.path().name() + ": someNeighbors:" + someNeighbors);
+        //wallet.addLogMsg("Addressed to " + self.path().name() + " from " + sender.path().name() + ": someNeighbors:" + someNeighbors);
 
         // your neighbours? my neighbours!
         for (Entry<String, ActorRef> neighbor : someNeighbors.entrySet()) {
diff --git a/src/main/java/fucoin/actions/transaction/ActionCommitDistributedCommittedTransfer.java b/src/main/java/fucoin/actions/transaction/ActionCommitDistributedCommittedTransfer.java
index 641fc121d4a38b970df45fb99e3d9c179bc56ad6..30c236cce5ebddbac4fbe059253555c503c36c0c 100644
--- a/src/main/java/fucoin/actions/transaction/ActionCommitDistributedCommittedTransfer.java
+++ b/src/main/java/fucoin/actions/transaction/ActionCommitDistributedCommittedTransfer.java
@@ -43,7 +43,7 @@ public class ActionCommitDistributedCommittedTransfer extends ClientAction {
     @Override
     protected void onAction(ActorRef sender, ActorRef self,
                             UntypedActorContext context, AbstractWallet wallet) {
-        wallet.addLogMsg("ActionCommitDistributedCommittedTransfer is granted? " + granted);
+        //wallet.addLogMsg("ActionCommitDistributedCommittedTransfer is granted? " + granted);
         if (granted) {
 
             if (source.compareTo(self) == 0) {
@@ -75,7 +75,6 @@ public class ActionCommitDistributedCommittedTransfer extends ClientAction {
             }
 
         }
-        //wallet.addLogMsg("wallet.amounts:" + wallet.amounts);
     }
 
 }
diff --git a/src/main/java/fucoin/actions/transaction/ActionInvokeDistributedCommittedTransfer.java b/src/main/java/fucoin/actions/transaction/ActionInvokeDistributedCommittedTransfer.java
index b277c64a9c613d842769089275996769947c0f60..82490ee04492fc29e4741b02128160d9b9f8fa83 100644
--- a/src/main/java/fucoin/actions/transaction/ActionInvokeDistributedCommittedTransfer.java
+++ b/src/main/java/fucoin/actions/transaction/ActionInvokeDistributedCommittedTransfer.java
@@ -28,9 +28,9 @@ public class ActionInvokeDistributedCommittedTransfer extends CoordinatorTransac
     @Override
     protected void onAction(ActorRef sender, ActorRef self,
                             UntypedActorContext context, SuperVisorImpl superVisor) {
-        superVisor.addLogMsg("invoke transaction " + source.path().name() +
+        /*superVisor.addLogMsg("invoke transaction " + source.path().name() +
                 " sends " + amount +
-                " to " + target.path().name());
+                " to " + target.path().name());*/
 
         long timeout = System.currentTimeMillis() + 500;
 
diff --git a/src/main/java/fucoin/actions/transaction/ActionPrepareDistributedCommittedTransferAnswer.java b/src/main/java/fucoin/actions/transaction/ActionPrepareDistributedCommittedTransferAnswer.java
index db21831de14d3e95c2d30f335586f35052dc307c..d7c9f45f6d58c11eaa6895e4ad5633f42c8ae83c 100644
--- a/src/main/java/fucoin/actions/transaction/ActionPrepareDistributedCommittedTransferAnswer.java
+++ b/src/main/java/fucoin/actions/transaction/ActionPrepareDistributedCommittedTransferAnswer.java
@@ -28,7 +28,7 @@ public class ActionPrepareDistributedCommittedTransferAnswer extends Coordinator
     protected void onAction(ActorRef sender, ActorRef self,
                             UntypedActorContext context, SuperVisorImpl superVisor) {
 
-        superVisor.addLogMsg("granted?" + granted);
+        //superVisor.addLogMsg("granted?" + granted);
 
         DistributedCommittedTransferRequest request = superVisor.getRequest(id);
 
diff --git a/src/main/java/fucoin/configurations/AbstractConfiguration.java b/src/main/java/fucoin/configurations/AbstractConfiguration.java
index 8493704af98937d47688ad0b57323902394e0d8d..eba6a5e4a811f663cfa488cfa56d397738c93b2e 100644
--- a/src/main/java/fucoin/configurations/AbstractConfiguration.java
+++ b/src/main/java/fucoin/configurations/AbstractConfiguration.java
@@ -2,9 +2,11 @@ package fucoin.configurations;
 
 import akka.actor.ActorRef;
 import akka.actor.Props;
+import akka.dispatch.Futures;
 import akka.pattern.Patterns;
 import akka.util.Timeout;
 import fucoin.AbstractNode;
+import fucoin.actions.control.ActionAddOverlayNeighbours;
 import fucoin.actions.control.ActionAnnounceWalletCreation;
 import fucoin.actions.control.ActionWalletSendMoney;
 import fucoin.actions.join.ActionTellSupervisor;
@@ -12,16 +14,20 @@ import fucoin.actions.transaction.ActionGetAmount;
 import fucoin.actions.transaction.ActionGetAmountAnswer;
 import fucoin.actions.transaction.ActionNotifyObserver;
 import fucoin.configurations.internal.ConfigurationCreator;
+import fucoin.configurations.internal.NodeHelper;
 import fucoin.supervisor.SuperVisorImpl;
 import fucoin.wallet.WalletImpl;
+import org.gephi.graph.api.Edge;
+import org.gephi.graph.api.Graph;
+import org.gephi.graph.api.Node;
 import scala.concurrent.Await;
 import scala.concurrent.Future;
+import scala.concurrent.Promise;
 import scala.concurrent.duration.Duration;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
 import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.Collectors;
 
 /**
  *
@@ -30,11 +36,14 @@ public abstract class AbstractConfiguration extends AbstractNode {
 
     private ActorRef superVisor;
 
-    private final List<ActorRef> activeActors = new ArrayList<>();
+    private final HashMap<String, ActorRef> activeActors = new HashMap<>();
 
     private Timeout timeout = new Timeout(Duration.create(10, "seconds"));
 
     private int remainingTransactions;
+    private Promise<Void> transactionFinished;
+
+    private ActorRef lastWallet = null;
 
     public static Props props(Class configurationClass) {
 
@@ -58,21 +67,18 @@ public abstract class AbstractConfiguration extends AbstractNode {
      */
     private ActorRef createWallet(String name, boolean createGUI) {
         Props props;
-        int numOfWallets = activeActors.size();
-        if (numOfWallets == 0) {
-            props = WalletImpl.props(null, name, createGUI);
-        } else {
-            props = WalletImpl.props(activeActors.get(numOfWallets - 1), name, createGUI);
-        }
 
-        ActorRef actorRef = context().actorOf(props, name);
+        props = WalletImpl.props(lastWallet, name, createGUI);
 
-        activeActors.add(actorRef);
+        ActorRef actorRef = context().actorOf(props, name);
+        activeActors.put(name, actorRef);
 
-        if (numOfWallets == 0) {
+        if (lastWallet == null) {
             actorRef.tell(new ActionTellSupervisor(superVisor), superVisor);
         }
 
+        lastWallet = actorRef;
+
         return actorRef;
     }
 
@@ -90,25 +96,40 @@ public abstract class AbstractConfiguration extends AbstractNode {
         Await.result(future, timeout.duration());
     }
 
+    public void spawnWalletsFromNodes(Collection<Node> nodes, boolean createGUI) throws Exception {
+        Future<Object> future = Patterns.ask(superVisor, new ActionAnnounceWalletCreation(nodes.size(), self()), timeout);
+        for (Node node : nodes) {
+            String nameOfTheWallet = NodeHelper.nameOfNode(node);
+            createWallet(nameOfTheWallet, createGUI);
+        }
+        Await.result(future, timeout.duration());
+    }
+
     /**
      * Fetch a random wallet
      */
     public ActorRef getRandomWallet() {
-        return activeActors.get(ThreadLocalRandom.current().nextInt(activeActors.size()));
+        return wallets().get(ThreadLocalRandom.current().nextInt(activeActors.size()));
     }
 
     public List<ActorRef> wallets() {
-        return this.activeActors;
+        return new ArrayList<>(this.activeActors.values());
     }
 
-    protected void randomTransactions(int number, int maxTransactionsAtTheSameTime) {
+    public ActorRef walletByName(String name) {
+        return activeActors.get(name);
+    }
 
+    protected Future<Void> randomTransactions(int number, int maxTransactionsAtTheSameTime) {
+        this.transactionFinished = Futures.promise();
         remainingTransactions = number;
 
         for (int i = 0; i < Math.min(number, maxTransactionsAtTheSameTime); i++) {
             nextRandomTransaction();
         }
 
+        return transactionFinished.future();
+
     }
 
     private void nextRandomTransaction() {
@@ -116,8 +137,9 @@ public abstract class AbstractConfiguration extends AbstractNode {
         try {
             randomTransaction();
         } catch (Exception e) {
-            System.err.println("Error while trying to perform a random transaction: "+e.getMessage());
+            System.err.println("Error while trying to perform a random transaction: " + e.getMessage());
             remainingTransactions = 0;
+            transactionFinished = null;
         }
     }
 
@@ -169,6 +191,11 @@ public abstract class AbstractConfiguration extends AbstractNode {
 
             if (remainingTransactions > 0) {
                 nextRandomTransaction();
+            } else {
+                if (transactionFinished != null) {
+                    transactionFinished.success(null);
+                    transactionFinished = null;
+                }
             }
         }
     }
@@ -181,4 +208,35 @@ public abstract class AbstractConfiguration extends AbstractNode {
     }
 
     public abstract void run();
+
+    protected void createOverlayNetwork(Graph g) {
+        Collection<Node> nodes = g.getNodes().toCollection();
+
+        try {
+            spawnWalletsFromNodes(nodes, false);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        nodes.stream().forEach(node -> {
+            ActorRef wallet = getWalletForNode(node);
+            Edge[] edges = g.getEdges(node).toArray();
+
+            // Search for all reachable neighbours of the node
+            // by filtering the list of incident edges of the node
+            // and retrieve the respective ActorRef instance
+            List<ActorRef> overlayNeighbours = Arrays.stream(edges).filter(edge -> !edge.isDirected() || edge.getSource() == node).map(edge -> {
+                if (edge.getSource() == node) {
+                    return edge.getTarget();
+                }
+                return edge.getSource();
+            }).map(this::getWalletForNode).collect(Collectors.toList());
+
+            wallet.tell(new ActionAddOverlayNeighbours(overlayNeighbours), self());
+        });
+    }
+
+    protected ActorRef getWalletForNode(Node node) {
+        return walletByName(NodeHelper.nameOfNode(node));
+    }
 }
diff --git a/src/main/java/fucoin/configurations/DefaultConfiguration.java b/src/main/java/fucoin/configurations/DefaultConfiguration.java
index 403d071f351c51d413d9e38fd07331f52625a13f..6b5a3565cae995040e504ae510eef27c74a2b158 100644
--- a/src/main/java/fucoin/configurations/DefaultConfiguration.java
+++ b/src/main/java/fucoin/configurations/DefaultConfiguration.java
@@ -1,19 +1,11 @@
 package fucoin.configurations;
 
 import akka.actor.ActorRef;
-import akka.pattern.Patterns;
 import akka.util.Timeout;
 import fucoin.actions.control.ActionWalletSendMoney;
-import fucoin.actions.transaction.ActionGetAmount;
-import fucoin.actions.transaction.ActionGetAmountAnswer;
-import fucoin.actions.transaction.ActionNotifyObserver;
 import fucoin.configurations.internal.ConfigurationName;
-import scala.concurrent.Await;
-import scala.concurrent.Future;
 import scala.concurrent.duration.Duration;
 
-import java.util.Collections;
-import java.util.List;
 import java.util.concurrent.ThreadLocalRandom;
 
 /**
diff --git a/src/main/java/fucoin/configurations/GephiConfiguration.java b/src/main/java/fucoin/configurations/GephiConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..bdf2360515b9a9662276ee73bd09a6b6c04dd0bc
--- /dev/null
+++ b/src/main/java/fucoin/configurations/GephiConfiguration.java
@@ -0,0 +1,69 @@
+package fucoin.configurations;
+
+import akka.actor.ActorRef;
+import akka.dispatch.OnSuccess;
+import akka.pattern.Patterns;
+import akka.util.Timeout;
+import fucoin.actions.transaction.ActionGetAmount;
+import fucoin.actions.transaction.ActionGetAmountAnswer;
+import fucoin.configurations.internal.ConfigurationName;
+import fucoin.configurations.internal.GephiLoader;
+import fucoin.configurations.internal.NodeHelper;
+import fucoin.gui.gephi.GephiFileSelector;
+import fucoin.gui.gephi.GraphWindow;
+import org.gephi.graph.api.Graph;
+import org.gephi.graph.api.Node;
+import scala.concurrent.Future;
+import scala.concurrent.duration.Duration;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+@ConfigurationName("Gephi Test Configuration")
+public class GephiConfiguration extends AbstractConfiguration {
+
+    private Timeout timeout = new Timeout(Duration.create(10, "seconds"));
+
+    @Override
+    public void run() {
+        initSupervisor();
+
+        GephiLoader gephiLoader = new GephiLoader();
+        GephiFileSelector fileSelector = new GephiFileSelector();
+
+        Graph g;
+        File selectedTopology;
+        try {
+            selectedTopology = fileSelector.selectTopology();
+            g = gephiLoader.loadFile(selectedTopology);
+        } catch (URISyntaxException | IOException e) {
+            e.printStackTrace();
+            return;
+        }
+
+        createOverlayNetwork(g);
+
+        GraphWindow graphWindow = new GraphWindow();
+        graphWindow.setDisplayedFilename(selectedTopology.getName());
+        graphWindow.setVisible(true);
+
+        // add a click listener for displaying further information about a wallet when clicking on a node
+        graphWindow.addNodeClickHandler((node, event) -> {
+
+            // get associated wallet and ask for its amount
+            ActorRef wallet = getWalletForNode(node);
+
+            Future<Object> future = Patterns.ask(wallet, new ActionGetAmount(), timeout);
+            future.onSuccess(new OnSuccess<Object>() {
+                @Override
+                public void onSuccess(Object result) throws Throwable {
+                    // display the amount when an answer is received
+                    ActionGetAmountAnswer answer = (ActionGetAmountAnswer) result;
+                    graphWindow.setInfobarText(NodeHelper.nameOfNode(node)+" has "+answer.amount+" FUCs");
+                }
+            }, context().dispatcher());
+        });
+
+    }
+}
diff --git a/src/main/java/fucoin/configurations/MassWalletConfiguration.java b/src/main/java/fucoin/configurations/MassWalletConfiguration.java
index fcaaadf3cea173e7b0cf3fa6fc038fbee5dcecae..14b4979a14ef1cf6abf82476a6e3bf6b0906aa6c 100644
--- a/src/main/java/fucoin/configurations/MassWalletConfiguration.java
+++ b/src/main/java/fucoin/configurations/MassWalletConfiguration.java
@@ -1,5 +1,7 @@
 package fucoin.configurations;
 
+import akka.dispatch.OnSuccess;
+import fucoin.actions.transaction.ActionGetAmountAnswer;
 import fucoin.configurations.internal.ConfigurationName;
 
 /**
@@ -11,13 +13,20 @@ public class MassWalletConfiguration extends AbstractConfiguration {
     public void run() {
         initSupervisor();
         try {
-            spawnWallets(200, false);
+            spawnWallets(2, false);
             System.out.println("Wallet spawning done!");
         } catch (Exception e) {
             System.out.println("Wallet spawning timed out!");
         }
 
-        randomTransactions(100, 10);
+        randomTransactions(5, 2).onSuccess(new OnSuccess<Void>() {
+            @Override
+            public void onSuccess(Void result) {
+                // You can start your algorithm here if you want to.
+                // Alternatively, you can also notify the user that all transactions are finished
+                System.out.println("All random transactions finished!");
+            }
+        }, context().dispatcher());
     }
 
     @Override
diff --git a/src/main/java/fucoin/configurations/internal/GephiLoader.java b/src/main/java/fucoin/configurations/internal/GephiLoader.java
new file mode 100644
index 0000000000000000000000000000000000000000..b88f56f707473f2c03cca38f1f6ff0ed0c7e6b51
--- /dev/null
+++ b/src/main/java/fucoin/configurations/internal/GephiLoader.java
@@ -0,0 +1,54 @@
+package fucoin.configurations.internal;
+
+import org.gephi.graph.api.Graph;
+import org.gephi.graph.api.GraphController;
+import org.gephi.io.importer.api.Container;
+import org.gephi.io.importer.api.ImportController;
+import org.gephi.io.processor.plugin.DefaultProcessor;
+import org.gephi.project.api.ProjectController;
+import org.gephi.project.api.Workspace;
+import org.openide.util.Lookup;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+
+public class GephiLoader {
+
+    private Workspace workspace;
+
+    /**
+     * Load a graph file that is in the resources directory of the application
+     *
+     * @throws URISyntaxException
+     * @throws FileNotFoundException
+     */
+    public Graph loadFileFromResources(String path) throws URISyntaxException, FileNotFoundException {
+        return loadFile(new File(getClass().getResource(path).toURI()));
+    }
+
+    /**
+     * Initialize the Gephi toolkit and load the provided file
+     *
+     * @throws FileNotFoundException
+     */
+    public Graph loadFile(File file) throws FileNotFoundException {
+        ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
+
+        pc.newProject();
+        workspace = pc.getCurrentWorkspace();
+
+        Container container;
+        ImportController importController = Lookup.getDefault().lookup(ImportController.class);
+        container = importController.importFile(file);
+
+
+        importController.process(container, new DefaultProcessor(), workspace);
+
+        return Lookup.getDefault().lookup(GraphController.class).getGraphModel(workspace).getGraph();
+    }
+
+    public Workspace getWorkspace() {
+        return workspace;
+    }
+}
diff --git a/src/main/java/fucoin/configurations/internal/NodeHelper.java b/src/main/java/fucoin/configurations/internal/NodeHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..359dcdeccf4246018b90aea548ed954fdd9d10f4
--- /dev/null
+++ b/src/main/java/fucoin/configurations/internal/NodeHelper.java
@@ -0,0 +1,23 @@
+package fucoin.configurations.internal;
+
+import org.gephi.graph.api.Node;
+
+public class NodeHelper {
+
+    public static String nameOfNode(Node n) {
+        String label = n.getLabel();
+
+        if (label == null || label.isEmpty()) {
+            return "Wallet" + n.getId();
+        }
+
+        label = label.replace(" ", "_");
+
+        if (Character.isDigit(label.charAt(0))) {
+            return "Wallet" + label;
+        }
+
+        return label;
+    }
+
+}
diff --git a/src/main/java/fucoin/gui/gephi/GephiFileSelector.java b/src/main/java/fucoin/gui/gephi/GephiFileSelector.java
new file mode 100644
index 0000000000000000000000000000000000000000..d4196a616dbd70baaa0eb30f73df6dadbd9720c9
--- /dev/null
+++ b/src/main/java/fucoin/gui/gephi/GephiFileSelector.java
@@ -0,0 +1,47 @@
+package fucoin.gui.gephi;
+
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class GephiFileSelector {
+
+    /**
+     * Display a file selector to select a gephi graph file
+     * @return the selected file or the first graph in the resources directory if none selected
+     * @throws IOException
+     * @throws URISyntaxException
+     */
+    public File selectTopology() throws IOException, URISyntaxException {
+        JFileChooser fileChooser = new JFileChooser(new File(getClass().getResource("/").toURI()));
+        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+        FileNameExtensionFilter fileNameExtensionFilter = new FileNameExtensionFilter("Graph Files", "gexf");
+        fileChooser.setFileFilter(fileNameExtensionFilter);
+        int result = fileChooser.showOpenDialog(null);
+
+        if (result == JFileChooser.APPROVE_OPTION) {
+            return fileChooser.getSelectedFile();
+        }
+
+        return getBundledTopologies().get(0);
+    }
+
+    /**
+     * Get a list of all bundled topology files (i.e. that are stored in the resources)
+     * @throws URISyntaxException
+     * @throws IOException
+     */
+    public List<File> getBundledTopologies() throws URISyntaxException, IOException {
+        return Files.list(Paths.get(getClass().getResource("/").toURI()))
+                .filter(Files::isRegularFile)
+                .filter(path -> path.toString().toLowerCase().endsWith(".gexf"))
+                .map(Path::toFile).collect(Collectors.toList());
+    }
+}
diff --git a/src/main/java/fucoin/gui/gephi/GraphWindow.java b/src/main/java/fucoin/gui/gephi/GraphWindow.java
new file mode 100644
index 0000000000000000000000000000000000000000..a0cfeed6b853293982c550b4af950f3cb4dee147
--- /dev/null
+++ b/src/main/java/fucoin/gui/gephi/GraphWindow.java
@@ -0,0 +1,146 @@
+package fucoin.gui.gephi;
+
+import org.gephi.graph.api.Node;
+import org.gephi.preview.api.*;
+import org.gephi.preview.types.DependantOriginalColor;
+import org.gephi.project.api.Workspace;
+import org.openide.util.Lookup;
+
+import javax.swing.*;
+import java.awt.*;
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.List;
+import java.util.Timer;
+
+public class GraphWindow extends JFrame implements NodeMouseListener {
+
+    protected List<NodeClickHandler> clickHandlers = new ArrayList<>();
+    private final PreviewController previewController;
+    private final PreviewSketch previewSketch;
+
+    private JLabel infobarText;
+    private Timer timer;
+
+    private final String baseWindowTitle = "Network Overlay Graph";
+    private final String defaultInfoBarText = "Click on a node to see further information.";
+
+    public GraphWindow() {
+        super();
+
+        timer = new Timer();
+
+        setTitle(baseWindowTitle);
+
+        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+        previewController = Lookup.getDefault().lookup(PreviewController.class);
+        PreviewModel previewModel = previewController.getModel();
+        previewModel.getProperties().putValue(PreviewProperty.SHOW_NODE_LABELS, Boolean.TRUE);
+        previewModel.getProperties().putValue(PreviewProperty.NODE_LABEL_COLOR, new DependantOriginalColor(Color.BLACK));
+
+        Font labelFont = new Font("Verdana", Font.PLAIN, 5);
+        previewModel.getProperties().putValue(PreviewProperty.NODE_LABEL_FONT, labelFont);
+        previewModel.getProperties().putValue(PreviewProperty.EDGE_CURVED, Boolean.FALSE);
+        previewModel.getProperties().putValue(PreviewProperty.EDGE_OPACITY, 50);
+        previewModel.getProperties().putValue(PreviewProperty.EDGE_RADIUS, 10f);
+        previewModel.getProperties().putValue("graphWindow.mouse.handler", this);
+
+        G2DTarget target = (G2DTarget) previewController.getRenderTarget(RenderTarget.G2D_TARGET);
+        previewSketch = new PreviewSketch(target, isRetina());
+
+        infobarText = new JLabel(defaultInfoBarText, SwingConstants.LEFT);
+
+        this.add(previewSketch, BorderLayout.CENTER);
+
+        JPanel infobar = new JPanel(new BorderLayout());
+        infobar.add(infobarText, BorderLayout.WEST);
+
+        JPanel zoomOptions = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 2));
+        zoomOptions.add(new JLabel("Zoom: "));
+
+        Dimension zoomBtnSize = new Dimension(20, 20);
+
+        JButton minusButton = new JButton("-");
+        minusButton.setPreferredSize(zoomBtnSize);
+        minusButton.addActionListener(e -> previewSketch.zoomMinus());
+        zoomOptions.add(minusButton);
+
+        JButton resetButton = new JButton("0");
+        resetButton.setPreferredSize(zoomBtnSize);
+        resetButton.addActionListener(e -> previewSketch.resetZoom());
+        zoomOptions.add(resetButton);
+
+        JButton plusButton = new JButton("+");
+        plusButton.setPreferredSize(zoomBtnSize);
+        plusButton.addActionListener(e -> previewSketch.zoomPlus());
+        zoomOptions.add(plusButton);
+
+        infobar.add(zoomOptions, BorderLayout.EAST);
+        this.add(infobar, BorderLayout.SOUTH);
+
+        previewController.refreshPreview();
+        previewSketch.resetZoom();
+
+
+        this.setSize(800, 600);
+    }
+
+    public void setDisplayedFilename(String filename) {
+        setTitle(baseWindowTitle + " - " + filename);
+    }
+
+    public static boolean isRetina() {
+        GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        final GraphicsDevice device = env.getDefaultScreenDevice();
+
+        try {
+            Field field = device.getClass().getDeclaredField("scale");
+
+            if (field != null) {
+                field.setAccessible(true);
+                Object scale = field.get(device);
+
+                if (scale instanceof Integer && (Integer) scale == 2) {
+                    return true;
+                }
+            }
+        } catch (Exception ignore) {
+        }
+        return false;
+    }
+
+    @Override
+    public void mouseClicked(Node node, PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) {
+        clickHandlers.stream().forEach(nodeClickHandler -> nodeClickHandler.accept(node, event));
+    }
+
+    public void addNodeClickHandler(NodeClickHandler handler) {
+        clickHandlers.add(handler);
+    }
+
+    @Override
+    public void setVisible(boolean b) {
+        super.setVisible(b);
+
+        previewController.refreshPreview();
+        previewSketch.refreshSketch();
+    }
+
+    /**
+     * Sets the displayed text of the infobar to text.
+     * After a certain time the text will be reset to the default text.
+     *
+     * @param text new infobar text
+     */
+    public void setInfobarText(String text) {
+        SwingUtilities.invokeLater(() -> infobarText.setText(text));
+        // set text back to default text after 2 seconds
+        timer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                SwingUtilities.invokeLater(() -> infobarText.setText(defaultInfoBarText));
+            }
+        }, 2000);
+    }
+}
diff --git a/src/main/java/fucoin/gui/gephi/ItemBuilderTemplate.java b/src/main/java/fucoin/gui/gephi/ItemBuilderTemplate.java
new file mode 100644
index 0000000000000000000000000000000000000000..d54941d98e7424b40b94ccf4c76cf52b8aed0016
--- /dev/null
+++ b/src/main/java/fucoin/gui/gephi/ItemBuilderTemplate.java
@@ -0,0 +1,20 @@
+package fucoin.gui.gephi;
+
+import org.gephi.graph.api.Graph;
+import org.gephi.preview.api.Item;
+import org.gephi.preview.spi.ItemBuilder;
+import org.openide.util.lookup.ServiceProvider;
+
+
+@ServiceProvider(service = ItemBuilder.class)
+public class ItemBuilderTemplate implements ItemBuilder {
+    @Override
+    public Item[] getItems(Graph graph) {
+        return new Item[0];
+    }
+
+    @Override
+    public String getType() {
+        return null;
+    }
+}
diff --git a/src/main/java/fucoin/gui/gephi/LabelItem.java b/src/main/java/fucoin/gui/gephi/LabelItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4a123309ab4af6d32e452a2d255e18442ebf9e0
--- /dev/null
+++ b/src/main/java/fucoin/gui/gephi/LabelItem.java
@@ -0,0 +1,36 @@
+package fucoin.gui.gephi;
+
+import org.gephi.graph.api.Node;
+import org.gephi.preview.api.Item;
+
+public class LabelItem implements Item {
+    Node node;
+
+    public LabelItem(Node node) {
+        this.node = node;
+    }
+
+    @Override
+    public Object getSource() {
+        return node;
+    }
+
+    @Override
+    public String getType() {
+        return "label.sometype";
+    }
+
+    @Override
+    public <D> D getData(String key) {
+        return null;
+    }
+
+    @Override
+    public void setData(String key, Object value) {
+    }
+
+    @Override
+    public String[] getKeys() {
+        return new String[0];
+    }
+}
diff --git a/src/main/java/fucoin/gui/gephi/MouseListenerTemplate.java b/src/main/java/fucoin/gui/gephi/MouseListenerTemplate.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e5d39ae4bca7ea7f7b7b90cb2a21d9d7001003a
--- /dev/null
+++ b/src/main/java/fucoin/gui/gephi/MouseListenerTemplate.java
@@ -0,0 +1,48 @@
+package fucoin.gui.gephi;
+
+import org.gephi.graph.api.GraphController;
+import org.gephi.graph.api.Node;
+import org.gephi.preview.api.PreviewMouseEvent;
+import org.gephi.preview.api.PreviewProperties;
+import org.gephi.preview.spi.PreviewMouseListener;
+import org.gephi.project.api.Workspace;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.ServiceProvider;
+
+@ServiceProvider(service = PreviewMouseListener.class)
+public class MouseListenerTemplate implements PreviewMouseListener {
+    @Override
+    public void mouseClicked(PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) {
+        for (Node node : Lookup.getDefault().lookup(GraphController.class).getGraphModel(workspace).getGraph().getNodes()) {
+            if (clickingInNode(node, event)) {
+                if (properties.hasProperty("graphWindow.mouse.handler")) {
+                    NodeMouseListener listener = properties.getValue("graphWindow.mouse.handler");
+                    listener.mouseClicked(node, event, properties, workspace);
+                }
+                event.setConsumed(true);
+                return;
+            }
+        }
+        event.setConsumed(true);//So the renderer is executed and the graph repainted
+    }
+
+    @Override
+    public void mousePressed(PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) {
+    }
+
+    @Override
+    public void mouseDragged(PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) {
+    }
+
+    @Override
+    public void mouseReleased(PreviewMouseEvent event, PreviewProperties properties, Workspace workspace) {
+    }
+
+    private boolean clickingInNode(Node node, PreviewMouseEvent event) {
+        float xdiff = node.x() - event.x;
+        float ydiff = -node.y() - event.y;//Note that y axis is inverse for node coordinates
+        float radius = node.size();
+
+        return xdiff * xdiff + ydiff * ydiff < radius * radius;
+    }
+}
diff --git a/src/main/java/fucoin/gui/gephi/NodeClickHandler.java b/src/main/java/fucoin/gui/gephi/NodeClickHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..9005017dddecabfb10636be551afaef1883b868c
--- /dev/null
+++ b/src/main/java/fucoin/gui/gephi/NodeClickHandler.java
@@ -0,0 +1,10 @@
+package fucoin.gui.gephi;
+
+import org.gephi.graph.api.Node;
+import org.gephi.preview.api.PreviewMouseEvent;
+
+import java.util.function.BiConsumer;
+
+
+public interface NodeClickHandler extends BiConsumer<Node, PreviewMouseEvent> {
+}
diff --git a/src/main/java/fucoin/gui/gephi/NodeMouseListener.java b/src/main/java/fucoin/gui/gephi/NodeMouseListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..348028b82f5f55183da6cc66b3caae928b2286af
--- /dev/null
+++ b/src/main/java/fucoin/gui/gephi/NodeMouseListener.java
@@ -0,0 +1,10 @@
+package fucoin.gui.gephi;
+
+import org.gephi.graph.api.Node;
+import org.gephi.preview.api.PreviewMouseEvent;
+import org.gephi.preview.api.PreviewProperties;
+import org.gephi.project.api.Workspace;
+
+public interface NodeMouseListener {
+    public void mouseClicked(Node node, PreviewMouseEvent event, PreviewProperties properties, Workspace workspace);
+}
diff --git a/src/main/java/fucoin/gui/gephi/PreviewSketch.java b/src/main/java/fucoin/gui/gephi/PreviewSketch.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f324bc99fe7dd900b002db11d56247d34cfb8ba
--- /dev/null
+++ b/src/main/java/fucoin/gui/gephi/PreviewSketch.java
@@ -0,0 +1,235 @@
+package fucoin.gui.gephi;
+
+import java.awt.Graphics;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.gephi.preview.api.G2DTarget;
+import org.gephi.preview.api.PreviewController;
+import org.gephi.preview.api.PreviewMouseEvent;
+import org.gephi.preview.api.Vector;
+import org.openide.util.Lookup;
+
+public class PreviewSketch extends JPanel implements MouseListener, MouseWheelListener, MouseMotionListener {
+    private static final int WHEEL_TIMER = 500;
+    //Data
+    private final PreviewController previewController;
+    private final G2DTarget target;
+    //Geometry
+    private final Vector ref = new Vector();
+    private final Vector lastMove = new Vector();
+    //Utils
+    private final RefreshLoop refreshLoop = new RefreshLoop();
+    private Timer wheelTimer;
+    private boolean inited;
+    private final boolean isRetina;
+
+    public PreviewSketch(G2DTarget target, boolean retina) {
+        this.target = target;
+        previewController = Lookup.getDefault().lookup(PreviewController.class);
+        isRetina = retina;
+    }
+
+    @Override
+    protected void paintComponent(Graphics g) {
+        super.paintComponent(g);
+
+        if (!inited) {
+            //Listeners
+            addMouseListener(this);
+            addMouseMotionListener(this);
+            addMouseWheelListener(this);
+            inited = true;
+        }
+
+        int width = (int) (getWidth() * (isRetina ? 2.0 : 1.0));
+        int height = (int) (getHeight() * (isRetina ? 2.0 : 1.0));
+
+        if (target.getWidth() != width || target.getHeight() != height) {
+            target.resize(width, height);
+        }
+
+        g.drawImage(target.getImage(), 0, 0, getWidth(), getHeight(), this);
+    }
+
+    public void refreshSketch() {
+        refreshLoop.refreshSketch();
+    }
+
+    public void setMoving(boolean moving) {
+        target.setMoving(moving);
+    }
+
+    @Override
+    public void mouseClicked(MouseEvent e) {
+        if (previewController.sendMouseEvent(buildPreviewMouseEvent(e, PreviewMouseEvent.Type.CLICKED))) {
+            refreshLoop.refreshSketch();
+        }
+    }
+
+    @Override
+    public void mousePressed(MouseEvent e) {
+        previewController.sendMouseEvent(buildPreviewMouseEvent(e, PreviewMouseEvent.Type.PRESSED));
+        ref.set(e.getX(), e.getY());
+        lastMove.set(target.getTranslate());
+
+        refreshLoop.refreshSketch();
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent e) {
+        if (!previewController.sendMouseEvent(buildPreviewMouseEvent(e, PreviewMouseEvent.Type.RELEASED))) {
+            setMoving(false);
+        }
+
+        refreshLoop.refreshSketch();
+    }
+
+    @Override
+    public void mouseEntered(MouseEvent e) {
+    }
+
+    @Override
+    public void mouseExited(MouseEvent e) {
+    }
+
+    @Override
+    public void mouseWheelMoved(MouseWheelEvent e) {
+        if (e.getUnitsToScroll() == 0) {
+            return;
+        }
+        float way = -e.getUnitsToScroll() / Math.abs(e.getUnitsToScroll());
+        target.setScaling(target.getScaling() * (way > 0 ? 2f : 0.5f));
+        setMoving(true);
+        if (wheelTimer != null) {
+            wheelTimer.cancel();
+            wheelTimer = null;
+        }
+        wheelTimer = new Timer();
+        wheelTimer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                setMoving(false);
+                refreshLoop.refreshSketch();
+                wheelTimer = null;
+            }
+        }, WHEEL_TIMER);
+        refreshLoop.refreshSketch();
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent e) {
+        if (!previewController.sendMouseEvent(buildPreviewMouseEvent(e, PreviewMouseEvent.Type.DRAGGED))) {
+            setMoving(true);
+            Vector trans = target.getTranslate();
+            trans.set(e.getX(), e.getY());
+            trans.sub(ref);
+            trans.mult(isRetina ? 2f : 1f);
+            trans.div(target.getScaling()); // ensure const. moving speed whatever the zoom is
+            trans.add(lastMove);
+
+            refreshLoop.refreshSketch();
+        }
+    }
+
+    @Override
+    public void mouseMoved(MouseEvent e) {
+    }
+
+    public void zoomPlus() {
+        target.setScaling(target.getScaling() * 2f);
+        refreshLoop.refreshSketch();
+    }
+
+    public void zoomMinus() {
+        target.setScaling(target.getScaling() / 2f);
+        refreshLoop.refreshSketch();
+    }
+
+    public void resetZoom() {
+        target.reset();
+        refreshLoop.refreshSketch();
+    }
+
+    private Vector screenPositionToModelPosition(Vector screenPos) {
+        Vector center = new Vector(getWidth() / 2f, getHeight() / 2f);
+        Vector scaledCenter = Vector.mult(center, target.getScaling());
+        Vector scaledTrans = Vector.sub(center, scaledCenter);
+
+        Vector modelPos = new Vector(screenPos.x, screenPos.y);
+        modelPos.sub(scaledTrans);
+        modelPos.mult((isRetina) ? 2f : 1f);
+        modelPos.div(target.getScaling());
+        modelPos.sub(target.getTranslate());
+        return modelPos;
+    }
+
+    private PreviewMouseEvent buildPreviewMouseEvent(MouseEvent evt, PreviewMouseEvent.Type type) {
+        int mouseX = evt.getX();
+        int mouseY = evt.getY();
+        PreviewMouseEvent.Button button = PreviewMouseEvent.Button.LEFT;
+        if (SwingUtilities.isMiddleMouseButton(evt)) {
+            button = PreviewMouseEvent.Button.MIDDLE;
+        } else if (SwingUtilities.isLeftMouseButton(evt)) {
+            button = PreviewMouseEvent.Button.LEFT;
+        } else if (SwingUtilities.isRightMouseButton(evt)) {
+            button = PreviewMouseEvent.Button.RIGHT;
+        }
+
+        Vector pos = screenPositionToModelPosition(new Vector(mouseX, mouseY));
+
+        return new PreviewMouseEvent((int) pos.x, (int) pos.y, type, button, null);
+    }
+
+    private class RefreshLoop {
+
+        private final long DELAY = 100;
+        private final AtomicBoolean running = new AtomicBoolean();
+        private final AtomicBoolean refresh = new AtomicBoolean();
+        //Timer
+        private long timeout = DELAY * 10;
+        private Timer timer;
+
+        public RefreshLoop() {
+            super();
+        }
+
+        public void refreshSketch() {
+            refresh.set(true);
+            if (!running.getAndSet(true)) {
+                startTimer();
+            }
+        }
+
+        private void startTimer() {
+            timer = new Timer("PreviewRefreshLoop", true);
+            timer.schedule(new TimerTask() {
+                @Override
+                public void run() {
+                    if (refresh.getAndSet(false)) {
+                        target.refresh();
+                        repaint();
+                    } else if (timeout == 0) {
+                        timeout = DELAY * 10;
+                        stopTimer();
+                    } else {
+                        timeout -= DELAY;
+                    }
+                }
+            }, 0, DELAY);
+        }
+
+        private void stopTimer() {
+            timer.cancel();
+            running.set(false);
+        }
+    }
+}
diff --git a/src/main/java/fucoin/gui/gephi/RendererTemplate.java b/src/main/java/fucoin/gui/gephi/RendererTemplate.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a69717f0869b037648568ee8bdd419031e85d59
--- /dev/null
+++ b/src/main/java/fucoin/gui/gephi/RendererTemplate.java
@@ -0,0 +1,64 @@
+package fucoin.gui.gephi;
+
+import org.gephi.graph.api.Node;
+import org.gephi.preview.api.*;
+import org.gephi.preview.spi.ItemBuilder;
+import org.gephi.preview.spi.MouseResponsiveRenderer;
+import org.gephi.preview.spi.PreviewMouseListener;
+import org.gephi.preview.spi.Renderer;
+import org.openide.util.lookup.ServiceProvider;
+
+import java.awt.*;
+
+@ServiceProvider(service = Renderer.class)
+public class RendererTemplate implements Renderer, MouseResponsiveRenderer {
+    @Override
+    public String getDisplayName() {
+        return "Some name";
+    }
+
+    @Override
+    public void preProcess(PreviewModel previewModel) {
+    }
+
+    @Override
+    public void render(Item item, RenderTarget target, PreviewProperties properties) {
+        //Retrieve clicked node for the label:
+        LabelItem label = (LabelItem) item;
+        Node node = label.node;
+
+        //Finally draw your graphics for the node label in each target
+        if (target instanceof G2DTarget) {
+            Graphics2D g = ((G2DTarget) target).getGraphics();
+
+            g.setColor(Color.RED);
+            g.fillOval((int) node.x(), (int) -node.y(), 5, 5);//Note that y axis is inverse for node coordinates
+        } else if (target instanceof PDFTarget) {
+        } else if (target instanceof SVGTarget) {
+        }
+    }
+
+    @Override
+    public PreviewProperty[] getProperties() {
+        return new PreviewProperty[0];
+    }
+
+    @Override
+    public boolean isRendererForitem(Item item, PreviewProperties properties) {
+        return item instanceof LabelItem;
+    }
+
+    @Override
+    public boolean needsItemBuilder(ItemBuilder itemBuilder, PreviewProperties properties) {
+        return itemBuilder instanceof ItemBuilderTemplate;
+    }
+
+    @Override
+    public boolean needsPreviewMouseListener(PreviewMouseListener pl) {
+        return pl instanceof MouseListenerTemplate;
+    }
+
+    public CanvasSize getCanvasSize(Item item, PreviewProperties properties) {
+        return new CanvasSize();
+    }
+}
diff --git a/src/main/java/fucoin/wallet/AbstractWallet.java b/src/main/java/fucoin/wallet/AbstractWallet.java
index 882c2a547b9060a576589281eaaea8c9d3e078ba..210b67e80cc706159f9db444d1cddd75ba2ee0df 100644
--- a/src/main/java/fucoin/wallet/AbstractWallet.java
+++ b/src/main/java/fucoin/wallet/AbstractWallet.java
@@ -6,6 +6,8 @@ import fucoin.gui.TransactionLogger;
 import scala.concurrent.Future;
 
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  *
@@ -22,6 +24,8 @@ public abstract class AbstractWallet extends AbstractNode implements Serializabl
      */
     protected final String name;
 
+    protected final List<ActorRef> overlayNeighbours = new ArrayList<>();
+
     /**
      * Init. a wallet with a name.
      *
@@ -114,4 +118,8 @@ public abstract class AbstractWallet extends AbstractNode implements Serializabl
      * @param observer
      */
     public abstract void send(String address, int amount, ActorRef observer);
+
+    public void addOverlayNeighbour(ActorRef wallet) {
+        overlayNeighbours.add(wallet);
+    }
 }
diff --git a/src/main/java/fucoin/wallet/WalletImpl.java b/src/main/java/fucoin/wallet/WalletImpl.java
index 951a1519f91fa609e143fce37a554279eebcecbb..ec7899f800a855ef4f12af91c65d01639f7581ac 100644
--- a/src/main/java/fucoin/wallet/WalletImpl.java
+++ b/src/main/java/fucoin/wallet/WalletImpl.java
@@ -50,7 +50,7 @@ public class WalletImpl extends AbstractWallet {
      */
     public void addAmount(int amount) {
         setAmount(this.getAmount() + amount);
-        addLogMsg(" My amount is now " + this.getAmount());
+        //addLogMsg(" My amount is now " + this.getAmount());
     }
 
     @Override
@@ -61,7 +61,7 @@ public class WalletImpl extends AbstractWallet {
     @Override
     public void onReceive(Object message) {
 
-        addLogMsg(getSender().path().name() + " invokes " + getSelf().path().name() + " to do " + message.getClass().getSimpleName());
+        //addLogMsg(getSender().path().name() + " invokes " + getSelf().path().name() + " to do " + message.getClass().getSimpleName());
         if (message instanceof ActionInvokeRevive) {
             ((ActionInvokeRevive) message).doAction(this);
         }
@@ -198,7 +198,7 @@ public class WalletImpl extends AbstractWallet {
 
     @Override
     public boolean addKnownNeighbor(String key, ActorRef value) {
-        addLogMsg(key + " is newNeighbor of " + name + "?" + !getKnownNeighbors().containsKey(key));
+        //addLogMsg(key + " is newNeighbor of " + name + "?" + !getKnownNeighbors().containsKey(key));
         if (getKnownNeighbors().containsKey(key) || key.equals(name)) {
             return false;
         }
diff --git a/src/main/resources/topology.gexf b/src/main/resources/topology.gexf
new file mode 100644
index 0000000000000000000000000000000000000000..45d86d94fb4f0fb2b7ffeccca6292f6313fe5414
--- /dev/null
+++ b/src/main/resources/topology.gexf
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gexf xmlns="http://www.gexf.net/1.3" version="1.3" xmlns:viz="http://www.gexf.net/1.3/viz" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gexf.net/1.3 http://www.gexf.net/1.3/gexf.xsd">
+  <meta lastmodifieddate="2016-07-08">
+    <creator>Gephi 0.9</creator>
+    <description></description>
+  </meta>
+  <graph defaultedgetype="directed" mode="static">
+    <nodes>
+      <node id="0" label="Node0">
+        <viz:size value="10.0"></viz:size>
+        <viz:position x="-294.57407" y="300.54153"></viz:position>
+        <viz:color r="153" g="153" b="153"></viz:color>
+      </node>
+      <node id="1" label="Node1">
+        <viz:size value="10.0"></viz:size>
+        <viz:position x="342.42365" y="-58.31403"></viz:position>
+        <viz:color r="153" g="153" b="153"></viz:color>
+      </node>
+      <node id="2" label="Node2">
+        <viz:size value="10.0"></viz:size>
+        <viz:position x="-482.98184" y="-252.69414"></viz:position>
+        <viz:color r="153" g="153" b="153"></viz:color>
+      </node>
+      <node id="3" label="Node3">
+        <viz:size value="10.0"></viz:size>
+        <viz:position x="183.92188" y="291.57016"></viz:position>
+        <viz:color r="153" g="153" b="153"></viz:color>
+      </node>
+    </nodes>
+    <edges>
+      <edge id="0" source="2" target="1"></edge>
+      <edge id="1" source="1" target="3"></edge>
+      <edge id="2" source="3" target="0"></edge>
+      <edge id="3" source="0" target="2"></edge>
+    </edges>
+  </graph>
+</gexf>
diff --git a/src/main/resources/topology2.gexf b/src/main/resources/topology2.gexf
new file mode 100644
index 0000000000000000000000000000000000000000..f7f453b0be6f37660060bb1bb27ab0241f7de0b6
--- /dev/null
+++ b/src/main/resources/topology2.gexf
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gexf xmlns="http://www.gexf.net/1.3" version="1.3" xmlns:viz="http://www.gexf.net/1.3/viz" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gexf.net/1.3 http://www.gexf.net/1.3/gexf.xsd">
+  <meta lastmodifieddate="2016-07-08">
+    <creator>Gephi 0.9</creator>
+    <description></description>
+  </meta>
+  <graph mode="static">
+    <nodes>
+      <node id="0" label="Node0">
+        <viz:size value="10.0"></viz:size>
+        <viz:position x="-294.57407" y="300.54153"></viz:position>
+        <viz:color r="153" g="153" b="153"></viz:color>
+      </node>
+      <node id="1" label="Node1">
+        <viz:size value="10.0"></viz:size>
+        <viz:position x="342.42365" y="-58.31403"></viz:position>
+        <viz:color r="153" g="153" b="153"></viz:color>
+      </node>
+      <node id="2" label="Node2">
+        <viz:size value="10.0"></viz:size>
+        <viz:position x="-482.98184" y="-252.69414"></viz:position>
+        <viz:color r="153" g="153" b="153"></viz:color>
+      </node>
+      <node id="3" label="Node3">
+        <viz:size value="10.0"></viz:size>
+        <viz:position x="183.92188" y="291.57016"></viz:position>
+        <viz:color r="153" g="153" b="153"></viz:color>
+      </node>
+    </nodes>
+    <edges>
+      <edge id="0" source="2" target="1" type="directed"></edge>
+      <edge id="1" source="1" target="3" type="directed"></edge>
+      <edge id="2" source="3" target="0" type="directed"></edge>
+      <edge id="4" source="2" target="0" type="undirected"></edge>
+    </edges>
+  </graph>
+</gexf>