8 log "github.com/sirupsen/logrus"
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"
18 type CreateAccountReq struct {
19 RootXPubs []chainkd.XPub `json:"root_xpubs"`
20 Quorum int `json:"quorum"`
21 Alias string `json:"alias"`
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)
28 return NewErrorResponse(err)
31 annotatedAccount := account.Annotated(acc)
32 log.WithField("account ID", annotatedAccount.ID).Info("Created account")
34 return NewSuccessResponse(annotatedAccount)
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"`
43 accountID := ins.AccountID
44 if ins.AccountAlias != "" {
45 foundAccount, err := a.wallet.AccountMgr.FindByAlias(ins.AccountAlias)
47 return NewErrorResponse(err)
49 accountID = foundAccount.ID
51 if err := a.wallet.UpdateAccountAlias(accountID, ins.NewAlias); err != nil {
52 return NewErrorResponse(err)
54 return NewSuccessResponse(nil)
57 // AccountInfo is request struct for deleteAccount
58 type AccountInfo struct {
59 Info string `json:"account_info"`
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)
68 return NewErrorResponse(err)
72 if err := a.wallet.DeleteAccount(accountID); err != nil {
73 return NewErrorResponse(err)
76 return NewSuccessResponse(nil)
79 type validateAddressResp struct {
80 Valid bool `json:"valid"`
81 IsLocal bool `json:"is_local"`
84 // POST /validate-address
85 func (a *API) validateAddress(ctx context.Context, ins struct {
86 Address string `json:"address"`
88 resp := &validateAddressResp{
92 address, err := common.DecodeAddress(ins.Address, &consensus.ActiveNetParams)
94 return NewSuccessResponse(resp)
97 redeemContract := address.ScriptAddress()
99 switch address.(type) {
100 case *common.AddressWitnessPubKeyHash:
101 program, err = vmutil.P2WPKHProgram(redeemContract)
102 case *common.AddressWitnessScriptHash:
103 program, err = vmutil.P2WSHProgram(redeemContract)
105 return NewSuccessResponse(resp)
108 return NewSuccessResponse(resp)
112 resp.IsLocal = a.wallet.AccountMgr.IsLocalControlProgram(program)
113 return NewSuccessResponse(resp)
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"`
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"`
132 // SortByIndex implements sort.Interface for addressResp slices
133 type SortByIndex []AddressResp
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 }
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)
145 return NewErrorResponse(err)
149 acc, err := a.wallet.AccountMgr.FindByID(accountID)
151 return NewErrorResponse(err)
156 cps, err := a.wallet.AccountMgr.ListControlProgram()
158 return NewErrorResponse(err)
161 addresses := []AddressResp{}
162 for _, cp := range cps {
163 if cp.Address == "" || cp.AccountID != target.ID {
166 addresses = append(addresses, AddressResp{
167 AccountAlias: target.Alias,
168 AccountID: cp.AccountID,
170 ControlProgram: hex.EncodeToString(cp.ControlProgram),
172 KeyIndex: cp.KeyIndex,
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])
182 type minigAddressResp struct {
183 MiningAddress string `json:"mining_address"`
186 func (a *API) getMiningAddress(ctx context.Context) Response {
187 miningAddress, err := a.wallet.AccountMgr.GetMiningAddress()
189 return NewErrorResponse(err)
191 return NewSuccessResponse(minigAddressResp{
192 MiningAddress: miningAddress,
196 // POST /set-mining-address
197 func (a *API) setMiningAddress(ctx context.Context, in struct {
198 MiningAddress string `json:"mining_address"`
200 miningAddress, err := a.wallet.AccountMgr.SetMiningAddress(in.MiningAddress)
202 return NewErrorResponse(err)
204 return NewSuccessResponse(minigAddressResp{
205 MiningAddress: miningAddress,