// Computes the total balance for a cipher.Address's coin.UxOuts func (self *Visor) balance(uxs coin.UxArray) wallet.Balance { prevTime := self.blockchain.Time() b := wallet.NewBalance(0, 0) for _, ux := range uxs { b = b.Add(wallet.NewBalance(ux.Body.Coins, ux.CoinHours(prevTime))) } return b }
// Computes the total balance for cipher.Addresses and their coin.UxOuts func (self *Visor) totalBalance(auxs coin.AddressUxOuts) wallet.Balance { prevTime := self.blockchain.Time() b := wallet.NewBalance(0, 0) for _, uxs := range auxs { for _, ux := range uxs { b = b.Add(wallet.NewBalance(ux.Body.Coins, ux.CoinHours(prevTime))) } } return b }
// Creates and broadcasts a transaction sending money from one of our wallets // to destination address. func walletSpendHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { //log.Printf("Spend1") if r.FormValue("id") == "" { Error400(w, "Missing wallet_id") return } walletId := wallet.WalletID(r.FormValue("id")) if walletId == "" { Error400(w, "Invalid Wallet Id") return } sdst := r.FormValue("dst") if sdst == "" { Error400(w, "Missing destination address \"dst\"") return } dst, err := cipher.DecodeBase58Address(sdst) if err != nil { //Error400(w, "Invalid destination address: %v", err) Error400(w, "Invalid destination address: %v", err.Error()) return } //set fee automatically for now /* sfee := r.FormValue("fee") fee, err := strconv.ParseUint(sfee, 10, 64) if err != nil { Error400(w, "Invalid \"fee\" value") return } */ //var fee uint64 = 0 scoins := r.FormValue("coins") //shours := r.FormValue("hours") coins, err := strconv.ParseUint(scoins, 10, 64) if err != nil { Error400(w, "Invalid \"coins\" value") return } var hours uint64 = 0 var fee uint64 = 0 //doesnt work/do anything right now //MOVE THIS INTO HERE ret := Spend(gateway.D, gateway.D.Visor, Wg, walletId, wallet.NewBalance(coins, hours), fee, dst) if ret.Error != "" { Error400(w, "Spend Failed: %s", ret.Error) } SendOr404(w, ret) } }
// Creates a Transaction spending coins and hours from our coins func CreateSpendingTransaction(wlt wallet.Wallet, unconfirmed *UnconfirmedTxnPool, unspent *coin.UnspentPool, headTime uint64, amt wallet.Balance, fee, burnFactor uint64, dest cipher.Address) (coin.Transaction, error) { txn := coin.Transaction{} auxs := unspent.AllForAddresses(wlt.GetAddresses()) // Subtract pending spends from available puxs := unconfirmed.SpendsForAddresses(unspent, wlt.GetAddressSet()) auxs = auxs.Sub(puxs) // Determine which unspents to spend spends, err := createSpends(headTime, auxs.Flatten(), amt, fee, burnFactor) if err != nil { return txn, err } // Add these unspents as tx inputs toSign := make([]cipher.SecKey, len(spends)) spending := wallet.Balance{0, 0} for i, au := range spends { entry, exists := wlt.GetEntry(au.Body.Address) if !exists { log.Panic("On second thought, the wallet entry does not exist") } txn.PushInput(au.Hash()) toSign[i] = entry.Secret spending.Coins += au.Body.Coins spending.Hours += au.CoinHours(headTime) } // Determine how much change we get back, if any _, changeHours, err := calculateBurnAndChange(spending.Hours, amt.Hours, fee, burnFactor) if err != nil { // This should not occur, else createSpends is broken return txn, err } change := wallet.NewBalance(spending.Coins-amt.Coins, changeHours) // TODO -- send change to a new address changeAddr := spends[0].Body.Address if change.Coins == 0 { if change.Hours > 0 { msg := ("Have enough coins, but not enough to send coin hours " + "change back. Would spend %d more hours than requested.") return txn, fmt.Errorf(msg, change.Hours) } } else { txn.PushOutput(changeAddr, change.Coins, change.Hours) } // Finalize the the transaction txn.PushOutput(dest, amt.Coins, amt.Hours) txn.SignInputs(toSign) txn.UpdateHeader() return txn, nil }
//DEPRECATE //deprecate dependency on wallet // Creates a Transaction spending coins and hours from our coins //MOVE SOMEWHERE ELSE //Move to wallet or move to ??? func CreateSpendingTransaction(wlt wallet.Wallet, unconfirmed *UnconfirmedTxnPool, unspent *coin.UnspentPool, headTime uint64, amt wallet.Balance, dest cipher.Address) (coin.Transaction, error) { txn := coin.Transaction{} auxs := unspent.AllForAddresses(wlt.GetAddresses()) // Subtract pending spends from available puxs := unconfirmed.SpendsForAddresses(unspent, wlt.GetAddressSet()) auxs = auxs.Sub(puxs) // Determine which unspents to spend spends, err := createSpends(headTime, auxs.Flatten(), amt) if err != nil { return txn, err } // Add these unspents as tx inputs toSign := make([]cipher.SecKey, len(spends)) spending := wallet.Balance{0, 0} for i, au := range spends { entry, exists := wlt.GetEntry(au.Body.Address) if !exists { log.Panic("On second thought, the wallet entry does not exist") } txn.PushInput(au.Hash()) toSign[i] = entry.Secret spending.Coins += au.Body.Coins spending.Hours += au.CoinHours(headTime) } //keep 1/4th of hours as change //send half to each address var changeHours uint64 = spending.Hours / 4 if amt.Coins == spending.Coins { txn.PushOutput(dest, amt.Coins, changeHours/2) txn.SignInputs(toSign) txn.UpdateHeader() return txn, nil } change := wallet.NewBalance(spending.Coins-amt.Coins, changeHours/2) // TODO -- send change to a new address changeAddr := spends[0].Body.Address //create transaction txn.PushOutput(changeAddr, change.Coins, change.Hours) txn.PushOutput(dest, amt.Coins, changeHours/2) txn.SignInputs(toSign) txn.UpdateHeader() return txn, nil }
// Creates and broadcasts a transaction sending money from one of our wallets // to destination address. func walletSpendHandler(gateway *daemon.Gateway) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { walletId := wallet.WalletID(r.FormValue("id")) if walletId == "" { Error400(w, "Missing wallet_id") return } sdst := r.FormValue("dst") if sdst == "" { Error400(w, "Missing destination address \"dst\"") return } dst, err := cipher.DecodeBase58Address(sdst) if err != nil { Error400(w, "Invalid destination address") return } sfee := r.FormValue("fee") fee, err := strconv.ParseUint(sfee, 10, 64) if err != nil { Error400(w, "Invalid \"fee\" value") return } scoins := r.FormValue("coins") shours := r.FormValue("hours") coins, err := strconv.ParseUint(scoins, 10, 64) if err != nil { Error400(w, "Invalid \"coins\" value") return } hours, err := strconv.ParseUint(shours, 10, 64) if err != nil { Error400(w, "Invalid \"hours\" value") return } SendOr404(w, gateway.Spend(walletId, wallet.NewBalance(coins, hours), fee, dst)) } }