status-go/services/wallet/transfers_query.go
Dmitry a67184adbd Wallet database isolated by the network id
Wallet database refactored so that every query ensures isolation by the network id.
Network id provided when database object is created, thus it is transparent to other parts
of the wallet module.

Additionally every uniqueness index is changed to ensure that it doesn't prevent adding
object with same id but from a different network.
2019-08-21 10:44:50 +03:00

97 lines
2.2 KiB
Go

package wallet
import (
"bytes"
"database/sql"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
const baseTransfersQuery = "SELECT transfers.hash, type, blocks.hash, blocks.number, blocks.timestamp, address, tx, sender, receipt, log FROM transfers JOIN blocks ON blk_hash = blocks.hash"
func newTransfersQuery() *transfersQuery {
buf := bytes.NewBuffer(nil)
buf.WriteString(baseTransfersQuery)
return &transfersQuery{buf: buf}
}
type transfersQuery struct {
buf *bytes.Buffer
args []interface{}
added bool
}
func (q *transfersQuery) andOrWhere() {
if q.added {
q.buf.WriteString(" AND")
} else {
q.buf.WriteString(" WHERE")
}
}
func (q *transfersQuery) FilterStart(start *big.Int) *transfersQuery {
if start != nil {
q.andOrWhere()
q.added = true
q.buf.WriteString(" blocks.number >= ?")
q.args = append(q.args, (*SQLBigInt)(start))
}
return q
}
func (q *transfersQuery) FilterEnd(end *big.Int) *transfersQuery {
if end != nil {
q.andOrWhere()
q.added = true
q.buf.WriteString(" blocks.number <= ?")
q.args = append(q.args, (*SQLBigInt)(end))
}
return q
}
func (q *transfersQuery) FilterNetwork(network uint64) *transfersQuery {
q.andOrWhere()
q.added = true
q.buf.WriteString(" blocks.network_id = ?")
q.args = append(q.args, network)
return q
}
func (q *transfersQuery) FilterAddress(address common.Address) *transfersQuery {
q.andOrWhere()
q.added = true
q.buf.WriteString(" address = ?")
q.args = append(q.args, address)
return q
}
func (q *transfersQuery) String() string {
return q.buf.String()
}
func (q *transfersQuery) Args() []interface{} {
return q.args
}
func (q *transfersQuery) Scan(rows *sql.Rows) (rst []Transfer, err error) {
for rows.Next() {
transfer := Transfer{
BlockNumber: &big.Int{},
Transaction: &types.Transaction{},
Receipt: &types.Receipt{},
Log: &types.Log{},
}
err = rows.Scan(
&transfer.ID, &transfer.Type, &transfer.BlockHash,
(*SQLBigInt)(transfer.BlockNumber), &transfer.Timestamp, &transfer.Address,
&JSONBlob{transfer.Transaction}, &transfer.From, &JSONBlob{transfer.Receipt}, &JSONBlob{transfer.Log})
if err != nil {
return nil, err
}
rst = append(rst, transfer)
}
return rst, nil
}