-
Notifications
You must be signed in to change notification settings - Fork 4
/
client.go
107 lines (100 loc) · 2.76 KB
/
client.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
package lib
import (
"database/sql"
"errors"
"fmt"
"github.com/memocash/index/client/lib/graph"
"github.com/memocash/index/ref/bitcoin/wallet"
"time"
)
type Client struct {
GraphUrl string
Database Database
}
func (c *Client) updateDb(addresses []wallet.Addr) error {
var prevLastUpdates []graph.AddressUpdate
for {
lastUpdates, err := c.Database.GetAddressLastUpdate(addresses)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return fmt.Errorf("error getting address last update; %w", err)
}
var needsUpdate bool
LastUpdateLoop:
for _, lastUpdate := range lastUpdates {
for _, prevLastUpdate := range prevLastUpdates {
if lastUpdate.Address == prevLastUpdate.Address && lastUpdate.Time.Equal(prevLastUpdate.Time) {
continue LastUpdateLoop
}
}
needsUpdate = true
}
if !needsUpdate {
break
}
prevLastUpdates = lastUpdates
history, err := graph.GetHistory(c.GraphUrl, lastUpdates)
if err != nil {
return fmt.Errorf("error getting history txs; %w", err)
}
if err := c.Database.SaveTxs(history.GetAllTxs()); err != nil {
return fmt.Errorf("error saving txs; %w", err)
}
var addressUpdates []graph.AddressUpdate
for _, addrTxs := range history {
var maxTime time.Time
for _, tx := range addrTxs.Txs {
if tx.Seen.After(maxTime) {
maxTime = tx.Seen
}
}
addressUpdates = append(addressUpdates, graph.AddressUpdate{
Address: addrTxs.Address,
Time: maxTime,
})
}
if err := c.Database.SetAddressLastUpdate(addressUpdates); err != nil {
return fmt.Errorf("error setting address last updates for client update db; %w", err)
}
}
return nil
}
func (c *Client) Broadcast(txRaw string) error {
if err := graph.Broadcast(c.GraphUrl, txRaw); err != nil {
return fmt.Errorf("error broadcasting lib client tx; %w", err)
}
return nil
}
func (c *Client) GetBalance(addresses []wallet.Addr) (*Balance, error) {
err := c.updateDb(addresses)
if err != nil {
return nil, fmt.Errorf("error updating db for get balance; %w", err)
}
balance, err := c.Database.GetAddressBalance(addresses)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, fmt.Errorf("error getting address balance from database; %w", err)
}
return balance, nil
}
func (c *Client) GetUtxos(addresses []wallet.Addr) ([]graph.Output, error) {
err := c.updateDb(addresses)
if err != nil {
return nil, fmt.Errorf("error updating db for get utxos; %w", err)
}
utxos, err := c.Database.GetUtxos(addresses)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, nil
}
return nil, fmt.Errorf("error getting utxos from database; %w", err)
}
return utxos, nil
}
func NewClient(graphUrl string, database Database) *Client {
return &Client{
GraphUrl: graphUrl,
Database: database,
}
}