Merge pull request #5526 from str4d/wallet-unified-addrs-in-rpcs
Handle wallet Unified Addresses in RPCs
This commit is contained in:
commit
2aad87e147
|
@ -46,6 +46,7 @@ class WalletListNotes(BitcoinTestFramework):
|
|||
assert_equal(1, len(unspent_cb))
|
||||
assert_equal(False, unspent_cb[0]['change'])
|
||||
assert_equal(txid_1, unspent_cb[0]['txid'])
|
||||
assert_equal('sprout', unspent_cb[0]['type'])
|
||||
assert_equal(True, unspent_cb[0]['spendable'])
|
||||
assert_equal(sproutzaddr, unspent_cb[0]['address'])
|
||||
assert_equal(receive_amount_1, unspent_cb[0]['amount'])
|
||||
|
@ -78,12 +79,14 @@ class WalletListNotes(BitcoinTestFramework):
|
|||
unspent_tx = sorted(unspent_tx, key=lambda k: k['amount'])
|
||||
assert_equal(False, unspent_tx[0]['change'])
|
||||
assert_equal(txid_2, unspent_tx[0]['txid'])
|
||||
assert_equal('sapling', unspent_tx[0]['type'])
|
||||
assert_equal(True, unspent_tx[0]['spendable'])
|
||||
assert_equal(saplingzaddr, unspent_tx[0]['address'])
|
||||
assert_equal(receive_amount_2, unspent_tx[0]['amount'])
|
||||
|
||||
assert_equal(True, unspent_tx[1]['change'])
|
||||
assert_equal(txid_2, unspent_tx[1]['txid'])
|
||||
assert_equal('sprout', unspent_tx[1]['type'])
|
||||
assert_equal(True, unspent_tx[1]['spendable'])
|
||||
assert_equal(sproutzaddr, unspent_tx[1]['address'])
|
||||
assert_equal(change_amount_2, unspent_tx[1]['amount'])
|
||||
|
@ -115,18 +118,21 @@ class WalletListNotes(BitcoinTestFramework):
|
|||
|
||||
assert_equal(False, unspent_tx[0]['change'])
|
||||
assert_equal(txid_2, unspent_tx[0]['txid'])
|
||||
assert_equal('sapling', unspent_tx[0]['type'])
|
||||
assert_equal(True, unspent_tx[0]['spendable'])
|
||||
assert_equal(saplingzaddr, unspent_tx[0]['address'])
|
||||
assert_equal(receive_amount_2, unspent_tx[0]['amount'])
|
||||
|
||||
assert_equal(False, unspent_tx[1]['change'])
|
||||
assert_equal(txid_3, unspent_tx[1]['txid'])
|
||||
assert_equal('sapling', unspent_tx[1]['type'])
|
||||
assert_equal(True, unspent_tx[1]['spendable'])
|
||||
assert_equal(saplingzaddr2, unspent_tx[1]['address'])
|
||||
assert_equal(receive_amount_3, unspent_tx[1]['amount'])
|
||||
|
||||
assert_equal(True, unspent_tx[2]['change'])
|
||||
assert_equal(txid_3, unspent_tx[2]['txid'])
|
||||
assert_equal('sprout', unspent_tx[2]['type'])
|
||||
assert_equal(True, unspent_tx[2]['spendable'])
|
||||
assert_equal(sproutzaddr, unspent_tx[2]['address'])
|
||||
assert_equal(change_amount_3, unspent_tx[2]['amount'])
|
||||
|
|
|
@ -26,6 +26,15 @@ class WalletShieldCoinbaseUANU5(WalletShieldCoinbaseTest):
|
|||
assert_equal(balances['pools']['sapling']['valueZat'], expected * COIN)
|
||||
# assert_equal(balances['pools']['orchard']['valueZat'], expected * COIN)
|
||||
|
||||
# While we're at it, check that z_listunspent only shows outputs with
|
||||
# the Unified Address (not the Orchard receiver), and of the expected
|
||||
# type.
|
||||
unspent = node.z_listunspent(1, 999999, False, [self.addr])
|
||||
assert_equal(
|
||||
[{'type': 'sapling', 'address': self.addr} for _ in unspent],
|
||||
[{'type': x['type'], 'address': x['address']} for x in unspent],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Test shielding to a unified address with NU5 activated")
|
||||
|
|
|
@ -24,6 +24,15 @@ class WalletShieldCoinbaseUASapling(WalletShieldCoinbaseTest):
|
|||
assert_equal(balances['pools']['sapling']['valueZat'], expected * COIN)
|
||||
assert('orchard' not in balances['pools'])
|
||||
|
||||
# While we're at it, check that z_listunspent only shows outputs with
|
||||
# the Unified Address (not the Sapling receiver), and of the expected
|
||||
# type.
|
||||
unspent = node.z_listunspent(1, 999999, False, [self.addr])
|
||||
assert_equal(
|
||||
[{'type': 'sapling', 'address': self.addr} for _ in unspent],
|
||||
[{'type': x['type'], 'address': x['address']} for x in unspent],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Test shielding to a unified address with sapling activated (but not NU5)")
|
||||
|
|
|
@ -129,6 +129,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
|||
assert(len(results) == 0)
|
||||
results = self.nodes[0].z_listunspent(0) # set minconf to zero
|
||||
assert(len(results) == 1)
|
||||
assert_equal(results[0]["type"], "sapling")
|
||||
assert_equal(results[0]["address"], myzaddr)
|
||||
assert_equal(results[0]["amount"], shieldvalue)
|
||||
assert_equal(results[0]["confirmations"], 0)
|
||||
|
@ -140,6 +141,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
|||
# Verify that z_listunspent returns one note which has been confirmed
|
||||
results = self.nodes[0].z_listunspent()
|
||||
assert(len(results) == 1)
|
||||
assert_equal(results[0]["type"], "sapling")
|
||||
assert_equal(results[0]["address"], myzaddr)
|
||||
assert_equal(results[0]["amount"], shieldvalue)
|
||||
assert_equal(results[0]["confirmations"], 1)
|
||||
|
@ -148,6 +150,7 @@ class WalletShieldingCoinbaseTest (BitcoinTestFramework):
|
|||
# Verify that z_listunspent returns note for watchonly address on node 3.
|
||||
results = self.nodes[3].z_listunspent(1, 999, True)
|
||||
assert(len(results) == 1)
|
||||
assert_equal(results[0]["type"], "sapling")
|
||||
assert_equal(results[0]["address"], myzaddr)
|
||||
assert_equal(results[0]["amount"], shieldvalue)
|
||||
assert_equal(results[0]["confirmations"], 1)
|
||||
|
|
|
@ -2256,21 +2256,22 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||
"Optionally filter to only include notes sent to specified addresses.\n"
|
||||
"When minconf is 0, unspent notes with zero confirmations are returned, even though they are not immediately spendable.\n"
|
||||
"Results are an array of Objects, each of which has:\n"
|
||||
"{txid, jsindex, jsoutindex, confirmations, address, amount, memo} (Sprout)\n"
|
||||
"{txid, outindex, confirmations, address, amount, memo} (Sapling)\n"
|
||||
"{txid, type, jsindex, jsoutindex, confirmations, address, amount, memo} (Sprout)\n"
|
||||
"{txid, type, outindex, confirmations, address, amount, memo} (Sapling)\n"
|
||||
"\nArguments:\n"
|
||||
"1. minconf (numeric, optional, default=1) The minimum confirmations to filter\n"
|
||||
"2. maxconf (numeric, optional, default=9999999) The maximum confirmations to filter\n"
|
||||
"3. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
|
||||
"4. \"addresses\" (string) A json array of zaddrs (both Sprout and Sapling) to filter on. Duplicate addresses not allowed.\n"
|
||||
"4. \"addresses\" (string) A json array of shielded addresses to filter on. Duplicate addresses not allowed.\n"
|
||||
" [\n"
|
||||
" \"address\" (string) zaddr\n"
|
||||
" \"address\" (string) Sprout, Sapling, or Unified address\n"
|
||||
" ,...\n"
|
||||
" ]\n"
|
||||
"\nResult (output indices for only one pool will be present):\n"
|
||||
"[ (array of json object)\n"
|
||||
" {\n"
|
||||
" \"txid\" : \"txid\", (string) the transaction id \n"
|
||||
" \"type\" : \"sprout|sapling|orchard\", (string) The shielded pool\n"
|
||||
" \"jsindex\" (sprout) : n, (numeric) the joinsplit index\n"
|
||||
" \"jsoutindex\" (sprout) : n, (numeric) the output index of the joinsplit\n"
|
||||
" \"outindex\" (sapling) : n, (numeric) the output index\n"
|
||||
|
@ -2373,6 +2374,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||
for (auto & entry : sproutEntries) {
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV("txid", entry.jsop.hash.ToString());
|
||||
obj.pushKV("type", ADDR_TYPE_SPROUT);
|
||||
obj.pushKV("jsindex", (int)entry.jsop.js );
|
||||
obj.pushKV("jsoutindex", (int)entry.jsop.n);
|
||||
obj.pushKV("confirmations", entry.confirmations);
|
||||
|
@ -2391,12 +2393,19 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
|
|||
for (auto & entry : saplingEntries) {
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV("txid", entry.op.hash.ToString());
|
||||
obj.pushKV("type", ADDR_TYPE_SAPLING);
|
||||
obj.pushKV("outindex", (int)entry.op.n);
|
||||
obj.pushKV("confirmations", entry.confirmations);
|
||||
bool hasSaplingSpendingKey = pwalletMain->HaveSaplingSpendingKeyForAddress(entry.address);
|
||||
obj.pushKV("spendable", hasSaplingSpendingKey);
|
||||
// TODO: If we found this entry via a UA, show that instead.
|
||||
obj.pushKV("address", keyIO.EncodePaymentAddress(entry.address));
|
||||
obj.pushKV("address", keyIO.EncodePaymentAddress([&]() {
|
||||
auto ua = pwalletMain->FindUnifiedAddressByReceiver(entry.address);
|
||||
if (ua.has_value()) {
|
||||
return libzcash::PaymentAddress{ua.value()};
|
||||
} else {
|
||||
return libzcash::PaymentAddress{entry.address};
|
||||
}
|
||||
}()));
|
||||
obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value()))); // note.value() is equivalent to plaintext.value()
|
||||
obj.pushKV("memo", HexStr(entry.memo));
|
||||
if (hasSaplingSpendingKey) {
|
||||
|
@ -3235,6 +3244,7 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
|
|||
"z_listaddresses ( includeWatchonly )\n"
|
||||
"\nDEPRECATED\n"
|
||||
"\nReturns the list of shielded addresses belonging to the wallet.\n"
|
||||
"\nThis never returns Unified Addresses; see 'listaddresses' for them.\n"
|
||||
"\nArguments:\n"
|
||||
"1. includeWatchonly (bool, optional, default=false) Also include watchonly addresses (see 'z_importviewingkey')\n"
|
||||
"\nResult:\n"
|
||||
|
@ -3269,6 +3279,10 @@ UniValue z_listaddresses(const UniValue& params, bool fHelp)
|
|||
std::set<libzcash::SaplingPaymentAddress> addresses;
|
||||
pwalletMain->GetSaplingPaymentAddresses(addresses);
|
||||
for (auto addr : addresses) {
|
||||
// Don't show Sapling receivers that are part of an account in the wallet.
|
||||
if (pwalletMain->FindUnifiedAddressByReceiver(addr).has_value()) {
|
||||
continue;
|
||||
}
|
||||
if (fIncludeWatchonly || pwalletMain->HaveSaplingSpendingKeyForAddress(addr)) {
|
||||
ret.push_back(keyIO.EncodePaymentAddress(addr));
|
||||
}
|
||||
|
@ -4066,13 +4080,14 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp)
|
|||
|
||||
// If the note belongs to a Sapling address that is part of an account in the
|
||||
// wallet, show the corresponding Unified Address.
|
||||
std::string address;
|
||||
const auto ua = pwalletMain->FindUnifiedAddressByReceiver(pa);
|
||||
if (ua.has_value()) {
|
||||
address = keyIO.EncodePaymentAddress(ua.value());
|
||||
} else {
|
||||
address = keyIO.EncodePaymentAddress(pa);
|
||||
}
|
||||
std::string address = keyIO.EncodePaymentAddress([&]() {
|
||||
auto ua = pwalletMain->FindUnifiedAddressByReceiver(pa);
|
||||
if (ua.has_value()) {
|
||||
return libzcash::PaymentAddress{ua.value()};
|
||||
} else {
|
||||
return libzcash::PaymentAddress{pa};
|
||||
}
|
||||
}());
|
||||
|
||||
UniValue entry(UniValue::VOBJ);
|
||||
entry.pushKV("type", ADDR_TYPE_SAPLING);
|
||||
|
@ -4119,13 +4134,14 @@ UniValue z_viewtransaction(const UniValue& params, bool fHelp)
|
|||
|
||||
// If the note belongs to a Sapling address that is part of an account in the
|
||||
// wallet, show the corresponding Unified Address.
|
||||
std::string address;
|
||||
const auto ua = pwalletMain->FindUnifiedAddressByReceiver(pa);
|
||||
if (ua.has_value()) {
|
||||
address = keyIO.EncodePaymentAddress(ua.value());
|
||||
} else {
|
||||
address = keyIO.EncodePaymentAddress(pa);
|
||||
}
|
||||
std::string address = keyIO.EncodePaymentAddress([&]() {
|
||||
auto ua = pwalletMain->FindUnifiedAddressByReceiver(pa);
|
||||
if (ua.has_value()) {
|
||||
return libzcash::PaymentAddress{ua.value()};
|
||||
} else {
|
||||
return libzcash::PaymentAddress{pa};
|
||||
}
|
||||
}());
|
||||
|
||||
UniValue entry(UniValue::VOBJ);
|
||||
entry.pushKV("type", ADDR_TYPE_SAPLING);
|
||||
|
|
Loading…
Reference in New Issue