derohe-miniblock-mod/cmd/dero-wallet-cli/easymenu_post_open.go

337 lines
11 KiB
Go
Raw Normal View History

// Copyright 2017-2021 DERO Project. All rights reserved.
// Use of this source code in any form is governed by RESEARCH license.
// license can be found in the LICENSE file.
// GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package main
import "io"
import "os"
import "fmt"
import "io/ioutil"
import "strings"
import "path/filepath"
import "encoding/hex"
import "github.com/chzyer/readline"
import "github.com/deroproject/derohe/globals"
import "github.com/deroproject/derohe/address"
//import "github.com/deroproject/derohe/walletapi"
import "github.com/deroproject/derohe/transaction"
// handle menu if a wallet is currently opened
func display_easymenu_post_open_command(l *readline.Instance) {
w := l.Stderr()
io.WriteString(w, "Menu:\n")
io.WriteString(w, "\t\033[1m1\033[0m\tDisplay account Address \n")
io.WriteString(w, "\t\033[1m2\033[0m\tDisplay Seed "+color_red+"(Please save seed in safe location)\n\033[0m")
io.WriteString(w, "\t\033[1m3\033[0m\tDisplay Keys (hex)\n")
if !is_registered(wallet) {
io.WriteString(w, "\t\033[1m4\033[0m\tAccount registration to blockchain (registration has no fee requirement and is precondition to use the account)\n")
io.WriteString(w, "\n")
io.WriteString(w, "\n")
} else { // hide some commands, if view only wallet
io.WriteString(w, "\n")
io.WriteString(w, "\t\033[1m5\033[0m\tTransfer (send DERO) To Another Wallet\n")
//io.WriteString(w, "\t\033[1m6\033[0m\tCreate Transaction in offline mode\n")
io.WriteString(w, "\n")
}
io.WriteString(w, "\t\033[1m7\033[0m\tChange wallet password\n")
io.WriteString(w, "\t\033[1m8\033[0m\tClose Wallet\n")
if is_registered(wallet) {
io.WriteString(w, "\t\033[1m12\033[0m\tTransfer all balance (send DERO) To Another Wallet\n")
io.WriteString(w, "\t\033[1m13\033[0m\tShow transaction history\n")
io.WriteString(w, "\t\033[1m14\033[0m\tRescan transaction history\n")
}
io.WriteString(w, "\n\t\033[1m9\033[0m\tExit menu and start prompt\n")
io.WriteString(w, "\t\033[1m0\033[0m\tExit Wallet\n")
}
// this handles all the commands if wallet in menu mode and a wallet is opened
func handle_easymenu_post_open_command(l *readline.Instance, line string) (processed bool) {
var err error
_ = err
line = strings.TrimSpace(line)
line_parts := strings.Fields(line)
processed = true
if len(line_parts) < 1 { // if no command return
return
}
command := ""
if len(line_parts) >= 1 {
command = strings.ToLower(line_parts[0])
}
offline_tx := false
_ = offline_tx
switch command {
case "1":
fmt.Fprintf(l.Stderr(), "Wallet address : "+color_green+"%s"+color_white+"\n", wallet.GetAddress())
if !is_registered(wallet) {
reg_tx := wallet.GetRegistrationTX()
fmt.Fprintf(l.Stderr(), "Registration TX : "+color_green+"%x"+color_white+"\n", reg_tx.Serialize())
}
PressAnyKey(l, wallet)
case "2": // give user his seed
if !ValidateCurrentPassword(l, wallet) {
globals.Logger.Warnf("Invalid password")
PressAnyKey(l, wallet)
break
}
display_seed(l, wallet) // seed should be given only to authenticated users
PressAnyKey(l, wallet)
case "3": // give user his keys in hex form
if !ValidateCurrentPassword(l, wallet) {
globals.Logger.Warnf("Invalid password")
PressAnyKey(l, wallet)
break
}
display_spend_key(l, wallet)
PressAnyKey(l, wallet)
case "4": // Registration
if !ValidateCurrentPassword(l, wallet) {
globals.Logger.Warnf("Invalid password")
PressAnyKey(l, wallet)
break
}
//if valid_registration_or_display_error(l, wallet) {
// globals.Logger.Warnf("This wallet address is already registered.")
// break
//}
fmt.Fprintf(l.Stderr(), "Wallet address : "+color_green+"%s"+color_white+" is going to be registered.This is a pre-condition for using the online chain.It will take few seconds to register/", wallet.GetAddress())
reg_tx := wallet.GetRegistrationTX()
if ConfirmYesNoDefaultNo(l, "Confirm Registration (y/N)") {
// at this point we must send the registration transaction
fmt.Fprintf(l.Stderr(), "Wallet address : "+color_green+"%s"+color_white+" is going to be registered.Pls wait till the account is registered.", wallet.GetAddress())
wallet.SendTransaction(reg_tx)
}
case "6":
offline_tx = true
fallthrough
case "5":
if !valid_registration_or_display_error(l, wallet) {
break
}
if !ValidateCurrentPassword(l, wallet) {
globals.Logger.Warnf("Invalid password")
break
}
// a , amount_to_transfer, err := collect_transfer_info(l,wallet)
a, err := ReadAddress(l)
if err != nil {
globals.Logger.Warnf("Err :%s", err)
break
}
amount_str := read_line_with_prompt(l, fmt.Sprintf("Enter amount to transfer in DERO (max TODO .00004 hard coded): "))
if amount_str == "" {
amount_str = ".00009"
}
amount_to_transfer, err := globals.ParseAmount(amount_str)
if err != nil {
globals.Logger.Warnf("Err :%s", err)
break // invalid amount provided, bail out
}
var payment_id []byte
_ = payment_id
// if user provided an integrated address donot ask him payment id
if a.IsIntegratedAddress() {
globals.Logger.Infof("Payment ID is integreted in address ID:%x", a.PaymentID)
}
if ConfirmYesNoDefaultNo(l, "Confirm Transaction (y/N)") {
addr_list := []address.Address{*a}
amount_list := []uint64{amount_to_transfer} // transfer 50 dero, 2 dero
fees_per_kb := uint64(0) // fees must be calculated by walletapi
tx, err := wallet.Transfer(addr_list, amount_list, 0, hex.EncodeToString(payment_id), fees_per_kb, 0, false)
if err != nil {
globals.Logger.Warnf("Error while building Transaction err %s\n", err)
break
}
build_relay_transaction(l, tx, err, offline_tx, amount_list)
}
case "12":
if !valid_registration_or_display_error(l, wallet) {
break
}
if !ValidateCurrentPassword(l, wallet) {
globals.Logger.Warnf("Invalid password")
break
}
// a , amount_to_transfer, err := collect_transfer_info(l,wallet)
fmt.Printf("dest address %s\n", "deroi1qxqqkmaz8nhv4q07w3cjyt84kmrqnuw4nprpqfl9xmmvtvwa7cdykxq5dph4ufnx5ndq4ltraf (14686f5e2666a4da) dero1qxqqkmaz8nhv4q07w3cjyt84kmrqnuw4nprpqfl9xmmvtvwa7cdykxqpfpaes")
a, err := ReadAddress(l)
if err != nil {
globals.Logger.Warnf("Err :%s", err)
break
}
// if user provided an integrated address donot ask him payment id
if a.IsIntegratedAddress() {
globals.Logger.Infof("Payment ID is integreted in address ID:%x", a.PaymentID)
}
if ConfirmYesNoDefaultNo(l, "Confirm Transaction to send entire balance (y/N)") {
addr_list := []address.Address{*a}
amount_list := []uint64{0} // transfer 50 dero, 2 dero
fees_per_kb := uint64(0) // fees must be calculated by walletapi
tx, err := wallet.Transfer(addr_list, amount_list, 0, "", fees_per_kb, 0, true)
if err != nil {
globals.Logger.Warnf("Error while building Transaction err %s\n", err)
break
}
build_relay_transaction(l, tx, err, offline_tx, amount_list)
}
//PressAnyKey(l, wallet) // wait for a key press
case "7": // change password
if ConfirmYesNoDefaultNo(l, "Change wallet password (y/N)") &&
ValidateCurrentPassword(l, wallet) {
new_password := ReadConfirmedPassword(l, "Enter new password", "Confirm password")
err = wallet.Set_Encrypted_Wallet_Password(new_password)
if err == nil {
globals.Logger.Infof("Wallet password successfully changed")
} else {
globals.Logger.Warnf("Wallet password could not be changed err %s", err)
}
}
case "8": // close and discard user key
wallet.Close_Encrypted_Wallet()
prompt_mutex.Lock()
wallet = nil // overwrite previous instance
prompt_mutex.Unlock()
fmt.Fprintf(l.Stderr(), color_yellow+"Wallet closed"+color_white)
case "9": // enable prompt mode
menu_mode = false
globals.Logger.Infof("Prompt mode enabled, type \"menu\" command to start menu mode")
case "0", "bye", "exit", "quit":
wallet.Close_Encrypted_Wallet() // save the wallet
prompt_mutex.Lock()
wallet = nil
globals.Exit_In_Progress = true
prompt_mutex.Unlock()
fmt.Fprintf(l.Stderr(), color_yellow+"Wallet closed"+color_white)
fmt.Fprintf(l.Stderr(), color_yellow+"Exiting"+color_white)
case "13":
show_transfers(l, wallet, 100)
case "14":
globals.Logger.Infof("Rescanning wallet history")
rescan_bc(wallet)
default:
processed = false // just loop
}
return
}
// handles the output after building tx, takes feedback, confirms or relays tx
func build_relay_transaction(l *readline.Instance, tx *transaction.Transaction, err error, offline_tx bool, amount_list []uint64) {
if err != nil {
globals.Logger.Warnf("Error while building Transaction err %s\n", err)
return
}
amount := uint64(0)
for i := range amount_list {
amount += amount_list[i]
}
globals.Logger.Infof("Transfering total amount %s DERO", globals.FormatMoney(amount))
globals.Logger.Infof("fees %s DERO", globals.FormatMoney(tx.Statement.Fees))
globals.Logger.Infof("TX Size %0.1f KiB", float32(len(tx.Serialize()))/1024.0)
//if input_sum != (amount + change + tx.Fee()) {
// panic(fmt.Sprintf("Inputs %d != outputs ( %d + %d + %d )", input_sum, amount, change, tx.RctSignature.Get_TX_Fee()))
//}
//if ConfirmYesNoDefaultNo(l, "Confirm Transaction (y/N)") {
if true {
if offline_tx { // if its an offline tx, dump it to a file
cur_dir, err := os.Getwd()
if err != nil {
globals.Logger.Warnf("Cannot obtain current directory to save tx")
globals.Logger.Infof("Transaction discarded")
return
}
filename := filepath.Join(cur_dir, tx.GetHash().String()+".tx")
err = ioutil.WriteFile(filename, []byte(hex.EncodeToString(tx.Serialize())), 0600)
if err == nil {
if err == nil {
globals.Logger.Infof("Transaction saved successfully. txid = %s", tx.GetHash())
globals.Logger.Infof("Saved to %s", filename)
} else {
globals.Logger.Warnf("Error saving tx to %s, err %s", filename, err)
}
}
} else {
err = wallet.SendTransaction(tx) // relay tx to daemon/network
if err == nil {
globals.Logger.Infof("Transaction sent successfully. txid = %s", tx.GetHash())
} else {
globals.Logger.Warnf("Transaction sending failed txid = %s, err %s", tx.GetHash(), err)
}
}
PressAnyKey(l, wallet) // wait for a key press
} else {
globals.Logger.Infof("Transaction discarded")
}
}