forked from go/golangs_learn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
237 lines
6.4 KiB
237 lines
6.4 KiB
package app
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"os"
|
|
"os/user"
|
|
|
|
"github.com/jinzhu/gorm"
|
|
"github.com/sirupsen/logrus"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/wailsapp/wails"
|
|
|
|
"github.com/grvlle/constellation_wallet/backend/api"
|
|
"github.com/grvlle/constellation_wallet/backend/models"
|
|
)
|
|
|
|
// WalletApplication holds all application specific objects
|
|
// such as the Client/Server event bus and logger
|
|
type WalletApplication struct {
|
|
Version string
|
|
RT *wails.Runtime
|
|
log *logrus.Logger
|
|
wallet models.Wallet
|
|
DB *gorm.DB
|
|
killSignal chan struct{}
|
|
Network struct {
|
|
URL string
|
|
Handles struct {
|
|
Send string // Takes TX Object, returns TX Hash (200)
|
|
Transaction string // Takes TX Object, returns TX Hash (200)
|
|
Balance string // Polls the wallets available balance
|
|
}
|
|
BlockExplorer struct {
|
|
URL string
|
|
Handles struct {
|
|
Transactions string // Takes TX Hash, returns TX info
|
|
Checkpoints string // Takes Checkpoint block hash, returns checkpoint block info
|
|
Snapshots string // Takes SnapshotHash, returns info
|
|
CollectTX string // Takes DAG address, returns tx objects
|
|
|
|
}
|
|
}
|
|
}
|
|
paths struct {
|
|
HomeDir string
|
|
DAGDir string
|
|
TMPDir string
|
|
EncryptedDir string
|
|
EmptyTXFile string
|
|
PrevTXFile string
|
|
LastTXFile string
|
|
AddressFile string
|
|
ImageDir string
|
|
Java string
|
|
}
|
|
KeyStoreAccess bool
|
|
TransactionFinished bool
|
|
TransactionFailed bool
|
|
UserLoggedIn bool
|
|
NewUser bool
|
|
WalletImported bool
|
|
FirstTX bool
|
|
SecondTX bool
|
|
WidgetRunning struct {
|
|
PassKeysToFrontend bool
|
|
DashboardWidgets bool
|
|
}
|
|
WalletCLI struct {
|
|
URL string
|
|
Version string
|
|
}
|
|
}
|
|
|
|
// WailsShutdown is called when the application is closed
|
|
func (a *WalletApplication) WailsShutdown() {
|
|
a.wallet = models.Wallet{}
|
|
close(a.killSignal) // Kills the Go Routines
|
|
a.DB.Close()
|
|
}
|
|
|
|
// WailsInit initializes the Client and Server side bindings
|
|
func (a *WalletApplication) WailsInit(runtime *wails.Runtime) error {
|
|
var err error
|
|
|
|
a.log = logrus.New()
|
|
err = a.initDirectoryStructure()
|
|
if err != nil {
|
|
a.log.Errorln("Unable to set up directory structure. Reason: ", err)
|
|
}
|
|
|
|
a.initLogger()
|
|
|
|
err = api.InitRPCServer()
|
|
if err != nil {
|
|
a.log.Panicf("Unable to initialize RPC Server. Reason: %v", err)
|
|
}
|
|
a.log.Infoln("RPC Server initialized.")
|
|
|
|
a.UserLoggedIn = false
|
|
a.NewUser = false
|
|
a.TransactionFinished = true
|
|
a.RT = runtime
|
|
a.killSignal = make(chan struct{}) // Used to kill go routines and hand back system resources
|
|
a.wallet.Currency = "USD" // Set default currency
|
|
a.WalletCLI.URL = "https://github.com/Constellation-Labs/constellation/releases/download"
|
|
a.WalletCLI.Version = "2.6.0"
|
|
a.Version = "1.2.0"
|
|
|
|
a.DB, err = gorm.Open("sqlite3", a.paths.DAGDir+"/store.db")
|
|
if err != nil {
|
|
a.log.Panicln("failed to connect database", err)
|
|
}
|
|
// Migrate the schema
|
|
a.DB.AutoMigrate(&models.Wallet{}, &models.TXHistory{}, &models.Path{})
|
|
a.detectJavaPath()
|
|
a.initMainnetConnection()
|
|
a.newReleaseAvailable()
|
|
|
|
return nil
|
|
}
|
|
|
|
// initLogger writes logs to STDOUT and a.paths.DAGDir/wallet.log
|
|
func (a *WalletApplication) initLogger() {
|
|
logFile, err := os.OpenFile(a.paths.DAGDir+"/wallet.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
|
|
if err != nil {
|
|
a.log.Fatal("Unable to create log file.")
|
|
}
|
|
mw := io.MultiWriter(os.Stdout, logFile)
|
|
a.log.SetOutput(mw)
|
|
a.log.SetFormatter(&log.TextFormatter{
|
|
ForceColors: true,
|
|
FullTimestamp: true,
|
|
})
|
|
}
|
|
|
|
// Initializes the Directory Structure and stores the paths to the WalletApplication struct.
|
|
func (a *WalletApplication) initDirectoryStructure() error {
|
|
|
|
user, err := user.Current()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
a.paths.HomeDir = user.HomeDir // Home directory of the user
|
|
a.paths.DAGDir = a.paths.HomeDir + "/.dag" // DAG directory for configuration files and wallet specific data
|
|
a.paths.TMPDir = a.paths.DAGDir + "/tmp"
|
|
a.paths.LastTXFile = a.paths.TMPDir + "/last_tx"
|
|
a.paths.PrevTXFile = a.paths.TMPDir + "/prev_tx"
|
|
a.paths.EmptyTXFile = a.paths.TMPDir + "/genesis_tx"
|
|
a.paths.ImageDir = "./frontend/src/assets/img/" // Image Folder
|
|
|
|
a.log.Info("DAG Directory: ", a.paths.DAGDir)
|
|
|
|
err = a.directoryCreator(a.paths.DAGDir, a.paths.TMPDir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// initMainnetConnection populates the WalletApplication struct with mainnet data
|
|
func (a *WalletApplication) initMainnetConnection() {
|
|
a.Network.URL = "http://lb.constellationnetwork.io:9000" // Temp
|
|
|
|
a.Network.Handles.Send = "/send"
|
|
a.Network.Handles.Transaction = "/transaction"
|
|
a.Network.Handles.Balance = "/address/"
|
|
|
|
a.Network.BlockExplorer.URL = "https://xju69fets2.execute-api.us-west-1.amazonaws.com/cl-block-explorer-mainnet"
|
|
a.Network.BlockExplorer.Handles.Transactions = "/transactions/"
|
|
a.Network.BlockExplorer.Handles.Checkpoints = "/checkpoints/"
|
|
a.Network.BlockExplorer.Handles.Snapshots = "/snapshots/"
|
|
a.Network.BlockExplorer.Handles.CollectTX = "/transactions?sender="
|
|
}
|
|
|
|
// APIError reported by the blockexplerer/loadbalancer are reported in the following format
|
|
// {"error": "Cannot find transactions for sender"}
|
|
type APIError struct {
|
|
Error string
|
|
}
|
|
|
|
// verifyAPIResponse takes API response converted to a byte array and checks if the API returned
|
|
// an error. If it did, it'll return the error message.
|
|
func (a *WalletApplication) verifyAPIResponse(r []byte) (bool, string) {
|
|
APIErr := APIError{}
|
|
if string(r[3:8]) == "error" {
|
|
err := json.Unmarshal(r, &APIErr)
|
|
if err != nil {
|
|
a.log.Errorln("Unable to parse API error. Reason: ", err)
|
|
}
|
|
return false, APIErr.Error
|
|
}
|
|
return true, ""
|
|
}
|
|
|
|
func (a *WalletApplication) sendSuccess(msg string) {
|
|
|
|
if len(msg) > 200 {
|
|
msg = string(msg[:200]) // Restrict error size for frontend
|
|
a.RT.Events.Emit("success", msg)
|
|
return
|
|
}
|
|
a.RT.Events.Emit("success", msg)
|
|
}
|
|
|
|
func (a *WalletApplication) sendWarning(msg string) {
|
|
|
|
if len(msg) > 200 {
|
|
msg = string(msg[:200]) // Restrict error size for frontend
|
|
a.RT.Events.Emit("warning", msg)
|
|
return
|
|
}
|
|
a.RT.Events.Emit("warning", msg)
|
|
}
|
|
|
|
func (a *WalletApplication) sendError(msg string, err error) {
|
|
|
|
var errStr string
|
|
|
|
if err != nil {
|
|
b := []byte(err.Error())
|
|
if len(b) > 80 {
|
|
errStr = string(b[:80]) // Restrict error size for frontend
|
|
} else if len(b) < 80 {
|
|
errStr = string(b)
|
|
} else {
|
|
errStr = ""
|
|
}
|
|
|
|
a.RT.Events.Emit("error_handling", msg, errStr+" ...")
|
|
} else {
|
|
a.RT.Events.Emit("error_handling", msg+" ...")
|
|
}
|
|
|
|
}
|
|
|