github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/api/accounts.go (about) 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/bytom/account" 11 "github.com/bytom/bytom/blockchain/signers" 12 "github.com/bytom/bytom/common" 13 "github.com/bytom/bytom/consensus" 14 "github.com/bytom/bytom/crypto/ed25519/chainkd" 15 "github.com/bytom/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.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 }