Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/wallet/api/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(wallet_api_sources
wallet.cpp
wallet_manager.cpp
enote_details.cpp
transaction_info.cpp
transaction_history.cpp
pending_transaction.cpp
Expand All @@ -48,6 +49,7 @@ set(wallet_api_headers
set(wallet_api_private_headers
wallet.h
wallet_manager.h
enote_details.h
transaction_info.h
transaction_history.h
pending_transaction.h
Expand Down
94 changes: 94 additions & 0 deletions src/wallet/api/enote_details.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright (c) 2014-2025, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "enote_details.h"


namespace Monero {

EnoteDetails::~EnoteDetails() {}


EnoteDetailsImpl::EnoteDetailsImpl():
m_block_height(0),
m_internal_enote_index(0),
m_global_enote_index(0),
m_spent(false),
m_frozen(false),
m_spent_height(0),
m_amount(0),
m_protocol_version(TxProtocol_CryptoNote),
m_key_image_known(false),
m_key_image_request(false),
m_pk_index(0),
m_key_image_partial(false)
{
}

EnoteDetailsImpl::~EnoteDetailsImpl() {}

std::string EnoteDetailsImpl::onetimeAddress() const
{ return m_onetime_address; }
std::string EnoteDetailsImpl::viewTag() const
{ return m_view_tag; }
std::uint64_t EnoteDetailsImpl::blockHeight() const
{ return m_block_height; }
std::string EnoteDetailsImpl::txId() const
{ return m_tx_id; }
std::uint64_t EnoteDetailsImpl::internalEnoteIndex() const
{ return m_internal_enote_index; }
std::uint64_t EnoteDetailsImpl::globalEnoteIndex() const
{ return m_global_enote_index; }
bool EnoteDetailsImpl::isSpent() const
{ return m_spent; }
bool EnoteDetailsImpl::isFrozen() const
{ return m_frozen; }
std::uint64_t EnoteDetailsImpl::spentHeight() const
{ return m_spent_height; }
std::string EnoteDetailsImpl::keyImage() const
{ return m_key_image; }
std::string EnoteDetailsImpl::mask() const
{ return m_mask; }
std::uint64_t EnoteDetailsImpl::amount() const
{ return m_amount; }
EnoteDetails::TxProtocol EnoteDetailsImpl::protocolVersion() const
{ return m_protocol_version; }
bool EnoteDetailsImpl::isKeyImageKnown() const
{ return m_key_image_known; }
bool EnoteDetailsImpl::isKeyImageRequest() const
{ return m_key_image_request; }
std::uint64_t EnoteDetailsImpl::pkIndex() const
{ return m_pk_index; }
std::vector<std::pair<std::uint64_t, std::string>> EnoteDetailsImpl::uses() const
{ return m_uses; }

// Multisig
bool EnoteDetailsImpl::isKeyImagePartial() const
{ return m_key_image_partial; }

} // namespace
107 changes: 107 additions & 0 deletions src/wallet/api/enote_details.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// Copyright (c) 2014-2025, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "wallet/api/wallet2_api.h"


namespace Monero {

class EnoteDetailsImpl : public EnoteDetails
{
public:
EnoteDetailsImpl();
~EnoteDetailsImpl() override;
std::string onetimeAddress() const override;
std::string viewTag() const override;
std::uint64_t blockHeight() const override;
std::string txId() const override;
std::uint64_t internalEnoteIndex() const override;
std::uint64_t globalEnoteIndex() const override;
bool isSpent() const override;
bool isFrozen() const override;
std::uint64_t spentHeight() const override;
std::string keyImage() const override;
std::string mask() const override;
std::uint64_t amount() const override;
TxProtocol protocolVersion() const override;
bool isKeyImageKnown() const override;
bool isKeyImageRequest() const override;
std::uint64_t pkIndex() const override;
std::vector<std::pair<std::uint64_t, std::string>> uses() const override;

// Multisig
bool isKeyImagePartial() const override;

private:
friend class WalletImpl;

// Ko
std::string m_onetime_address;
// view_tag
std::string m_view_tag;
// this enote was received at block height
std::uint64_t m_block_height;
// tx id in which tx enote was received
std::string m_tx_id;
// relative index in tx
std::uint64_t m_internal_enote_index;
// absolute index from `cryptonote::COMMAND_RPC_GET_TRANSACTIONS::entry.output_indices`
std::uint64_t m_global_enote_index;
// is spent
bool m_spent;
// is frozen
bool m_frozen;
// blockchain height, set if spent
std::uint64_t m_spent_height;
// key image
std::string m_key_image;
// x, blinding factor in amount commitment C = x G + a H
std::string m_mask;
// a
std::uint64_t m_amount;
// protocol version : TxProtocol_CryptoNote / TxProtocol_RingCT
TxProtocol m_protocol_version;
// is key image known
bool m_key_image_known;
// view wallets: we want to request it; cold wallets: it was requested
bool m_key_image_request;
// public key index in tx_extra
std::uint64_t m_pk_index;
// track uses of this enote in the blockchain in the format [ [block_height, tx_id], ... ] if `wallet2::m_track_uses` is true (default is false)
std::vector<std::pair<std::uint64_t, std::string>> m_uses;

// Multisig
bool m_key_image_partial;
// NOTE : These multisig members are part of wallet2 transfer_details and may need to get added here.
/*
std::vector<rct::key> m_multisig_k;
std::vector<multisig_info> m_multisig_info; // one per other participant
*/
};

} // namespace
23 changes: 23 additions & 0 deletions src/wallet/api/pending_transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,29 @@ bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite)
return m_status == Status_Ok;
}

std::string PendingTransactionImpl::convertTxToStr()
{
std::string tx;
LOG_PRINT_L3("m_pending_tx size: " << m_pending_tx.size());

try {
tx = m_wallet.m_wallet->dump_tx_to_str(m_pending_tx);
m_status = Status_Ok;
return tx;
} catch (const tools::error::wallet_internal_error&) {
m_errorString = tr("Wallet internal eror.");
m_status = Status_Error;
} catch (const std::exception &e) {
m_errorString = string(tr("Unknown exception: ")) + e.what();
m_status = Status_Error;
} catch (...) {
m_errorString = tr("Unhandled exception");
LOG_ERROR(m_errorString);
m_status = Status_Error;
}
return ""; // m_status != Status_Ok
}

uint64_t PendingTransactionImpl::amount() const
{
uint64_t result = 0;
Expand Down
3 changes: 3 additions & 0 deletions src/wallet/api/pending_transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class PendingTransactionImpl : public PendingTransaction
std::string multisigSignData() override;
void signMultisigTx() override;
std::vector<std::string> signersKeys() const override;
std::string convertTxToStr() override;

private:
friend class WalletImpl;
Expand All @@ -69,6 +70,8 @@ class PendingTransactionImpl : public PendingTransaction
std::unordered_set<crypto::public_key> m_signers;
std::vector<std::string> m_tx_device_aux;
std::vector<crypto::key_image> m_key_images;
// wallet2 m_cold_key_images
std::unordered_map<crypto::public_key, crypto::key_image> m_tx_key_images;
};


Expand Down
20 changes: 20 additions & 0 deletions src/wallet/api/transaction_history.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ void TransactionHistoryImpl::refresh()
ti->m_timestamp = pd.m_timestamp;
ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
ti->m_unlock_time = pd.m_unlock_time;
// not used for payment_details
ti->m_change = 0;
ti->m_tx_state = TransactionInfo::TxState_Confirmed;
// not used for payment_details
ti->m_double_spend_seen = false;
m_history.push_back(ti);

}
Expand Down Expand Up @@ -193,6 +198,11 @@ void TransactionHistoryImpl::refresh()
ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
ti->m_timestamp = pd.m_timestamp;
ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
ti->m_unlock_time = pd.m_unlock_time;
ti->m_change = pd.m_change;
ti->m_tx_state = TransactionInfo::TxState_Confirmed;
// not used for confirmed_transfer_details
ti->m_double_spend_seen = false;

// single output transaction might contain multiple transfers
for (const auto &d: pd.m_dests) {
Expand Down Expand Up @@ -229,6 +239,11 @@ void TransactionHistoryImpl::refresh()
ti->m_label = pd.m_subaddr_indices.size() == 1 ? m_wallet->m_wallet->get_subaddress_label({pd.m_subaddr_account, *pd.m_subaddr_indices.begin()}) : "";
ti->m_timestamp = pd.m_timestamp;
ti->m_confirmations = 0;
ti->m_unlock_time = pd.m_tx.unlock_time;
ti->m_change = pd.m_change;
ti->m_tx_state = (TransactionInfo::TxState) pd.m_state;
// not used for unconfirmed_transfer_details
ti->m_double_spend_seen = false;
for (const auto &d : pd.m_dests)
{
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
Expand Down Expand Up @@ -258,6 +273,11 @@ void TransactionHistoryImpl::refresh()
ti->m_label = m_wallet->m_wallet->get_subaddress_label(pd.m_subaddr_index);
ti->m_timestamp = pd.m_timestamp;
ti->m_confirmations = 0;
ti->m_unlock_time = pd.m_unlock_time;
// not used for pool_payment_details
ti->m_change = 0;
ti->m_tx_state = TransactionInfo::TxState_PendingInPool;
ti->m_double_spend_seen = i->second.m_double_spend_seen;
m_history.push_back(ti);

LOG_PRINT_L1(__FUNCTION__ << ": Unconfirmed payment found " << pd.m_amount);
Expand Down
15 changes: 15 additions & 0 deletions src/wallet/api/transaction_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,19 @@ uint64_t TransactionInfoImpl::unlockTime() const
return m_unlock_time;
}

std::uint64_t TransactionInfoImpl::receivedChangeAmount() const
{
return m_change;
}

TransactionInfo::TxState TransactionInfoImpl::txState() const
{
return m_tx_state;
}

bool TransactionInfoImpl::isDoubleSpendSeen() const
{
return m_double_spend_seen;
}

} // namespace
10 changes: 10 additions & 0 deletions src/wallet/api/transaction_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class TransactionInfoImpl : public TransactionInfo
virtual uint64_t confirmations() const override;
virtual uint64_t unlockTime() const override;

std::uint64_t receivedChangeAmount() const override;
TxState txState() const override;
bool isDoubleSpendSeen() const override;

private:
int m_direction;
bool m_pending;
Expand All @@ -81,6 +85,12 @@ class TransactionInfoImpl : public TransactionInfo
std::vector<Transfer> m_transfers;
uint64_t m_confirmations;
uint64_t m_unlock_time;
// received change amount from outgoing transaction
std::uint64_t m_change;
// tx state : TxState_Pending / TxState_PendingInPool / TxState_Failed / TxState_Confirmed
TxState m_tx_state;
// is double spend seen
bool m_double_spend_seen;

friend class TransactionHistoryImpl;

Expand Down
22 changes: 22 additions & 0 deletions src/wallet/api/unsigned_transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,4 +315,26 @@ uint64_t UnsignedTransactionImpl::minMixinCount() const
return min_mixin;
}

std::string UnsignedTransactionImpl::signAsString()
{
if(m_wallet.watchOnly())
{
m_errorString = tr("This is a watch only wallet");
m_status = Status_Error;
return "";
}
tools::wallet2::signed_tx_set signed_txes;
std::vector<tools::wallet2::pending_tx> ptx;
try
{
return m_wallet.m_wallet->sign_tx_dump_to_str(m_unsigned_tx_set, ptx, signed_txes);
}
catch (const std::exception &e)
{
m_errorString = string(tr("Failed to sign transaction ")) + e.what();
m_status = Status_Error;
return "";
}
}

} // namespace
1 change: 1 addition & 0 deletions src/wallet/api/unsigned_transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class UnsignedTransactionImpl : public UnsignedTransaction
bool sign(const std::string &signedFileName) override;
std::string confirmationMessage() const override {return m_confirmationMessage;}
uint64_t minMixinCount() const override;
std::string signAsString() override;

private:
// Callback function to check all loaded tx's and generate confirmationMessage
Expand Down
Loading
Loading