public TumblerClientConfiguration LoadArgs(String[] args)
        {
            ConfigurationFile = args.Where(a => a.StartsWith("-conf=", StringComparison.Ordinal)).Select(a => a.Substring("-conf=".Length).Replace("\"", "")).FirstOrDefault();
            DataDir           = args.Where(a => a.StartsWith("-datadir=", StringComparison.Ordinal)).Select(a => a.Substring("-datadir=".Length).Replace("\"", "")).FirstOrDefault();
            if (DataDir != null && ConfigurationFile != null)
            {
                var isRelativePath = Path.GetFullPath(ConfigurationFile).Length > ConfigurationFile.Length;
                if (isRelativePath)
                {
                    ConfigurationFile = Path.Combine(DataDir, ConfigurationFile);
                }
            }

            Network = args.Contains("-testnet", StringComparer.OrdinalIgnoreCase) ? Network.TestNet :
                      args.Contains("-regtest", StringComparer.OrdinalIgnoreCase) ? Network.RegTest :
                      null;

            if (ConfigurationFile != null)
            {
                AssetConfigFileExists();
                var configTemp = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));
                Network = Network ?? (configTemp.GetOrDefault <bool>("testnet", false) ? Network.TestNet :
                                      configTemp.GetOrDefault <bool>("regtest", false) ? Network.RegTest : null);
            }
            Network = Network ?? Network.Main;

            if (DataDir == null)
            {
                DataDir = DefaultDataDirectory.GetDefaultDirectory("NTumbleBit", Network);
            }

            if (ConfigurationFile == null)
            {
                ConfigurationFile = GetDefaultConfigurationFile(DataDir, Network);
            }
            Logs.Configuration.LogInformation("Network: " + Network);

            Logs.Configuration.LogInformation("Data directory set to " + DataDir);
            Logs.Configuration.LogInformation("Configuration file set to " + ConfigurationFile);

            if (!Directory.Exists(DataDir))
            {
                throw new ConfigurationException("Data directory does not exists");
            }

            var consoleConfig = new TextFileConfiguration(args);
            var config        = TextFileConfiguration.Parse(File.ReadAllText(ConfigurationFile));

            consoleConfig.MergeInto(config, true);
            config.AddAlias("server", "tumbler.server");

            OnlyMonitor   = config.GetOrDefault <bool>("onlymonitor", false);
            Cooperative   = config.GetOrDefault <bool>("cooperative", true);
            TumblerServer = config.GetOrDefault("tumbler.server", null as TumblerUrlBuilder);
            TorPath       = config.GetOrDefault <string>("torpath", "tor");

            RPCArgs = RPCArgs.Parse(config, Network);

            if (!OnlyMonitor && TumblerServer == null)
            {
                throw new ConfigException("tumbler.server not configured");
            }

            try
            {
                var key = config.GetOrDefault("outputwallet.extpubkey", null as string);
                if (key != null)
                {
                    OutputWallet.RootKey = new BitcoinExtPubKey(key, Network);
                }
            }
            catch
            {
                throw new ConfigException("outputwallet.extpubkey is not configured correctly");
            }

            OutputWallet.KeyPath = new KeyPath("0");
            string keyPathString = config.GetOrDefault("outputwallet.keypath", null as string);

            if (keyPathString != null)
            {
                try
                {
                    OutputWallet.KeyPath = new KeyPath(keyPathString);
                }
                catch
                {
                    throw new ConfigException("outputwallet.keypath is not configured correctly");
                }
            }

            if (OutputWallet.KeyPath.ToString().Contains("'"))
            {
                throw new ConfigException("outputwallet.keypath should not contain any hardened derivation");
            }

            if (OutputWallet.RootKey != null && OutputWallet.RootKey.Network != Network)
            {
                throw new ConfigException("outputwallet.extpubkey is pointing an incorrect network");
            }

            OutputWallet.RPCArgs = RPCArgs.Parse(config, Network, "outputwallet");

            AliceConnectionSettings = ConnectionSettingsBase.ParseConnectionSettings("alice", config);
            BobConnectionSettings   = ConnectionSettingsBase.ParseConnectionSettings("bob", config);

            AllowInsecure = config.GetOrDefault <bool>("allowinsecure", IsTest(Network));

            RPCClient rpc = null;

            try
            {
                rpc = RPCArgs.ConfigureRPCClient(Network);
            }
            catch
            {
                throw new ConfigException("Please, fix rpc settings in " + ConfigurationFile);
            }

            DBreezeRepository = new DBreezeRepository(Path.Combine(DataDir, "db2"));
            Tracker           = new Tracker(DBreezeRepository, Network);
            Services          = ExternalServices.CreateFromRPCClient(rpc, DBreezeRepository, Tracker, true);

            if (OutputWallet.RootKey != null && OutputWallet.KeyPath != null)
            {
                DestinationWallet = new ClientDestinationWallet(OutputWallet.RootKey, OutputWallet.KeyPath, DBreezeRepository, Network);
            }
            else if (OutputWallet.RPCArgs != null)
            {
                try
                {
                    DestinationWallet = new RPCDestinationWallet(OutputWallet.RPCArgs.ConfigureRPCClient(Network));
                }
                catch
                {
                    throw new ConfigException("Please, fix outputwallet rpc settings in " + ConfigurationFile);
                }
            }
            else
            {
                throw new ConfigException("Missing configuration for outputwallet");
            }

            return(this);
        }
        public async Task ConfigureAsync(TumblerClientConfiguration configuration, ClientInteraction interaction)
        {
            interaction = interaction ?? new AcceptAllClientInteraction();

            Network       = configuration.Network;
            TumblerServer = configuration.TumblerServer;
            BobSettings   = configuration.BobConnectionSettings;
            AliceSettings = configuration.AliceConnectionSettings;
            AllowInsecure = configuration.AllowInsecure;

            await SetupTorAsync(interaction, configuration.TorPath).ConfigureAwait(false);

            RPCClient rpc = null;

            try
            {
                rpc = configuration.RPCArgs.ConfigureRPCClient(configuration.Network);
            }
            catch
            {
                throw new ConfigException("Please, fix rpc settings in " + configuration.ConfigurationFile);
            }

            var dbreeze = new DBreezeRepository(Path.Combine(configuration.DataDir, "db2"));

            Cooperative = configuration.Cooperative;
            Repository  = dbreeze;
            _Disposables.Add(dbreeze);
            Tracker  = new Tracker(dbreeze, Network);
            Services = ExternalServices.CreateFromRPCClient(rpc, dbreeze, Tracker);

            if (configuration.OutputWallet.RootKey != null && configuration.OutputWallet.KeyPath != null)
            {
                DestinationWallet = new ClientDestinationWallet(configuration.OutputWallet.RootKey, configuration.OutputWallet.KeyPath, dbreeze, configuration.Network);
            }
            else if (configuration.OutputWallet.RPCArgs != null)
            {
                try
                {
                    DestinationWallet = new RPCDestinationWallet(configuration.OutputWallet.RPCArgs.ConfigureRPCClient(Network));
                }
                catch
                {
                    throw new ConfigException("Please, fix outputwallet rpc settings in " + configuration.ConfigurationFile);
                }
            }
            else
            {
                throw new ConfigException("Missing configuration for outputwallet");
            }

            TumblerParameters = dbreeze.Get <ClassicTumbler.ClassicTumblerParameters>("Configuration", configuration.TumblerServer.Uri.AbsoluteUri);

            if (TumblerParameters != null && TumblerParameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
            {
                TumblerParameters = null;
            }

            if (!configuration.OnlyMonitor)
            {
                var client = CreateTumblerClient(0);
                if (TumblerParameters == null)
                {
                    Logs.Configuration.LogInformation("Downloading tumbler information of " + configuration.TumblerServer.Uri.AbsoluteUri);
                    var parameters = Retry(3, () => client.GetTumblerParameters());
                    if (parameters == null)
                    {
                        throw new ConfigException("Unable to download tumbler's parameters");
                    }

                    if (parameters.GetHash() != configuration.TumblerServer.ConfigurationHash)
                    {
                        throw new ConfigException("The tumbler returned an invalid configuration");
                    }

                    var standardCycles = new StandardCycles(configuration.Network);
                    var standardCycle  = standardCycles.GetStandardCycle(parameters);

                    if (standardCycle == null || !parameters.IsStandard())
                    {
                        Logs.Configuration.LogWarning("This tumbler has non standard parameters");
                        if (!AllowInsecure)
                        {
                            throw new ConfigException("This tumbler has non standard parameters");
                        }
                        standardCycle = null;
                    }

                    await interaction.ConfirmParametersAsync(parameters, standardCycle).ConfigureAwait(false);

                    Repository.UpdateOrInsert("Configuration", TumblerServer.Uri.AbsoluteUri, parameters, (o, n) => n);
                    TumblerParameters = parameters;

                    Logs.Configuration.LogInformation("Tumbler parameters saved");
                }

                Logs.Configuration.LogInformation($"Using tumbler {TumblerServer.Uri.AbsoluteUri}");
            }
        }