Repository: bitcoin/bitcoin
File: src/rpc/blockchain.cpp (C++)

Code before:

        ret.pushKV("from_height", start_block_height);
        ret.pushKV("to_height", start_index->nHeight); // start_index is always the last scanned block here
        ret.pushKV("relevant_blocks", std::move(blocks));
        ret.pushKV("completed", completed);
    }
    else {
        throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid action '%s'", request.params[0].get_str()));
    }
    return ret;
},
    };
}

static RPCHelpMan getdescriptoractivity()
{
    return RPCHelpMan{
        "getdescriptoractivity",
        "Get spend and receive activity associated with a set of descriptors for a set of blocks. "
        "This command pairs well with the `relevant_blocks` output of `scanblocks()`.\n"
        "This call may take several minutes. If you encounter timeouts, try specifying no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
        {
            RPCArg{"blockhashes", RPCArg::Type::ARR, RPCArg::Optional::NO, "The list of blockhashes to examine for activity. Order doesn't matter. Must be along main chain or an error is thrown.\n", {
                {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A valid blockhash"},
            }},
            RPCArg{"scanobjects", RPCArg::Type::ARR, RPCArg::Optional::NO, "Array of scan objects. Every scan object is either a string descriptor or an object:", {
                output_descriptor,
                obj_with_output_descriptor},
                scanobjects_oneline_description},
            {"include_mempool", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to include unconfirmed activity"},
        },
        RPCResult{
            RPCResult::Type::OBJ, "", "", {
                {RPCResult::Type::ARR, "activity", "events", {
                    {RPCResult::Type::OBJ, "", "", {
                        {RPCResult::Type::STR, "type", "always 'spend'"},
                        {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the spent output"},
                        {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The blockhash this spend appears in (omitted if unconfirmed)"},
                        {RPCResult::Type::NUM, "height", /*optional=*/true, "Height of the spend (omitted if unconfirmed)"},
                        {RPCResult::Type::STR_HEX, "spend_txid", "The txid of the spending transaction"},
                        {RPCResult::Type::NUM, "spend_vout", "The vout of the spend"},
                        {RPCResult::Type::STR_HEX, "prevout_txid", "The txid of the prevout"},
                        {RPCResult::Type::NUM, "prevout_vout", "The vout of the prevout"},
                        {RPCResult::Type::OBJ, "prevout_spk", "", ScriptPubKeyDoc()},
                    }},
                    {RPCResult::Type::OBJ, "", "", {
                        {RPCResult::Type::STR, "type", "always 'receive'"},
                        {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the new output"},
                        {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The block that this receive is in (omitted if unconfirmed)"},
                        {RPCResult::Type::NUM, "height", /*optional=*/true, "The height of the receive (omitted if unconfirmed)"},
                        {RPCResult::Type::STR_HEX, "txid", "The txid of the receiving transaction"},

Review comment (suggestion):
nit: Unfortunately we have to keep the name "scanobjects" for backwards compatibility, but I think the description should be made more relevant to what this RPC is doing, in line with the `blockhashes` documentation, e.g.

```suggestion
            RPCArg{"scanobjects", RPCArg::Type::ARR, RPCArg::Optional::NO, "The list of descriptors (scan objects) to examine for activity. Every scan object is either a string descriptor or an object:", {
```

Code after:
    }
    return ret;
},
    };
}

static RPCHelpMan getdescriptoractivity()
{
    return RPCHelpMan{
        "getdescriptoractivity",
        "Get spend and receive activity associated with a set of descriptors for a set of blocks. "
        "This command pairs well with the `relevant_blocks` output of `scanblocks()`.\n"
        "This call may take several minutes. If you encounter timeouts, try specifying no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
        {
            RPCArg{"blockhashes", RPCArg::Type::ARR, RPCArg::Optional::NO, "The list of blockhashes to examine for activity. Order doesn't matter. Must be along main chain or an error is thrown.\n", {
                {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "A valid blockhash"},
            }},
            RPCArg{"scanobjects", RPCArg::Type::ARR, RPCArg::Optional::NO, "The list of descriptors (scan objects) to examine for activity. Every scan object is either a string descriptor or an object:",
                {
                    {"descriptor", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "An output descriptor"},
                    output_descriptor_obj,
                },
                RPCArgOptions{.oneline_description="[scanobjects,...]"},
            },
            {"include_mempool", RPCArg::Type::BOOL, RPCArg::Default{true}, "Whether to include unconfirmed activity"},
        },
        RPCResult{
            RPCResult::Type::OBJ, "", "", {
                {RPCResult::Type::ARR, "activity", "events", {
                    {RPCResult::Type::OBJ, "", "", {
                        {RPCResult::Type::STR, "type", "always 'spend'"},
                        {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the spent output"},
                        {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The blockhash this spend appears in (omitted if unconfirmed)"},
                        {RPCResult::Type::NUM, "height", /*optional=*/true, "Height of the spend (omitted if unconfirmed)"},
                        {RPCResult::Type::STR_HEX, "spend_txid", "The txid of the spending transaction"},
                        {RPCResult::Type::NUM, "spend_vout", "The vout of the spend"},
                        {RPCResult::Type::STR_HEX, "prevout_txid", "The txid of the prevout"},
                        {RPCResult::Type::NUM, "prevout_vout", "The vout of the prevout"},
                        {RPCResult::Type::OBJ, "prevout_spk", "", ScriptPubKeyDoc()},
                    }},
                    {RPCResult::Type::OBJ, "", "", {
                        {RPCResult::Type::STR, "type", "always 'receive'"},
                        {RPCResult::Type::STR_AMOUNT, "amount", "The total amount in " + CURRENCY_UNIT + " of the new output"},
                        {RPCResult::Type::STR_HEX, "blockhash", /*optional=*/true, "The block that this receive is in (omitted if unconfirmed)"},
                        {RPCResult::Type::NUM, "height", /*optional=*/true, "The height of the receive (omitted if unconfirmed)"},
                        {RPCResult::Type::STR_HEX, "txid", "The txid of the receiving transaction"},
                        {RPCResult::Type::NUM, "vout", "The vout of the receiving output"},
                        {RPCResult::Type::OBJ, "output_spk", "", ScriptPubKeyDoc()},
                    }},
                    // TODO is the skip_type_check avoidable with a heterogeneous ARR?
                }, /*skip_type_check=*/true},