OSDN Git Service

d8e56618cc5448ad81841e63ce65268e306086ec
[bytom/bytom.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/account"
11         "github.com/bytom/blockchain/signers"
12         "github.com/bytom/common"
13         "github.com/bytom/consensus"
14         "github.com/bytom/crypto/ed25519/chainkd"
15         "github.com/bytom/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.AccountMgr.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, in AccountInfo) Response {
62         if err := a.wallet.AccountMgr.DeleteAccount(in.Info); err != nil {
63                 return NewErrorResponse(err)
64         }
65         return NewSuccessResponse(nil)
66 }
67
68 type validateAddressResp struct {
69         Valid   bool `json:"valid"`
70         IsLocal bool `json:"is_local"`
71 }
72
73 // POST /validate-address
74 func (a *API) validateAddress(ctx context.Context, ins struct {
75         Address string `json:"address"`
76 }) Response {
77         resp := &validateAddressResp{
78                 Valid:   false,
79                 IsLocal: false,
80         }
81         address, err := common.DecodeAddress(ins.Address, &consensus.ActiveNetParams)
82         if err != nil {
83                 return NewSuccessResponse(resp)
84         }
85
86         redeemContract := address.ScriptAddress()
87         program := []byte{}
88         switch address.(type) {
89         case *common.AddressWitnessPubKeyHash:
90                 program, err = vmutil.P2WPKHProgram(redeemContract)
91         case *common.AddressWitnessScriptHash:
92                 program, err = vmutil.P2WSHProgram(redeemContract)
93         default:
94                 return NewSuccessResponse(resp)
95         }
96         if err != nil {
97                 return NewSuccessResponse(resp)
98         }
99
100         resp.Valid = true
101         resp.IsLocal = a.wallet.AccountMgr.IsLocalControlProgram(program)
102         return NewSuccessResponse(resp)
103 }
104
105 type addressResp struct {
106         AccountAlias   string `json:"account_alias"`
107         AccountID      string `json:"account_id"`
108         Address        string `json:"address"`
109         ControlProgram string `json:"control_program"`
110         Change         bool   `json:"change"`
111         KeyIndex       uint64 `json:"key_index"`
112 }
113
114 // SortByIndex implements sort.Interface for addressResp slices
115 type SortByIndex []addressResp
116
117 func (a SortByIndex) Len() int           { return len(a) }
118 func (a SortByIndex) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
119 func (a SortByIndex) Less(i, j int) bool { return a[i].KeyIndex < a[j].KeyIndex }
120
121 func (a *API) listAddresses(ctx context.Context, ins struct {
122         AccountID    string `json:"account_id"`
123         AccountAlias string `json:"account_alias"`
124         From         uint   `json:"from"`
125         Count        uint   `json:"count"`
126 }) Response {
127         accountID := ins.AccountID
128         var target *account.Account
129         if ins.AccountAlias != "" {
130                 acc, err := a.wallet.AccountMgr.FindByAlias(ins.AccountAlias)
131                 if err != nil {
132                         return NewErrorResponse(err)
133                 }
134                 target = acc
135         } else {
136                 acc, err := a.wallet.AccountMgr.FindByID(accountID)
137                 if err != nil {
138                         return NewErrorResponse(err)
139                 }
140                 target = acc
141         }
142
143         cps, err := a.wallet.AccountMgr.ListControlProgram()
144         if err != nil {
145                 return NewErrorResponse(err)
146         }
147
148         addresses := []addressResp{}
149         for _, cp := range cps {
150                 if cp.Address == "" || cp.AccountID != target.ID {
151                         continue
152                 }
153                 addresses = append(addresses, addressResp{
154                         AccountAlias:   target.Alias,
155                         AccountID:      cp.AccountID,
156                         Address:        cp.Address,
157                         ControlProgram: hex.EncodeToString(cp.ControlProgram),
158                         Change:         cp.Change,
159                         KeyIndex:       cp.KeyIndex,
160                 })
161         }
162
163         // sort AddressResp by KeyIndex
164         sort.Sort(SortByIndex(addresses))
165         start, end := getPageRange(len(addresses), ins.From, ins.Count)
166         return NewSuccessResponse(addresses[start:end])
167 }
168
169 type minigAddressResp struct {
170         MiningAddress string `json:"mining_address"`
171 }
172
173 func (a *API) getMiningAddress(ctx context.Context) Response {
174         miningAddress, err := a.wallet.AccountMgr.GetMiningAddress()
175         if err != nil {
176                 return NewErrorResponse(err)
177         }
178         return NewSuccessResponse(minigAddressResp{
179                 MiningAddress: miningAddress,
180         })
181 }
182
183 // POST /set-mining-address
184 func (a *API) setMiningAddress(ctx context.Context, in struct {
185         MiningAddress string `json:"mining_address"`
186 }) Response {
187         miningAddress, err := a.wallet.AccountMgr.SetMiningAddress(in.MiningAddress)
188         if err != nil {
189                 return NewErrorResponse(err)
190         }
191         return NewSuccessResponse(minigAddressResp{
192                 MiningAddress: miningAddress,
193         })
194 }