public override void Run(ConnectionOptions mainOptions, IEnumerable <string> addresses)
        {
            var inGroups = new List <List <string> >();

            using (var mainDB = new ODatabase(mainOptions))
            {
                foreach (var address in addresses)
                {
                    var groups = mainDB.Query($"SELECT inE().tAddr AS address FROM (SELECT expand(inV) FROM (SELECT inV() FROM Link WHERE tAddr = '{address}' LIMIT 10000))").SelectMany(x => x.GetField <List <string> >("address")).Where(y => !string.IsNullOrEmpty(y)).Where(x => x.Count() > 1).Distinct().ToList();
                    try
                    {
                        inGroups.Add(groups);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(address + " not in DB?");
                    }
                    Console.WriteLine(address + " done.");
                }
            }
            var cc = new ClusteringCollapser();

            cc.Collapse(inGroups);
            _result = cc.Clustering;
        }
        public override void Run(ConnectionOptions mainOptions, IEnumerable <string> addresses)
        {
            var groups = new List <List <string> >();

            using (var mainDB = new ODatabase(mainOptions))
            {
                foreach (var address in addresses)
                {
                    var record = mainDB.Query($"SELECT $i as inputs, $o as outputs FROM (SELECT expand(inV) FROM (SELECT inV() FROM Link WHERE tAddr = '{address}' LIMIT 10000)) LET $i = set(inE().tAddr), $o = set(outE().tAddr) WHERE Coinbase = false").Select(x => new KeyValuePair <string, List <List <string> > >(x.GetField <ORID>("tx").ToString(), new List <List <string> >()
                    {
                        x.GetField <List <string> >("source"), x.GetField <List <string> >("target")
                    })).First();
                    // clean the record
                    record.Value[0] = record.Value[0].Distinct().ToList();
                    record.Value[1] = record.Value[0].Distinct().ToList();
                    record.Value[0].RemoveAll(x => x == null);
                    record.Value[1].RemoveAll(x => x == null);
                    // can we identify a return address?
                    var occurrences = new Dictionary <string, int>();
                    foreach (var outAddr in record.Value[1])
                    {
                        var count = mainDB.Query($"SELECT COUNT(*) FROM Link WHERE tAddr = '{outAddr}'").SingleOrDefault()?.GetField <long>("count");
                        if (count != null)
                        {
                            occurrences.Add(outAddr, (int)count);
                        }
                    }
                    var addr = GetChangeAddress(record, occurrences, mainOptions);
                    if (addr != null)
                    {
                        // add a new group
                        var group = record.Value.First();
                        group.Add(addr);
                        group.RemoveAll(x => string.IsNullOrEmpty(x));
                        groups.Add(group);
                    }
                }
            }
            var cc = new ClusteringCollapser();

            cc.Collapse(groups);
            _result = cc.Clustering;
        }