aboutsummaryrefslogtreecommitdiff
path: root/src/libwalletqt/TransactionHistory.cpp
blob: 86e9c4c707ebfdca7fd167a771655b6b58604ab8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include "TransactionHistory.h"
#include "TransactionInfo.h"
#include <wallet/api/wallet2_api.h>

#include <QFile>
#include <QDebug>


TransactionInfo *TransactionHistory::transaction(int index)
{

    if (index < 0 || index >= m_tinfo.size()) {
        qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
        qCritical("%s: there's %d transactions in backend", __FUNCTION__, m_pimpl->count());
        return nullptr;
    }
    return m_tinfo.at(index);
}

//// XXX: not sure if this method really needed;
//TransactionInfo *TransactionHistory::transaction(const QString &id)
//{
//    return nullptr;
//}

QList<TransactionInfo *> TransactionHistory::getAll(quint32 accountIndex) const
{
    // XXX this invalidates previously saved history that might be used by model
    emit refreshStarted();
    qDeleteAll(m_tinfo);
    m_tinfo.clear();

    QDateTime firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block
    QDateTime lastDateTime  = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
    quint64 lastTxHeight = 0;
    m_locked = false;
    m_minutesToUnlock = 0;
    TransactionHistory * parent = const_cast<TransactionHistory*>(this);
    for (const auto i : m_pimpl->getAll()) {
        TransactionInfo * ti = new TransactionInfo(i, parent);
        if (ti->subaddrAccount() != accountIndex) {
            delete ti;
            continue;
        }
        m_tinfo.append(ti);
        // looking for transactions timestamp scope
        if (ti->timestamp() >= lastDateTime) {
            lastDateTime = ti->timestamp();
        }
        if (ti->timestamp() <= firstDateTime) {
            firstDateTime = ti->timestamp();
        }
        quint64 requiredConfirmations = (ti->blockHeight() < ti->unlockTime()) ? ti->unlockTime() - ti->blockHeight() : 10;
        // store last tx height
        if (ti->confirmations() < requiredConfirmations && ti->blockHeight() >= lastTxHeight) {
            lastTxHeight = ti->blockHeight();
            // TODO: Fetch block time and confirmations needed from wallet2?
            m_minutesToUnlock = (requiredConfirmations - ti->confirmations()) * 2;
            m_locked = true;
        }

    }
    emit refreshFinished();

    if (m_firstDateTime != firstDateTime) {
        m_firstDateTime = firstDateTime;
        emit firstDateTimeChanged();
    }
    if (m_lastDateTime != lastDateTime) {
        m_lastDateTime = lastDateTime;
        emit lastDateTimeChanged();
    }

    return m_tinfo;
}

void TransactionHistory::refresh(quint32 accountIndex)
{
    // rebuilding transaction list in wallet_api;
    m_pimpl->refresh();
    // copying list here and keep track on every item to avoid memleaks
    getAll(accountIndex);
}

quint64 TransactionHistory::count() const
{
    return m_tinfo.count();
}

QDateTime TransactionHistory::firstDateTime() const
{
    return m_firstDateTime;
}

QDateTime TransactionHistory::lastDateTime() const
{
    return m_lastDateTime;
}

quint64 TransactionHistory::minutesToUnlock() const
{
    return m_minutesToUnlock;
}

bool TransactionHistory::TransactionHistory::locked() const
{
    return m_locked;
}


TransactionHistory::TransactionHistory(Monero::TransactionHistory *pimpl, QObject *parent)
    : QObject(parent), m_pimpl(pimpl), m_minutesToUnlock(0), m_locked(false)
{
    m_firstDateTime  = QDateTime(QDate(2014, 4, 18)); // the genesis block
    m_lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
}

QString TransactionHistory::writeCSV(quint32 accountIndex, QString out)
{
    QList<TransactionInfo *> history = this->getAll(accountIndex);
    if(history.count() < 1){
        return QString("");
    }

    // construct filename
    qint64 now = QDateTime::currentDateTime().currentMSecsSinceEpoch();
    QString fn = QString(QString("%1/monero-txs_%2.csv").arg(out, QString::number(now / 1000)));

    // open file
    QFile data(fn);
    if(!data.open(QFile::WriteOnly | QFile::Truncate)){
        return QString("");
    }

    // write header
    QTextStream output(&data);
    output << "blockHeight,epoch,date,direction,amount,atomicAmount,fee,txid,label,subaddrAccount,paymentId\n";

    foreach(const TransactionInfo *info, history)
    {
        // collect column data
        double amount = info->amount();
        quint64 atomicAmount = info->atomicAmount();
        quint32 subaddrAccount = info->subaddrAccount();
        QString fee = info->fee();
        QString direction = QString("");
        TransactionInfo::Direction _direction = info->direction();
        if(_direction == TransactionInfo::Direction_In)
        {
            direction = QString("in");
        }
        else if(_direction == TransactionInfo::Direction_Out){
            direction = QString("out");
        }
        else {
            continue;  // skip TransactionInfo::Direction_Both
        }
        QString label = info->label();
        label.remove(QChar('"'));  // reserved
        quint64 blockHeight = info->blockHeight();
        QDateTime timeStamp = info->timestamp();
        QString date = info->date() + " " + info->time();
        uint epoch = timeStamp.toTime_t();
        QString displayAmount = info->displayAmount();
        QString paymentId = info->paymentId();
        if(paymentId == "0000000000000000"){
            paymentId = "";
        }

        // format and write
        QString line = QString("%1,%2,%3,%4,%5,%6,%7,%8,\"%9\",%10,%11\n")
            .arg(QString::number(blockHeight), QString::number(epoch), date)
            .arg(direction, QString::number(amount), QString::number(atomicAmount))
            .arg(info->fee(), info->hash(), label, QString::number(subaddrAccount))
            .arg(paymentId);
        output << line;
    }

    data.close();
    return fn;
}