From 8aa7937d44d5f2cf300a3d30c53d57a51a0b624f Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 7 Jan 2017 07:41:42 -0800 Subject: [PATCH] Fixes #1960: z_getoperationstatus/result now includes operation details. --- doc/payment-api.md | 4 ++++ qa/rpc-tests/wallet_protectcoinbase.py | 8 ++++++++ src/asyncrpcoperation.h | 3 ++- src/wallet/asyncrpcoperation_sendmany.cpp | 19 +++++++++++++++++-- src/wallet/asyncrpcoperation_sendmany.h | 6 +++++- src/wallet/rpcwallet.cpp | 10 +++++++++- 6 files changed, 45 insertions(+), 5 deletions(-) diff --git a/doc/payment-api.md b/doc/payment-api.md index 3560add64..69877e5db 100644 --- a/doc/payment-api.md +++ b/doc/payment-api.md @@ -89,6 +89,10 @@ Asynchronous calls return an OperationStatus object which is a JSON object with * code : number * message: error message +Depending on the type of asynchronous call, there may be other key-value pairs. For example, a z_sendmany operation will also include the following in an OperationStatus object: + +* params : an object containing the parameters to z_sendmany + Currently, as soon as you retrieve the operation status for an operation which has finished, that is it has either succeeded, failed, or been cancelled, the operation and any associated information is removed. It is currently not possible to cancel operations. diff --git a/qa/rpc-tests/wallet_protectcoinbase.py b/qa/rpc-tests/wallet_protectcoinbase.py index 5f0c285c0..ddef5fdaf 100755 --- a/qa/rpc-tests/wallet_protectcoinbase.py +++ b/qa/rpc-tests/wallet_protectcoinbase.py @@ -98,6 +98,14 @@ class WalletProtectCoinbaseTest (BitcoinTestFramework): else: status = results[0]["status"] errorString = results[0]["error"]["message"] + + # Test that the returned status object contains a params field with the operation's input parameters + params =results[0]["params"] + assert_equal(params["fee"], Decimal('0.0001')) # default + assert_equal(params["minconf"], Decimal('1')) # default + assert_equal(params["fromaddress"], mytaddr) + assert_equal(params["amounts"][0]["address"], myzaddr) + assert_equal(params["amounts"][0]["amount"], Decimal('1.23456789')) break assert_equal("failed", status) assert_equal("wallet does not allow any change" in errorString, True) diff --git a/src/asyncrpcoperation.h b/src/asyncrpcoperation.h index bcfda892e..526a62ad0 100644 --- a/src/asyncrpcoperation.h +++ b/src/asyncrpcoperation.h @@ -66,7 +66,8 @@ public: return creation_time_; } - Value getStatus() const; + // Override this method to add data to the default status object. + virtual Value getStatus() const; Value getError() const; diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index c65664eae..c9b5b3ef2 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -51,8 +51,9 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany( std::vector tOutputs, std::vector zOutputs, int minDepth, - CAmount fee) : - fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), mindepth_(minDepth), fee_(fee) + CAmount fee, + Value contextInfo) : + fromaddress_(fromAddress), t_outputs_(tOutputs), z_outputs_(zOutputs), mindepth_(minDepth), fee_(fee), contextinfo_(contextInfo) { assert(fee_ > 0); @@ -1089,4 +1090,18 @@ boost::array AsyncRPCOperation_sendmany::get_memo_f return memo; } +/** + * Override getStatus() to append the operation's input parameters to the default status object. + */ +Value AsyncRPCOperation_sendmany::getStatus() const { + Value v = AsyncRPCOperation::getStatus(); + if (contextinfo_.is_null()) { + return v; + } + + Object obj = v.get_obj(); + obj.push_back(Pair("method", "z_sendmany")); + obj.push_back(Pair("params", contextinfo_ )); + return Value(obj); +} diff --git a/src/wallet/asyncrpcoperation_sendmany.h b/src/wallet/asyncrpcoperation_sendmany.h index 0382f0241..5108de8c5 100644 --- a/src/wallet/asyncrpcoperation_sendmany.h +++ b/src/wallet/asyncrpcoperation_sendmany.h @@ -50,7 +50,7 @@ struct WitnessAnchorData { class AsyncRPCOperation_sendmany : public AsyncRPCOperation { public: - AsyncRPCOperation_sendmany(std::string fromAddress, std::vector tOutputs, std::vector zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE); + AsyncRPCOperation_sendmany(std::string fromAddress, std::vector tOutputs, std::vector zOutputs, int minDepth, CAmount fee = ASYNC_RPC_OPERATION_DEFAULT_MINERS_FEE, Value contextInfo = Value::null); virtual ~AsyncRPCOperation_sendmany(); // We don't want to be copied or moved around @@ -61,11 +61,15 @@ public: virtual void main(); + virtual Value getStatus() const; + bool testmode = false; // Set to true to disable sending txs and generating proofs private: friend class TEST_FRIEND_AsyncRPCOperation_sendmany; // class for unit testing + Value contextinfo_; // optional data to include in return value from getStatus() + CAmount fee_; int mindepth_; std::string fromaddress_; diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 6b0f5f528..143c28f65 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3353,9 +3353,17 @@ Value z_sendmany(const Array& params, bool fHelp) } } + // Use input parameters as the optional context info to be returned by z_getoperationstatus and z_getoperationresult. + Object o; + o.push_back(Pair("fromaddress", params[0])); + o.push_back(Pair("amounts", params[1])); + o.push_back(Pair("minconf", nMinDepth)); + o.push_back(Pair("fee", std::stod(FormatMoney(nFee)))); + Value contextInfo = Value(o); + // Create operation and add to global queue std::shared_ptr q = getAsyncRPCQueue(); - std::shared_ptr operation( new AsyncRPCOperation_sendmany(fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee) ); + std::shared_ptr operation( new AsyncRPCOperation_sendmany(fromaddress, taddrRecipients, zaddrRecipients, nMinDepth, nFee, contextInfo) ); q->addOperation(operation); AsyncRPCOperationId operationId = operation->getId(); return operationId;