OSDN Git Service

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