OSDN Git Service

Merge pull request #375 from Bytom/dev
[bytom/bytom-spv.git] / blockchain / query.go
1 package blockchain
2
3 import (
4         "context"
5         "fmt"
6         "sort"
7
8         log "github.com/sirupsen/logrus"
9
10         "github.com/bytom/blockchain/account"
11         "github.com/bytom/blockchain/query"
12 )
13
14 // POST /list-accounts
15 func (bcr *BlockchainReactor) listAccounts(ctx context.Context, filter struct {
16         ID string `json:"id"`
17 }) Response {
18         accounts, err := bcr.accounts.ListAccounts(filter.ID)
19         if err != nil {
20                 log.Errorf("listAccounts: %v", err)
21                 return NewErrorResponse(err)
22         }
23
24         return NewSuccessResponse(accounts)
25 }
26
27 // POST /list-assets
28 func (bcr *BlockchainReactor) listAssets(ctx context.Context, filter struct {
29         ID string `json:"id"`
30 }) Response {
31         assets, err := bcr.assets.ListAssets(filter.ID)
32         if err != nil {
33                 log.Errorf("listAssets: %v", err)
34                 return NewErrorResponse(err)
35         }
36
37         return NewSuccessResponse(assets)
38 }
39
40 // POST /listBalances
41 func (bcr *BlockchainReactor) listBalances(ctx context.Context) Response {
42         accountUTXOs, err := bcr.wallet.GetAccountUTXOs("")
43         if err != nil {
44                 log.Errorf("GetAccountUTXOs: %v", err)
45                 return NewErrorResponse(err)
46         }
47
48         return NewSuccessResponse(bcr.indexBalances(accountUTXOs))
49 }
50
51 type accountBalance struct {
52         AccountID  string `json:"account_id"`
53         Alias      string `json:"account_alias"`
54         AssetAlias string `json:"asset_alias"`
55         AssetID    string `json:"asset_id"`
56         Amount     uint64 `json:"amount"`
57 }
58
59 func (bcr *BlockchainReactor) indexBalances(accountUTXOs []account.UTXO) []accountBalance {
60         accBalance := make(map[string]map[string]uint64)
61         balances := make([]accountBalance, 0)
62         tmpBalance := accountBalance{}
63
64         for _, accountUTXO := range accountUTXOs {
65
66                 assetID := accountUTXO.AssetID.String()
67                 if _, ok := accBalance[accountUTXO.AccountID]; ok {
68                         if _, ok := accBalance[accountUTXO.AccountID][assetID]; ok {
69                                 accBalance[accountUTXO.AccountID][assetID] += accountUTXO.Amount
70                         } else {
71                                 accBalance[accountUTXO.AccountID][assetID] = accountUTXO.Amount
72                         }
73                 } else {
74                         accBalance[accountUTXO.AccountID] = map[string]uint64{assetID: accountUTXO.Amount}
75                 }
76         }
77
78         sortedAccount := []string{}
79         for k := range accBalance {
80                 sortedAccount = append(sortedAccount, k)
81         }
82         sort.Strings(sortedAccount)
83
84         for _, id := range sortedAccount {
85                 sortedAsset := []string{}
86                 for k := range accBalance[id] {
87                         sortedAsset = append(sortedAsset, k)
88                 }
89                 sort.Strings(sortedAsset)
90
91                 for _, assetID := range sortedAsset {
92
93                         alias := bcr.accounts.GetAliasByID(id)
94                         assetAlias := bcr.assets.GetAliasByID(assetID)
95                         tmpBalance.Alias = alias
96                         tmpBalance.AccountID = id
97                         tmpBalance.AssetID = assetID
98                         tmpBalance.AssetAlias = assetAlias
99                         tmpBalance.Amount = accBalance[id][assetID]
100                         balances = append(balances, tmpBalance)
101                 }
102         }
103
104         return balances
105 }
106
107 // POST /list-transactions
108 func (bcr *BlockchainReactor) listTransactions(ctx context.Context, filter struct {
109         ID        string `json:"id"`
110         AccountID string `json:"account_id"`
111         Detail    bool   `json:"detail"`
112 }) Response {
113         var transactions []*query.AnnotatedTx
114         var err error
115
116         if filter.AccountID != "" {
117                 transactions, err = bcr.wallet.GetTransactionsByAccountID(filter.AccountID)
118         } else {
119                 transactions, err = bcr.wallet.GetTransactionsByTxID(filter.ID)
120         }
121
122         if err != nil {
123                 log.Errorf("listTransactions: %v", err)
124                 return NewErrorResponse(err)
125         }
126
127         if filter.Detail == false {
128                 txSummary := bcr.wallet.GetTransactionsSummary(transactions)
129                 return NewSuccessResponse(txSummary)
130         }
131         return NewSuccessResponse(transactions)
132 }
133
134 type annotatedUTXO struct {
135         Alias               string `json:"account_alias"`
136         OutputID            string `json:"id"`
137         AssetID             string `json:"asset_id"`
138         AssetAlias          string `json:"asset_alias"`
139         Amount              uint64 `json:"amount"`
140         AccountID           string `json:"account_id"`
141         Address             string `json:"address"`
142         ControlProgramIndex uint64 `json:"control_program_index"`
143         Program             string `json:"program"`
144         SourceID            string `json:"source_id"`
145         SourcePos           uint64 `json:"source_pos"`
146         RefDataHash         string `json:"ref_data"`
147         ValidHeight         uint64 `json:"valid_height"`
148 }
149
150 // POST /list-unspent-outputs
151 func (bcr *BlockchainReactor) listUnspentOutputs(ctx context.Context, filter struct {
152         ID string `json:"id"`
153 }) Response {
154         tmpUTXO := annotatedUTXO{}
155         UTXOs := make([]annotatedUTXO, 0)
156
157         accountUTXOs, err := bcr.wallet.GetAccountUTXOs(filter.ID)
158         if err != nil {
159                 log.Errorf("list Unspent Outputs: %v", err)
160                 return NewErrorResponse(err)
161         }
162
163         for _, utxo := range accountUTXOs {
164                 tmpUTXO.AccountID = utxo.AccountID
165                 tmpUTXO.OutputID = utxo.OutputID.String()
166                 tmpUTXO.SourceID = utxo.SourceID.String()
167                 tmpUTXO.AssetID = utxo.AssetID.String()
168                 tmpUTXO.Amount = utxo.Amount
169                 tmpUTXO.SourcePos = utxo.SourcePos
170                 tmpUTXO.Program = fmt.Sprintf("%x", utxo.ControlProgram)
171                 tmpUTXO.RefDataHash = utxo.RefDataHash.String()
172                 tmpUTXO.ControlProgramIndex = utxo.ControlProgramIndex
173                 tmpUTXO.Address = utxo.Address
174                 tmpUTXO.ValidHeight = utxo.ValidHeight
175
176                 tmpUTXO.Alias = bcr.accounts.GetAliasByID(utxo.AccountID)
177                 tmpUTXO.AssetAlias = bcr.assets.GetAliasByID(tmpUTXO.AssetID)
178
179                 UTXOs = append(UTXOs, tmpUTXO)
180         }
181
182         return NewSuccessResponse(UTXOs)
183 }