예제 #1
0
		public RPCException(RPCErrorCode code, string message, RPCResponse result)
			: base(String.IsNullOrEmpty(message) ? FindMessage(code) : message)
		{
			_RPCCode = code;
			_RPCCodeMessage = FindMessage(code);
			_RPCResult = result;
		}
예제 #2
0
        /// <summary>
        ///	Send all commands in one batch
        /// </summary>
        public async Task SendBatchAsync()
        {
            Tuple <RPCRequest, TaskCompletionSource <RPCResponse> >         req;
            List <Tuple <RPCRequest, TaskCompletionSource <RPCResponse> > > requests = new List <Tuple <RPCRequest, TaskCompletionSource <RPCResponse> > >();
            var batches = _BatchedRequests;

            if (batches == null)
            {
                throw new InvalidOperationException("This RPCClient instance is not a batch, use PrepareBatch");
            }
            _BatchedRequests = null;
            while (batches.TryDequeue(out req))
            {
                requests.Add(req);
            }
            if (requests.Count == 0)
            {
                return;
            }

            var writer = new StringWriter();

            writer.Write("[");
            bool first = true;

            foreach (var item in requests)
            {
                if (!first)
                {
                    writer.Write(",");
                }
                first = false;
                item.Item1.WriteJSON(writer);
            }
            writer.Write("]");
            writer.Flush();

            var json  = writer.ToString();
            var bytes = Encoding.UTF8.GetBytes(json);

            var webRequest = CreateWebRequest();

#if !(PORTABLE || NETCORE)
            webRequest.ContentLength = bytes.Length;
#endif

            int responseIndex = 0;
            var dataStream    = await webRequest.GetRequestStreamAsync().ConfigureAwait(false);

            await dataStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);

            await dataStream.FlushAsync().ConfigureAwait(false);

            dataStream.Dispose();
            JArray      response;
            WebResponse webResponse   = null;
            WebResponse errorResponse = null;
            try
            {
                webResponse = await webRequest.GetResponseAsync().ConfigureAwait(false);

                response = JArray.Load(new JsonTextReader(
                                           new StreamReader(
                                               await ToMemoryStreamAsync(webResponse.GetResponseStream()).ConfigureAwait(false), Encoding.UTF8)));
                foreach (var jobj in response.OfType <JObject>())
                {
                    try
                    {
                        RPCResponse rpcResponse = new RPCResponse(jobj);
                        requests[responseIndex].Item2.TrySetResult(rpcResponse);
                    }
                    catch (Exception ex)
                    {
                        requests[responseIndex].Item2.TrySetException(ex);
                    }
                    responseIndex++;
                }
            }
            catch (WebException ex)
            {
                if (ex.Response == null || ex.Response.ContentLength == 0)
                {
                    foreach (var item in requests)
                    {
                        item.Item2.TrySetException(ex);
                    }
                }
                else
                {
                    errorResponse = ex.Response;
                    try
                    {
                        RPCResponse rpcResponse = RPCResponse.Load(await ToMemoryStreamAsync(errorResponse.GetResponseStream()).ConfigureAwait(false));
                        foreach (var item in requests)
                        {
                            item.Item2.TrySetResult(rpcResponse);
                        }
                    }
                    catch (Exception)
                    {
                        foreach (var item in requests)
                        {
                            item.Item2.TrySetException(ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                foreach (var item in requests)
                {
                    item.Item2.TrySetException(ex);
                }
            }
            finally
            {
                if (errorResponse != null)
                {
                    errorResponse.Dispose();
                    errorResponse = null;
                }
                if (webResponse != null)
                {
                    webResponse.Dispose();
                    webResponse = null;
                }
            }
        }
        /// <summary>
        /// Sign a transaction
        /// </summary>
        /// <param name="tx">The transaction to be signed</param>
        /// <returns>The signed transaction</returns>
        public async Task <Transaction> SignRawTransactionAsync(Transaction tx)
        {
            RPCResponse result = await SendCommandAsync(RPCOperations.signrawtransaction, tx.ToHex()).ConfigureAwait(false);

            return(new Transaction(result.Result["hex"].Value <string>()));
        }
        /// <summary>
        /// Returns an array of unspent transaction outputs belonging to this wallet.
        /// </summary>
        public async Task <UnspentCoin[]> ListUnspentAsync()
        {
            RPCResponse response = await SendCommandAsync(RPCOperations.listunspent).ConfigureAwait(false);

            return(response.Result.Select(i => new UnspentCoin((JObject)i, this.Network)).ToArray());
        }
        // listunspent

        /// <summary>
        /// Returns an array of unspent transaction outputs belonging to this wallet.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Note: as of Bitcoin Core 0.10.0, outputs affecting watch-only addresses will be returned;
        /// see the spendable field in the results.
        /// </para>
        /// </remarks>
        public UnspentCoin[] ListUnspent()
        {
            RPCResponse response = SendCommand(RPCOperations.listunspent);

            return(response.Result.Select(i => new UnspentCoin((JObject)i, this.Network)).ToArray());
        }
        /// <summary>
        /// Lists accounts and their balances, based on the specified number of confirmations.
        /// </summary>
        /// <param name="confirmations">
        /// The minimum number of confirmations an externally-generated transaction must have before
        /// it is counted towards the balance. Transactions generated by this node are counted immediately.
        /// Typically, externally-generated transactions are payments to this wallet and transactions
        /// generated by this node are payments to other wallets. Use 0 to count unconfirmed transactions.
        /// Default is 1.
        /// </param>
        /// <returns>
        /// A list of accounts and their balances.
        /// </returns>
        public IEnumerable <RPCAccount> ListAccounts(int confirmations)
        {
            RPCResponse response = SendCommand(RPCOperations.listaccounts, confirmations);

            return(AsRPCAccount(response));
        }
        // dumpprivkey

        public BitcoinSecret DumpPrivKey(BitcoinAddress address)
        {
            RPCResponse response = SendCommand(RPCOperations.dumpprivkey, address.ToString());

            return(this.Network.Parse <BitcoinSecret>((string)response.Result));
        }
예제 #8
0
        public async Task <WalletCreateFundedPSBTResponse> WalletCreateFundedPSBTAsync(
            TxIn[] inputs,
            Tuple <Dictionary <BitcoinAddress, Money>, Dictionary <string, string> > outputs,
            LockTime locktime = default(LockTime),
            FundRawTransactionOptions options = null,
            bool bip32derivs = false
            )
        {
            var values = new object[] { };

            if (inputs == null)
            {
                inputs = new TxIn[] { }
            }
            ;
            if (outputs == null)
            {
                throw new ArgumentNullException(nameof(outputs));
            }

            var rpcInputs = inputs.Select(i => i.ToRPCInputs()).ToArray();

            var outputToSend = new JObject {
            };

            if (outputs.Item1 != null)
            {
                foreach (var kv in outputs.Item1)
                {
                    outputToSend.Add(kv.Key.ToString(), kv.Value.ToUnit(MoneyUnit.BTC));
                }
            }
            if (outputs.Item2 != null)
            {
                foreach (var kv in outputs.Item2)
                {
                    outputToSend.Add(kv.Key, kv.Value);
                }
            }
            JObject jOptions;

            if (options != null)
            {
                jOptions = FundRawTransactionOptionsToJson(options);
            }
            else
            {
                jOptions = (JObject)"";
            }
            RPCResponse response = await SendCommandAsync(
                "walletcreatefundedpsbt",
                rpcInputs,
                outputToSend,
                locktime.Value,
                jOptions,
                bip32derivs).ConfigureAwait(false);

            var result    = (JObject)response.Result;
            var psbt      = PSBT.Parse(result.Property("psbt").Value.Value <string>(), Network.Main);
            var fee       = Money.Coins(result.Property("fee").Value.Value <decimal>());
            var changePos = result.Property("changepos").Value.Value <int>();
            var tmp       = changePos == -1 ? (int?)null : (int?)changePos;

            return(new WalletCreateFundedPSBTResponse {
                PSBT = psbt, Fee = fee, ChangePos = tmp
            });
        }
        public async Task <Money> GetBalanceAsync(int minConf, bool includeWatchOnly)
        {
            RPCResponse data = await SendCommandAsync(RPCOperations.getbalance, "*", minConf, includeWatchOnly).ConfigureAwait(false);

            return(Money.Coins(data.Result.Value <decimal>()));
        }
        public async Task <Money> GetBalanceAsync()
        {
            RPCResponse data = await SendCommandAsync(RPCOperations.getbalance, "*").ConfigureAwait(false);

            return(Money.Coins(data.Result.Value <decimal>()));
        }
        // getaddressesbyaccount

        /// <summary>
        /// Returns a list of every address assigned to a particular account.
        /// </summary>
        /// <param name="account">
        /// The name of the account containing the addresses to get. To get addresses from the default account,
        /// pass an empty string ("").
        /// </param>
        /// <returns>
        /// A collection of all addresses belonging to the specified account.
        /// If the account has no addresses, the collection will be empty.
        /// </returns>
        public IEnumerable <BitcoinAddress> GetAddressesByAccount(string account)
        {
            RPCResponse response = SendCommand(RPCOperations.getaddressesbyaccount, account);

            return(response.Result.Select(t => this.Network.Parse <BitcoinAddress>((string)t)));
        }
        public async Task <BitcoinAddress> GetAccountAddressAsync(string account)
        {
            RPCResponse response = await SendCommandAsync(RPCOperations.getaccountaddress, account).ConfigureAwait(false);

            return(this.Network.Parse <BitcoinAddress>((string)response.Result));
        }
        // getaccountaddress

        public BitcoinAddress GetAccountAddress(string account)
        {
            RPCResponse response = SendCommand(RPCOperations.getaccountaddress, account);

            return(this.Network.Parse <BitcoinAddress>((string)response.Result));
        }
        public async Task <BitcoinSecret> DumpPrivKeyAsync(BitcoinAddress address)
        {
            RPCResponse response = await SendCommandAsync(RPCOperations.dumpprivkey, address.ToString()).ConfigureAwait(false);

            return(this.Network.Parse <BitcoinSecret>((string)response.Result));
        }
예제 #15
0
        async Task <RPCResponse> SendCommandAsyncCore(RPCRequest request, bool throwIfRPCError)
        {
            RPCResponse response = null;
            var         batches  = _BatchedRequests;

            if (batches != null)
            {
                TaskCompletionSource <RPCResponse> source = new TaskCompletionSource <RPCResponse>();
                batches.Enqueue(Tuple.Create(request, source));
                response = await source.Task.ConfigureAwait(false);
            }
            HttpWebRequest webRequest = response == null?CreateWebRequest() : null;

            if (response == null)
            {
                var writer = new StringWriter();
                request.WriteJSON(writer);
                writer.Flush();
                var json  = writer.ToString();
                var bytes = Encoding.UTF8.GetBytes(json);
#if !(PORTABLE || NETCORE)
                webRequest.ContentLength = bytes.Length;
#endif
                var dataStream = await webRequest.GetRequestStreamAsync().ConfigureAwait(false);

                await dataStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);

                await dataStream.FlushAsync().ConfigureAwait(false);

                dataStream.Dispose();
            }
            WebResponse webResponse   = null;
            WebResponse errorResponse = null;
            try
            {
                webResponse = response == null ? await webRequest.GetResponseAsync().ConfigureAwait(false) : null;

                response = response ?? RPCResponse.Load(await ToMemoryStreamAsync(webResponse.GetResponseStream()).ConfigureAwait(false));

                if (throwIfRPCError)
                {
                    response.ThrowIfError();
                }
            }
            catch (WebException ex)
            {
                if (ex.Response == null || ex.Response.ContentLength == 0)
                {
                    throw;
                }
                errorResponse = ex.Response;
                response      = RPCResponse.Load(await ToMemoryStreamAsync(errorResponse.GetResponseStream()).ConfigureAwait(false));
                if (throwIfRPCError)
                {
                    response.ThrowIfError();
                }
            }
            finally
            {
                if (errorResponse != null)
                {
                    errorResponse.Dispose();
                    errorResponse = null;
                }
                if (webResponse != null)
                {
                    webResponse.Dispose();
                    webResponse = null;
                }
            }
            return(response);
        }
예제 #16
0
        public async Task <RPCResponse> SendCommandAsync(RPCRequest request, bool throwIfRPCError = true)
        {
            var webRequest = (HttpWebRequest)WebRequest.Create(Address);

            webRequest.Headers[HttpRequestHeader.Authorization] = "Basic " + Encoders.Base64.EncodeData(Encoders.ASCII.DecodeData(_Authentication));
            webRequest.ContentType = "application/json-rpc";
            webRequest.Method      = "POST";

            var writer = new StringWriter();

            request.WriteJSON(writer);
            writer.Flush();
            var json  = writer.ToString();
            var bytes = Encoding.UTF8.GetBytes(json);

#if !(PORTABLE || NETCORE)
            webRequest.ContentLength = bytes.Length;
#endif
            var dataStream = await webRequest.GetRequestStreamAsync().ConfigureAwait(false);

            await dataStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);

            await dataStream.FlushAsync().ConfigureAwait(false);

            dataStream.Dispose();
            RPCResponse response;
            WebResponse webResponse   = null;
            WebResponse errorResponse = null;
            try
            {
                webResponse = await webRequest.GetResponseAsync().ConfigureAwait(false);

                response = RPCResponse.Load(await ToMemoryStreamAsync(webResponse.GetResponseStream()).ConfigureAwait(false));

                if (throwIfRPCError)
                {
                    response.ThrowIfError();
                }
            }
            catch (WebException ex)
            {
                if (ex.Response == null || ex.Response.ContentLength == 0)
                {
                    throw;
                }
                errorResponse = ex.Response;
                response      = RPCResponse.Load(await ToMemoryStreamAsync(errorResponse.GetResponseStream()).ConfigureAwait(false));
                if (throwIfRPCError)
                {
                    response.ThrowIfError();
                }
            }
            finally
            {
                if (errorResponse != null)
                {
                    errorResponse.Dispose();
                    errorResponse = null;
                }
                if (webResponse != null)
                {
                    webResponse.Dispose();
                    webResponse = null;
                }
            }
            return(response);
        }
        public async Task <FundRawTransactionResponse> FundRawTransactionAsync(Transaction transaction, FundRawTransactionOptions options = null)
        {
            if (transaction == null)
            {
                throw new ArgumentNullException("transaction");
            }

            RPCResponse response = null;

            if (options != null)
            {
                var jOptions = new JObject();

                if (options.ChangeAddress != null)
                {
                    jOptions.Add(new JProperty("changeAddress", options.ChangeAddress.ToString()));
                }

                if (options.ChangePosition != null)
                {
                    jOptions.Add(new JProperty("changePosition", options.ChangePosition.Value));
                }

                jOptions.Add(new JProperty("includeWatching", options.IncludeWatching));
                jOptions.Add(new JProperty("lockUnspents", options.LockUnspents));

                if (options.ReserveChangeKey != null)
                {
                    jOptions.Add(new JProperty("reserveChangeKey", options.ReserveChangeKey));
                }

                if (options.FeeRate != null)
                {
                    jOptions.Add(new JProperty("feeRate", options.FeeRate.GetFee(1000).ToDecimal(MoneyUnit.BTC)));
                }

                if (options.SubtractFeeFromOutputs != null)
                {
                    var array = new JArray();
                    foreach (int v in options.SubtractFeeFromOutputs)
                    {
                        array.Add(new JValue(v));
                    }
                    jOptions.Add(new JProperty("subtractFeeFromOutputs", array));
                }

                response = await SendCommandAsync("fundrawtransaction", ToHex(transaction), jOptions).ConfigureAwait(false);
            }
            else
            {
                response = await SendCommandAsync("fundrawtransaction", ToHex(transaction)).ConfigureAwait(false);
            }

            var r = (JObject)response.Result;

            return(new FundRawTransactionResponse()
            {
                Transaction = new Transaction(r["hex"].Value <string>()),
                Fee = Money.Coins(r["fee"].Value <decimal>()),
                ChangePos = r["changepos"].Value <int>()
            });
        }
예제 #18
0
		private static BlockHeader ParseBlockHeader(RPCResponse resp)
		{
			var header = new BlockHeader();
			header.Version = (int)resp.Result["version"];
			header.Nonce = (uint)resp.Result["nonce"];
			header.Bits = new Target(Encoders.Hex.DecodeData((string)resp.Result["bits"]));
			if (resp.Result["previousblockhash"] != null)
			{
				header.HashPrevBlock = uint256.Parse((string)resp.Result["previousblockhash"]);
			}
			if (resp.Result["time"] != null)
			{
				header.BlockTime = Utils.UnixTimeToDateTime((uint)resp.Result["time"]);
			}
			if (resp.Result["merkleroot"] != null)
			{
				header.HashMerkleRoot = uint256.Parse((string)resp.Result["merkleroot"]);
			}
			return header;
		}
        /// <summary>
        /// Returns the total amount received by the specified address in transactions with the
        /// specified number of confirmations. It does not count coinbase transactions.
        /// </summary>
        /// <param name="confirmations">
        /// The minimum number of confirmations an externally-generated transaction must have before
        /// it is counted towards the balance. Transactions generated by this node are counted immediately.
        /// Typically, externally-generated transactions are payments to this wallet and transactions
        /// generated by this node are payments to other wallets. Use 0 to count unconfirmed transactions.
        /// Default is 1.
        /// </param>
        /// <returns>The number of bitcoins received by the address, excluding coinbase transactions. May be 0.</returns>
        public Money GetReceivedByAddress(BitcoinAddress address, int confirmations)
        {
            RPCResponse response = SendCommand(RPCOperations.getreceivedbyaddress, address.ToString(), confirmations);

            return(Money.Coins(response.Result.Value <decimal>()));
        }