OSDN Git Service

new repo
[bytom/vapor.git] / api / accounts.go
1 package api
2
3 import (
4         "context"
5         "encoding/hex"
6         "sort"
7
8         log "github.com/sirupsen/logrus"
9
10         "github.com/vapor/account"
11         "github.com/vapor/blockchain/signers"
12         "github.com/vapor/common"
13         "github.com/vapor/consensus"
14         "github.com/vapor/crypto/ed25519/chainkd"
15         "github.com/vapor/protocol/vm/vmutil"
16 )
17
18 // POST /create-account
19 func (a *API) createAccount(ctx context.Context, ins struct {
20         RootXPubs []chainkd.XPub `json:"root_xpubs"`
21         Quorum    int            `json:"quorum"`
22         Alias     string         `json:"alias"`
23 }) Response {
24         acc, err := a.wallet.AccountMgr.Create(ins.RootXPubs, ins.Quorum, ins.Alias, signers.BIP0044)
25         if err != nil {
26                 return NewErrorResponse(err)
27         }
28
29         annotatedAccount := account.Annotated(acc)
30         log.WithField("account ID", annotatedAccount.ID).Info("Created account")
31
32         return NewSuccessResponse(annotatedAccount)
33 }
34
35 // POST update-account-alias
36 func (a *API) updateAccountAlias(ctx context.Context, ins struct {
37         AccountID    string `json:"account_id"`
38         AccountAlias string `json:"account_alias"`
39         NewAlias     string `json:"new_alias"`
40 }) Response {
41         accountID := ins.AccountID
42         if ins.AccountAlias != "" {
43                 foundAccount, err := a.wallet.AccountMgr.FindByAlias(ins.AccountAlias)
44                 if err != nil {
45                         return NewErrorResponse(err)
46                 }
47                 accountID = foundAccount.ID
48         }
49         if err := a.wallet.UpdateAccountAlias(accountID, ins.NewAlias); err != nil {
50                 return NewErrorResponse(err)
51         }
52         return NewSuccessResponse(nil)
53 }
54
55 // AccountInfo is request struct for deleteAccount
56 type AccountInfo struct {
57         Info string `json:"account_info"`
58 }
59
60 // POST /delete-account
61 func (a *API) deleteAccount(ctx context.Context, filter struct {
62         AccountID    string `json:"account_id"`
63         AccountAlias string `json:"account_alias"`
64 }) Response {
65         accountID := filter.AccountID
66         if filter.AccountAlias != "" {
67                 acc, err := a.wallet.AccountMgr.FindByAlias(filter.AccountAlias)
68                 if err != nil {
69                         return NewErrorResponse(err)
70                 }
71                 accountID = acc.ID
72         }
73         if err := a.wallet.DeleteAccount(accountID); err != nil {
74                 return NewErrorResponse(err)
75         }
76
77         return NewSuccessResponse(nil)
78 }
79
80 type validateAddressResp struct {
81         Valid   bool `json:"valid"`
82         IsLocal bool `json:"is_local"`
83 }
84
85 // POST /validate-address
86 func (a *API) validateAddress(ctx context.Context, ins struct {
87         Address string `json:"address"`
88 }) Response {
89         resp := &validateAddressResp{
90                 Valid:   false,
91                 IsLocal: false,
92         }
93         address, err := common.DecodeAddress(ins.Address, &consensus.ActiveNetParams)
94         if err != nil {
95                 return NewSuccessResponse(resp)
96         }
97
98         redeemContract := address.ScriptAddress()
99         program := []byte{}
100         switch address.(type) {
101         case *common.AddressWitnessPubKeyHash:
102                 program, err = vmutil.P2WPKHProgram(redeemContract)
103         case *common.AddressWitnessScriptHash:
104                 program, err = vmutil.P2WSHProgram(redeemContract)
105         default:
106                 return NewSuccessResponse(resp)
107         }
108         if err != nil {
109                 return NewSuccessResponse(resp)
110         }
111
112         resp.Valid = true
113         resp.IsLocal = a.wallet.AccountMgr.IsLocalControlProgram(program)
114         return NewSuccessResponse(resp)
115 }
116
117 type addressResp struct {
118         AccountAlias   string `json:"account_alias"`
119         AccountID      string `json:"account_id"`
120         Address        string `json:"address"`
121         ControlProgram string `json:"control_program"`
122         Change         bool   `json:"change"`
123         KeyIndex       uint64 `json:"key_index"`
124 }
125
126 // SortByIndex implements sort.Interface for addressResp slices
127 type SortByIndex []addressResp
128
129 func (a SortByIndex) Len() int           { return len(a) }
130 func (a SortByIndex) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
131 func (a SortByIndex) Less(i, j int) bool { return a[i].KeyIndex < a[j].KeyIndex }
132
133 func (a *API) listAddresses(ctx context.Context, ins struct {
134         AccountID    string `json:"account_id"`
135         AccountAlias string `json:"account_alias"`
136         From         uint   `json:"from"`
137         Count        uint   `json:"count"`
138 }) Response {
139         accountID := ins.AccountID
140         var target *account.Account
141         if ins.AccountAlias != "" {
142                 acc, err := a.wallet.AccountMgr.FindByAlias(ins.AccountAlias)
143                 if err != nil {
144                         return NewErrorResponse(err)
145                 }
146                 target = acc
147         } else {
148                 acc, err := a.wallet.AccountMgr.FindByID(accountID)
149                 if err != nil {
150                         return NewErrorResponse(err)
151                 }
152                 target = acc
153         }
154
155         cps, err := a.wallet.AccountMgr.ListControlProgram()
156         if err != nil {
157                 return NewErrorResponse(err)
158         }
159
160         addresses := []addressResp{}
161         for _, cp := range cps {
162                 if cp.Address == "" || cp.AccountID != target.ID {
163                         continue
164                 }
165                 addresses = append(addresses, addressResp{
166                         AccountAlias:   target.Alias,
167                         AccountID:      cp.AccountID,
168                         Address:        cp.Address,
169                         ControlProgram: hex.EncodeToString(cp.ControlProgram),
170                         Change:         cp.Change,
171                         KeyIndex:       cp.KeyIndex,
172                 })
173         }
174
175         // sort AddressResp by KeyIndex
176         sort.Sort(SortByIndex(addresses))
177         start, end := getPageRange(len(addresses), ins.From, ins.Count)
178         return NewSuccessResponse(addresses[start:end])
179 }
180
181 type minigAddressResp struct {
182         MiningAddress string `json:"mining_address"`
183 }
184
185 func (a *API) getMiningAddress(ctx context.Context) Response {
186         miningAddress, err := a.wallet.AccountMgr.GetMiningAddress()
187         if err != nil {
188                 return NewErrorResponse(err)
189         }
190         return NewSuccessResponse(minigAddressResp{
191                 MiningAddress: miningAddress,
192         })
193 }
194
195 // POST /set-mining-address
196 func (a *API) setMiningAddress(ctx context.Context, in struct {
197         MiningAddress string `json:"mining_address"`
198 }) Response {
199         miningAddress, err := a.wallet.AccountMgr.SetMiningAddress(in.MiningAddress)
200         if err != nil {
201                 return NewErrorResponse(err)
202         }
203         return NewSuccessResponse(minigAddressResp{
204                 MiningAddress: miningAddress,
205         })
206 }