public BitcoinUrlBuilder(string uri)
        {
            if (!uri.StartsWith("bitcoin:", StringComparison.OrdinalIgnoreCase))
            {
                throw new FormatException("Invalid scheme");
            }
            uri = uri.Remove(0, "bitcoin:".Length);
            if (uri.StartsWith("//"))
            {
                uri = uri.Remove(0, 2);
            }

            var    paramStart = uri.IndexOf('?');
            string address    = null;

            if (paramStart == -1)
            {
                address = uri;
            }
            else
            {
                address = uri.Substring(0, paramStart);
                uri     = uri.Remove(0, 1);             //remove ?
            }
            if (address != String.Empty)
            {
                Address = Network.CreateFromBase58Data <BitcoinAddress>(address);
            }
            uri = uri.Remove(0, address.Length);

            var parameters = UriHelper.DecodeQueryParameters(uri);

            if (parameters.ContainsKey("amount"))
            {
                Amount = Money.Parse(parameters["amount"]);
                parameters.Remove("amount");
            }
            if (parameters.ContainsKey("label"))
            {
                Label = parameters["label"];
                parameters.Remove("label");
            }
            if (parameters.ContainsKey("message"))
            {
                Message = parameters["message"];
                parameters.Remove("message");
            }
            if (parameters.ContainsKey("r"))
            {
                PaymentRequestUrl = new Uri(parameters["r"], UriKind.Absolute);
                parameters.Remove("r");
            }
            _UnknowParameters = parameters;
            var reqParam = parameters.Keys.FirstOrDefault(k => k.StartsWith("req-", StringComparison.OrdinalIgnoreCase));

            if (reqParam != null)
            {
                throw new FormatException("Non compatible required parameter " + reqParam);
            }
        }
        public BitcoinUrlBuilder(string uri, Network network)
        {
            if (uri == null)
            {
                throw new ArgumentNullException(nameof(uri));
            }
            if (network == null)
            {
                throw new ArgumentNullException(nameof(network));
            }
            scheme = network.UriScheme;
            if (!uri.StartsWith($"{scheme}:", StringComparison.OrdinalIgnoreCase))
            {
                if (uri.StartsWith("bitcoin:", StringComparison.OrdinalIgnoreCase))
                {
                    scheme = "bitcoin";
                }
                else
                {
                    throw new FormatException("Invalid scheme");
                }
            }
            Network = network;
            uri     = uri.Remove(0, $"{scheme}:".Length);
            if (uri.StartsWith("//"))
            {
                uri = uri.Remove(0, 2);
            }

            var    paramStart = uri.IndexOf('?');
            string?address    = null;

            if (paramStart == -1)
            {
                address = uri;
            }
            else
            {
                address = uri.Substring(0, paramStart);
                uri     = uri.Remove(0, 1);             //remove ?
            }
            if (address != String.Empty)
            {
                Address = Network.Parse <BitcoinAddress>(address, network);
            }
            uri = uri.Remove(0, address.Length);

            Dictionary <string, string> parameters;

            try
            {
                parameters = UriHelper.DecodeQueryParameters(uri);
            }
            catch (ArgumentException)
            {
                throw new FormatException("A URI parameter is duplicated");
            }
            if (parameters.ContainsKey("amount"))
            {
                Amount = Money.Parse(parameters["amount"]);
                parameters.Remove("amount");
            }
            if (parameters.ContainsKey("label"))
            {
                Label = parameters["label"];
                parameters.Remove("label");
            }
            if (parameters.ContainsKey("message"))
            {
                Message = parameters["message"];
                parameters.Remove("message");
            }
            _UnknownParameters = parameters;
            var reqParam = parameters.Keys.FirstOrDefault(k => k.StartsWith("req-", StringComparison.OrdinalIgnoreCase));

            if (reqParam != null)
            {
                throw new FormatException("Non compatible required parameter " + reqParam);
            }
        }
        public BitcoinUrlBuilder(string uri)
        {
            if (uri == null)
            {
                throw new ArgumentNullException(nameof(uri));
            }
            if (!uri.StartsWith("bitcoin:", StringComparison.OrdinalIgnoreCase))
            {
                throw new FormatException("Invalid scheme");
            }
            uri = uri.Remove(0, "bitcoin:".Length);
            if (uri.StartsWith("//"))
            {
                uri = uri.Remove(0, 2);
            }

            var    paramStart = uri.IndexOf('?');
            string address    = null;

            if (paramStart == -1)
            {
                address = uri;
            }
            else
            {
                address = uri.Substring(0, paramStart);
                uri     = uri.Remove(0, 1);             //remove ?
            }
            if (address != String.Empty)
            {
                Address = Network.Parse <BitcoinAddress>(address, null);
            }
            uri = uri.Remove(0, address.Length);

            Dictionary <string, string> parameters;

            try
            {
                parameters = UriHelper.DecodeQueryParameters(uri);
            }
            catch (ArgumentException)
            {
                throw new FormatException("A URI parameter is duplicated");
            }
            if (parameters.ContainsKey("amount"))
            {
                Amount = Money.Parse(parameters["amount"]);
                parameters.Remove("amount");
            }
            if (parameters.ContainsKey("label"))
            {
                Label = parameters["label"];
                parameters.Remove("label");
            }
            if (parameters.ContainsKey("message"))
            {
                Message = parameters["message"];
                parameters.Remove("message");
            }
#pragma warning disable CS0618 // Type or member is obsolete
            if (parameters.ContainsKey("r"))
            {
                PaymentRequestUrl = new Uri(parameters["r"], UriKind.Absolute);
                parameters.Remove("r");
            }
#pragma warning restore CS0618 // Type or member is obsolete
            _UnknowParameters = parameters;
            var reqParam = parameters.Keys.FirstOrDefault(k => k.StartsWith("req-", StringComparison.OrdinalIgnoreCase));
            if (reqParam != null)
            {
                throw new FormatException("Non compatible required parameter " + reqParam);
            }
        }