-
Notifications
You must be signed in to change notification settings - Fork 146
/
transactions.go
151 lines (133 loc) · 3.88 KB
/
transactions.go
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
package models
import (
"database/sql"
"encoding/json"
"time"
"github.com/go-gorp/gorp"
)
// TransactionsModel groups operations on Transactions.
type TransactionsModel struct{}
// Transaction is a transaction.
type Transaction struct {
BlockHeight int `db:"block_height" json:"block_height"` // pk1
TxIndex int `db:"tx_index" json:"index"` // pk2
Hash string `db:"hash" json:"hash"`
BlockHash string `db:"block_hash" json:"block_hash"`
Timestamp int64 `db:"timestamp" json:"timestamp"`
TimestampHuman time.Time `db:"-" json:"timestamp_human"`
TxType int `db:"tx_type" json:"type"`
Address string `db:"address" json:"address"`
Raw string `db:"raw" json:"raw"`
Tx interface{} `db:"-" json:"tx"`
}
// PostGet is the hook after SELECT query.
func (tx *Transaction) PostGet(s gorp.SqlExecutor) error {
tx.TimestampHuman = time.Unix(0, tx.Timestamp)
return json.Unmarshal([]byte(tx.Raw), &tx.Tx)
}
// GetTransactionByHash get a transaction by its hash.
func (m *TransactionsModel) GetTransactionByHash(hash string) (tx *Transaction, err error) {
tx = &Transaction{}
query := `SELECT block_height, tx_index, hash, block_hash, timestamp, tx_type,
address, raw
FROM indexed_transactions WHERE hash = ?`
err = chaindb.SelectOne(tx, query, hash)
if err == sql.ErrNoRows {
return nil, nil
}
return tx, err
}
// GetTransactionListOfBlock get a transaction list of block.
func (m *TransactionsModel) GetTransactionListOfBlock(ofBlockHeight int, page, size int) (
txs []*Transaction, pagination *Pagination, err error,
) {
var (
querySQL = `
SELECT
block_height,
tx_index,
hash,
block_hash,
timestamp,
tx_type,
address,
raw
FROM
indexed_transactions
`
countSQL = buildCountSQL(querySQL)
conds []string
args []interface{}
)
pagination = NewPagination(page, size)
conds = append(conds, "block_height = ?")
args = append(args, ofBlockHeight)
querySQL, countSQL = buildSQLWithConds(querySQL, countSQL, conds)
count, err := chaindb.SelectInt(countSQL, args...)
if err != nil {
return nil, pagination, err
}
pagination.SetTotal(int(count))
if pagination.Offset() > pagination.Total {
return txs, pagination, nil
}
querySQL += " ORDER BY tx_index DESC"
querySQL += " LIMIT ? OFFSET ?"
args = append(args, pagination.Limit(), pagination.Offset())
_, err = chaindb.Select(&txs, querySQL, args...)
return txs, pagination, err
}
// GetTransactionList get a transaction list by hash marker.
func (m *TransactionsModel) GetTransactionList(since string, page, size int) (
txs []*Transaction, pagination *Pagination, err error,
) {
var (
sinceBlockHeight = 0
sinceTxIndex = 0
)
if since != "" {
tx, err := m.GetTransactionByHash(since)
if tx == nil {
return txs, pagination, err
}
sinceBlockHeight = tx.BlockHeight
sinceTxIndex = tx.TxIndex
}
var (
querySQL = `
SELECT
block_height,
tx_index,
hash,
block_hash,
timestamp,
tx_type,
address,
raw
FROM
indexed_transactions
`
countSQL = buildCountSQL(querySQL)
conds []string
args []interface{}
)
pagination = NewPagination(page, size)
if sinceBlockHeight > 0 {
conds = append(conds, "(block_height < ? or (block_height = ? and tx_index < ?))")
args = append(args, sinceBlockHeight, sinceBlockHeight, sinceTxIndex)
}
querySQL, countSQL = buildSQLWithConds(querySQL, countSQL, conds)
count, err := chaindb.SelectInt(countSQL, args...)
if err != nil {
return nil, pagination, err
}
pagination.SetTotal(int(count))
if pagination.Offset() > pagination.Total {
return txs, pagination, nil
}
querySQL += " ORDER BY block_height DESC, tx_index DESC"
querySQL += " LIMIT ? OFFSET ?"
args = append(args, pagination.Limit(), pagination.Offset())
_, err = chaindb.Select(&txs, querySQL, args...)
return txs, pagination, err
}