// GetAddresses get all addresses in wallet. // mode: GET // url: /api/v1/wallet/addresses?id=[:id] // params: // id: wallet id. func GetAddresses(se Servicer) httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { var rlt *pp.EmptyRes for { id := r.FormValue("id") if id == "" { rlt = pp.MakeErrRes(errors.New("id is required")) break } addrs, err := wallet.GetAddresses(id) if err != nil { logger.Error(err.Error()) rlt = pp.MakeErrResWithCode(pp.ErrCode_WrongRequest) break } res := struct { Result *pp.Result `json:"result"` Addresses []string `json:"addresses"` }{ Result: pp.MakeResultWithCode(pp.ErrCode_Success), Addresses: addrs, } sendJSON(w, &res) return } sendJSON(w, rlt) } }
// PrepareTx prepares the transaction info func (cn coinEx) PrepareTx(params interface{}) ([]coin.TxIn, interface{}, error) { p := params.(sendParams) tp := strings.Split(p.WalletID, "_")[0] if tp != cn.Name { return nil, nil, fmt.Errorf("invalid wallet %v", tp) } // validate address if err := cn.ValidateAddr(p.ToAddr); err != nil { return nil, nil, err } addrs, err := wallet.GetAddresses(p.WalletID) if err != nil { return nil, nil, err } // outMap := make(map[string][]*pp.SkyUtxo) totalUtxos, err := cn.getOutputs(addrs) if err != nil { return nil, nil, err } utxos, err := cn.getSufficientOutputs(totalUtxos, p.Amount) if err != nil { return nil, nil, err } bal, hours := func(utxos []*pp.SkyUtxo) (uint64, uint64) { var c, h uint64 for _, u := range utxos { c += u.GetCoins() h += u.GetHours() } return c, h }(utxos) txIns := make([]coin.TxIn, len(utxos)) for i, u := range utxos { txIns[i] = coin.TxIn{ Txid: u.GetHash(), Address: u.GetAddress(), } } var txOut []skycoin.TxOut chgAmt := bal - p.Amount chgHours := hours / 4 chgAddr := addrs[0] if chgAmt > 0 { txOut = append(txOut, cn.makeTxOut(p.ToAddr, p.Amount, chgHours/2), cn.makeTxOut(chgAddr, chgAmt, chgHours/2)) } else { txOut = append(txOut, cn.makeTxOut(p.ToAddr, p.Amount, chgHours/2)) } return txIns, txOut, nil }
func (bn bitcoinCli) PrepareTx(params interface{}) ([]coin.TxIn, interface{}, error) { p := params.(btcSendParams) tp := strings.Split(p.WalletID, "_")[0] if tp != "bitcoin" { return nil, nil, fmt.Errorf("invalid wallet %v", tp) } // valid address if err := bn.ValidateAddr(p.ToAddr); err != nil { return nil, nil, err } addrs, err := wallet.GetAddresses(p.WalletID) if err != nil { return nil, nil, err } totalUtxos, err := bn.getOutputs(addrs) if err != nil { return nil, nil, err } utxos, bal, err := bn.getSufficientOutputs(totalUtxos, p.Amount+p.Fee) if err != nil { return nil, nil, err } txIns := make([]coin.TxIn, len(utxos)) for i, u := range utxos { txIns[i] = coin.TxIn{ Txid: u.GetTxid(), Vout: u.GetVout(), Address: u.GetAddress(), } } var txOut []bitcoin.TxOut chgAmt := bal - p.Amount - p.Fee chgAddr := addrs[0] if chgAmt > 0 { txOut = append(txOut, bn.makeTxOut(p.ToAddr, p.Amount), bn.makeTxOut(chgAddr, chgAmt)) } else { txOut = append(txOut, bn.makeTxOut(p.ToAddr, p.Amount)) } return txIns, txOut, nil }
// GetWalletBalance get local wallet balance. // mode: GET // url: /api/v1/wallet/balance?id=[:id] // params: // id: wallet id. func GetWalletBalance(se Servicer) httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { var rlt *pp.EmptyRes for { id := r.FormValue("id") if id == "" { err := errors.New("id is empty") logger.Error(err.Error()) rlt = pp.MakeErrRes(err) break } // get addresses in wallet. addrs, err := wallet.GetAddresses(id) if err != nil { logger.Error(err.Error()) rlt = pp.MakeErrRes(err) break } if len(addrs) == 0 { res := pp.GetAddrBalanceRes{ Result: pp.MakeResult(pp.ErrCode_NotExits, "wallet have no address"), } sendJSON(w, &res) return } cp := strings.Split(id, "_")[0] // get address balance. req := pp.GetAddrBalanceReq{ CoinType: pp.PtrString(cp), Addrs: pp.PtrString(strings.Join(addrs, ",")), } var res pp.GetAddrBalanceRes if err := sknet.EncryGet(se.GetServAddr(), "/get/address/balance", req, &res); err != nil { logger.Error(err.Error()) rlt = pp.MakeErrResWithCode(pp.ErrCode_ServerError) break } sendJSON(w, res) return } sendJSON(w, rlt) } }
// GetAddresses get all addresses in one specific wallet. func (wlts wallets) GetAddresses(cp string) ([]string, error) { if id, ok := wlts.ids[cp]; ok { return wallet.GetAddresses(id) } return []string{}, fmt.Errorf("%s wallet not supported", cp) }
func TestGetAddresses(t *testing.T) { _, teardown, err := setup(t) assert.Nil(t, err) defer teardown() testData := []struct { Type coin.Type Seed string Num int Entries []coin.AddressEntry }{ { Type: coin.Bitcoin, Seed: "sd999", Num: 2, Entries: []coin.AddressEntry{ { Address: "1FLZTRDS51eiMGu1MwV75VmQPags7UjysZ", Public: "0378c76e20e4f93730e67bb469bc7186681a8c85023088b64c70930e78d4aff690", Secret: "L4fDKYKxMSoZ3EUfKHacykA5cM8h6EXeqQ1w2TrpeQ7f81cR5EhT", }, { Address: "1HsUndbHFjRMSXuGyxo1kzVMsQcuhpJcwE", Public: "0270d2d9b6df46e1b22effee8a3dfb42f6c3fe69b4361158b6101b451f6cced51c", Secret: "Kz9vEMVPXTzTEXFrP4Pmnv79UfPRr2HWgZoQt4VAWzbUauF2MrNf", }, }, }, { Type: coin.Skycoin, Seed: "sd888", Num: 2, Entries: []coin.AddressEntry{ { Address: "fYJPkCTqdChw3sPSGUgze9nuGMNtC5DvPY", Public: "02ba572a03c8471822c308e5d041aba549b35676a0ef1c737b4517eef70c32377e", Secret: "2f4aacc72a6d192e04ec540328689588caf4167d71904bdb870a4a2cee7f29c8", }, { Address: "t6t7bJ9Ruxq9z44pYQT5AkEeAjGjgantU", Public: "039f4b6a110a9c5c38da08a0bff133edf07472348a4dc4c9d63b178fe26807606e", Secret: "b720d3c0f67f3c91e23805237f182e78121b90890f483133cc46f9d91232cf4c", }, }, }, } for _, d := range testData { // new wallet wlt, err := wallet.New(d.Type, d.Seed) if err != nil { t.Fatal(err) } if _, err := wallet.NewAddresses(wlt.GetID(), d.Num); err != nil { t.Fatal(err) } addrs, err := wallet.GetAddresses(wlt.GetID()) if err != nil { t.Fatal(err) } for _, e := range d.Entries { find := func(addr string) bool { for _, a := range addrs { if a == addr { return true } } return false } if !find(e.Address) { t.Fatal("GetAddresses failed") } } } }