-
Notifications
You must be signed in to change notification settings - Fork 245
/
api.go
177 lines (150 loc) · 5.56 KB
/
api.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
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
package wallet
import (
"context"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log"
)
var (
// ErrServiceNotInitialized returned when wallet is not initialized/started,.
ErrServiceNotInitialized = errors.New("wallet service is not initialized")
)
func NewAPI(s *Service) *API {
return &API{s}
}
// API is class with methods available over RPC.
type API struct {
s *Service
}
// GetTransfersByAddress returns transfers for a single address
func (api *API) GetTransfersByAddress(ctx context.Context, address common.Address, toBlock, limit *hexutil.Big) ([]TransferView, error) {
log.Debug("[WalletAPI:: GetTransfersByAddress] get transfers for an address", "address", address, "block", toBlock, "limit", limit)
if api.s.db == nil {
log.Error("[WalletAPI:: GetTransfersByAddress] db is not initialized")
return nil, ErrServiceNotInitialized
}
var toBlockBN *big.Int
if toBlock != nil {
toBlockBN = toBlock.ToInt()
}
rst, err := api.s.db.GetTransfersByAddress(address, toBlockBN, limit.ToInt().Int64())
if err != nil {
log.Error("[WalletAPI:: GetTransfersByAddress] can't fetch transfers", "err", err)
return nil, err
}
transfersCount := big.NewInt(int64(len(rst)))
if limit.ToInt().Cmp(transfersCount) == 1 {
block, err := api.s.db.GetFirstKnownBlock(address)
if err != nil {
return nil, err
}
if block == nil {
return castToTransferViews(rst), nil
}
from, err := findFirstRange(ctx, address, block, api.s.client)
if err != nil {
return nil, err
}
fromByAddress := map[common.Address]*big.Int{address: from}
toByAddress := map[common.Address]*big.Int{address: block}
balanceCache := newBalanceCache()
blocksCommand := &findAndCheckBlockRangeCommand{
accounts: []common.Address{address},
db: api.s.db,
chain: api.s.reactor.chain,
client: api.s.client,
balanceCache: balanceCache,
feed: api.s.feed,
fromByAddress: fromByAddress,
toByAddress: toByAddress,
}
if err = blocksCommand.Command()(ctx); err != nil {
return nil, err
}
blocks, err := api.s.db.GetBlocksByAddress(address, numberOfBlocksCheckedPerIteration)
if err != nil {
return nil, err
}
log.Info("checking blocks again", "blocks", len(blocks))
if len(blocks) > 0 {
txCommand := &loadTransfersCommand{
accounts: []common.Address{address},
db: api.s.db,
chain: api.s.reactor.chain,
client: api.s.client,
}
err = txCommand.Command()(ctx)
if err != nil {
return nil, err
}
rst, err = api.s.db.GetTransfersByAddress(address, toBlockBN, limit.ToInt().Int64())
if err != nil {
return nil, err
}
}
}
return castToTransferViews(rst), nil
}
// GetTokensBalances return mapping of token balances for every account.
func (api *API) GetTokensBalances(ctx context.Context, accounts, tokens []common.Address) (map[common.Address]map[common.Address]*hexutil.Big, error) {
if api.s.client == nil {
return nil, ErrServiceNotInitialized
}
return GetTokensBalances(ctx, api.s.client, accounts, tokens)
}
func (api *API) GetCustomTokens(ctx context.Context) ([]*Token, error) {
log.Debug("call to get custom tokens")
rst, err := api.s.db.GetCustomTokens()
log.Debug("result from database for custom tokens", "len", len(rst))
return rst, err
}
func (api *API) AddCustomToken(ctx context.Context, token Token) error {
log.Debug("call to create or edit custom token")
err := api.s.db.AddCustomToken(token)
log.Debug("result from database for create or edit custom token", "err", err)
return err
}
func (api *API) DeleteCustomToken(ctx context.Context, address common.Address) error {
log.Debug("call to remove custom token")
err := api.s.db.DeleteCustomToken(address)
log.Debug("result from database for remove custom token", "err", err)
return err
}
func (api *API) GetPendingTransactions(ctx context.Context) ([]*PendingTransaction, error) {
log.Debug("call to get pending transactions")
rst, err := api.s.db.GetPendingTransactions()
log.Debug("result from database for pending transactions", "len", len(rst))
return rst, err
}
func (api *API) GetPendingOutboundTransactionsByAddress(ctx context.Context, address common.Address) ([]*PendingTransaction, error) {
log.Debug("call to get pending transactions by address")
rst, err := api.s.db.GetPendingOutboundTransactionsByAddress(address)
log.Debug("result from database for pending transactions by address", "len", len(rst))
return rst, err
}
func (api *API) StorePendingTransaction(ctx context.Context, trx PendingTransaction) error {
log.Debug("call to create or edit pending transaction")
err := api.s.db.StorePendingTransaction(trx)
log.Debug("result from database for creating or editing a pending transaction", "err", err)
return err
}
func (api *API) DeletePendingTransaction(ctx context.Context, transactionHash common.Hash) error {
log.Debug("call to remove pending transaction")
err := api.s.db.DeletePendingTransaction(transactionHash)
log.Debug("result from database for remove pending transaction", "err", err)
return err
}
func (api *API) GetFavourites(ctx context.Context) ([]*Favourite, error) {
log.Debug("call to get favourites")
rst, err := api.s.db.GetFavourites()
log.Debug("result from database for favourites", "len", len(rst))
return rst, err
}
func (api *API) AddFavourite(ctx context.Context, favourite Favourite) error {
log.Debug("call to create or update favourites")
err := api.s.db.AddFavourite(favourite)
log.Debug("result from database for create or update favouritesn", "err", err)
return err
}