walletunlock.go raw

   1  package gui
   2  
   3  import (
   4  	"encoding/hex"
   5  	"encoding/json"
   6  	"fmt"
   7  	"io/ioutil"
   8  	"path/filepath"
   9  	"time"
  10  
  11  	"golang.org/x/exp/shiny/materialdesign/icons"
  12  	"lukechampine.com/blake3"
  13  
  14  	l "github.com/p9c/p9/pkg/gel/gio/layout"
  15  	"github.com/p9c/p9/pkg/gel/gio/text"
  16  
  17  	"github.com/p9c/p9/pkg/interrupt"
  18  
  19  	"github.com/p9c/p9/pkg/gel"
  20  	"github.com/p9c/p9/pkg/p9icons"
  21  )
  22  
  23  func (wg *WalletGUI) unlockWallet(pass string) {
  24  	D.Ln("entered password", pass)
  25  	// unlock wallet
  26  	// wg.cx.Config.Lock()
  27  	wg.cx.Config.WalletPass.Set(pass)
  28  	wg.cx.Config.WalletOff.F()
  29  	// wg.cx.Config.Unlock()
  30  	// load config into a fresh variable
  31  	// cfg := podcfgs.GetDefaultConfig()
  32  	var cfgFile []byte
  33  	var e error
  34  	if cfgFile, e = ioutil.ReadFile(wg.cx.Config.ConfigFile.V()); E.Chk(e) {
  35  		// this should not happen
  36  		// TODO: panic-type conditions - for gel should have a notification maybe?
  37  		panic("config file does not exist")
  38  	}
  39  	cfg := wg.cx.Config
  40  	D.Ln("loaded config")
  41  	if e = json.Unmarshal(cfgFile, &cfg); !E.Chk(e) {
  42  		D.Ln("unmarshaled config")
  43  		bhb := blake3.Sum256([]byte(pass))
  44  		bh := hex.EncodeToString(bhb[:])
  45  		I.Ln(pass, bh, cfg.WalletPass.V())
  46  		if cfg.WalletPass.V() == bh {
  47  			D.Ln("loading previously saved state")
  48  			filename := filepath.Join(wg.cx.Config.DataDir.V(), "state.json")
  49  			// if log.FileExists(filename) {
  50  			I.Ln("#### loading state data...")
  51  			if e = wg.State.Load(filename, wg.cx.Config.WalletPass.Bytes()); !E.Chk(e) {
  52  				D.Ln("#### loaded state data")
  53  			}
  54  			// it is as though it is loaded if it didn't exist
  55  			wg.stateLoaded.Store(true)
  56  			// the entered password matches the stored hash
  57  			wg.cx.Config.NodeOff.F()
  58  			wg.cx.Config.WalletOff.F()
  59  			wg.cx.Config.WalletPass.Set(pass)
  60  			if e = wg.cx.Config.WriteToFile(wg.cx.Config.ConfigFile.V()); E.Chk(e) {
  61  			}
  62  			wg.cx.Config.WalletPass.Set(pass)
  63  			wg.WalletWatcher = wg.Watcher()
  64  			// }
  65  			//
  66  			// qrText := fmt.Sprintf("parallelcoin:%s?amount=%s&message=%s",
  67  			// 	wg.State.currentReceivingAddress.Load().EncodeAddress(),
  68  			// 	wg.inputs["receiveAmount"].GetText(),
  69  			// 	wg.inputs["receiveMessage"].GetText(),
  70  			// )
  71  			// var qrc image.Image
  72  			// if qrc, e = qrcode.Encode(qrText, 0, qrcode.ECLevelL, 4); !E.Chk(e) {
  73  			// 	iop := paint.NewImageOp(qrc)
  74  			// 	wg.currentReceiveQRCode = &iop
  75  			// 	wg.currentReceiveQR = wg.ButtonLayout(wg.currentReceiveCopyClickable.SetClick(func() {
  76  			// 		D.Ln("clicked qr code copy clicker")
  77  			// 		if e := clipboard.WriteAll(qrText); E.Chk(e) {
  78  			// 		}
  79  			// 	})).
  80  			// 		// CornerRadius(0.5).
  81  			// 		// Corners(gel.NW | gel.SW | gel.NE).
  82  			// 		Background("white").
  83  			// 		Embed(
  84  			// 			wg.Inset(0.125,
  85  			// 				wg.Image().Src(*wg.currentReceiveQRCode).Scale(1).Fn,
  86  			// 			).Fn,
  87  			// 		).Fn
  88  			// 	// *wg.currentReceiveQRCode = iop
  89  			// }
  90  		}
  91  	} else {
  92  		D.Ln("failed to unlock the wallet")
  93  	}
  94  }
  95  
  96  func (wg *WalletGUI) getWalletUnlockAppWidget() (a *gel.App) {
  97  	a = wg.App(wg.Window.Width, wg.State.activePage, Break1).
  98  		SetMainDirection(l.Center + 1).
  99  		SetLogo(&p9icons.ParallelCoin).
 100  		SetAppTitleText("Parallelcoin Wallet")
 101  	wg.unlockPage = a
 102  	password := wg.cx.Config.WalletPass
 103  	exitButton := wg.WidgetPool.GetClickable()
 104  	unlockButton := wg.WidgetPool.GetClickable()
 105  	wg.unlockPassword = wg.Password(
 106  		"enter password", password, "DocText",
 107  		"DocBg", "PanelBg", func(pass string) {
 108  			I.Ln("wallet unlock initiated", pass)
 109  			wg.unlockWallet(pass)
 110  		},
 111  	)
 112  	// wg.unlockPage.SetThemeHook(
 113  	// 	func() {
 114  	// 		D.Ln("theme hook")
 115  	// 		// D.Ln(wg.bools)
 116  	// 		wg.cx.Config.DarkTheme.Set(*wg.Dark)
 117  	// 		b := wg.configs["config"]["DarkTheme"].Slot.(*bool)
 118  	// 		*b = *wg.Dark
 119  	// 		if wgb, ok := wg.config.Bools["DarkTheme"]; ok {
 120  	// 			wgb.Value(*wg.Dark)
 121  	// 		}
 122  	// 		var e error
 123  	// 		if e = wg.cx.Config.WriteToFile(wg.cx.Config.ConfigFile.V()); E.Chk(e) {
 124  	// 		}
 125  	// 	},
 126  	// )
 127  	a.Pages(
 128  		map[string]l.Widget{
 129  			"home": wg.Page(
 130  				"home", gel.Widgets{
 131  					gel.WidgetSize{
 132  						Widget:
 133  						func(gtx l.Context) l.Dimensions {
 134  							var dims l.Dimensions
 135  							return wg.Flex().
 136  								AlignMiddle().
 137  								Flexed(
 138  									1,
 139  									wg.VFlex().
 140  										Flexed(0.5, gel.EmptyMaxHeight()).
 141  										Rigid(
 142  											wg.Flex().
 143  												SpaceEvenly().
 144  												AlignMiddle().
 145  												Rigid(
 146  													wg.Fill(
 147  														"DocBg", l.Center, wg.TextSize.V, 0,
 148  														wg.Inset(
 149  															0.5,
 150  															wg.Flex().
 151  																AlignMiddle().
 152  																Rigid(
 153  																	wg.VFlex().
 154  																		AlignMiddle().
 155  																		Rigid(
 156  																			func(gtx l.Context) l.Dimensions {
 157  																				dims = wg.Flex().
 158  																					AlignBaseline().
 159  																					Rigid(
 160  																						wg.Fill(
 161  																							"Fatal",
 162  																							l.Center,
 163  																							wg.TextSize.V/2,
 164  																							0,
 165  																							wg.Inset(
 166  																								0.5,
 167  																								wg.Icon().
 168  																									Scale(gel.Scales["H3"]).
 169  																									Color("DocBg").
 170  																									Src(&icons.ActionLock).Fn,
 171  																							).Fn,
 172  																						).Fn,
 173  																					).
 174  																					Rigid(
 175  																						wg.Inset(
 176  																							0.5,
 177  																							gel.EmptySpace(0, 0),
 178  																						).Fn,
 179  																					).
 180  																					Rigid(
 181  																						wg.H2("locked").Color("DocText").Fn,
 182  																					).
 183  																					Fn(gtx)
 184  																				return dims
 185  																			},
 186  																		).
 187  																		Rigid(wg.Inset(0.5, gel.EmptySpace(0, 0)).Fn).
 188  																		Rigid(
 189  																			func(gtx l.Context) l.
 190  																			Dimensions {
 191  																				gtx.Constraints.Max.
 192  																					X = dims.Size.X
 193  																				return wg.
 194  																					unlockPassword.
 195  																					Fn(gtx)
 196  																			},
 197  																		).
 198  																		Rigid(wg.Inset(0.5, gel.EmptySpace(0, 0)).Fn).
 199  																		Rigid(
 200  																			wg.Body1(
 201  																				fmt.Sprintf(
 202  																					"%v idle timeout",
 203  																					time.Duration(wg.incdecs["idleTimeout"].GetCurrent())*time.Second,
 204  																				),
 205  																			).
 206  																				Color("DocText").
 207  																				Font("bariol bold").
 208  																				Fn,
 209  																		).
 210  																		Rigid(
 211  																			wg.Flex().
 212  																				Rigid(
 213  																					wg.Body1("Idle timeout in seconds:").Color(
 214  																						"DocText",
 215  																					).Fn,
 216  																				).
 217  																				Rigid(
 218  																					wg.incdecs["idleTimeout"].
 219  																						Color("DocText").
 220  																						Background("DocBg").
 221  																						Scale(gel.Scales["Caption"]).
 222  																						Fn,
 223  																				).
 224  																				Fn,
 225  																		).
 226  																		Rigid(
 227  																			wg.Flex().
 228  																				Rigid(
 229  																					wg.Inset(
 230  																						0.25,
 231  																						wg.ButtonLayout(
 232  																							exitButton.SetClick(
 233  																								func() {
 234  																									interrupt.Request()
 235  																								},
 236  																							),
 237  																						).
 238  																							CornerRadius(0.5).
 239  																							Corners(0).
 240  																							Background("PanelBg").
 241  																							Embed(
 242  																								// wg.Fill("DocText",
 243  																								wg.Inset(
 244  																									0.25,
 245  																									wg.Flex().AlignMiddle().
 246  																										Rigid(
 247  																											wg.Icon().
 248  																												Scale(
 249  																													gel.Scales["H4"],
 250  																												).
 251  																												Color("DocText").
 252  																												Src(
 253  																													&icons.
 254  																														MapsDirectionsRun,
 255  																												).Fn,
 256  																										).
 257  																										Rigid(
 258  																											wg.Inset(
 259  																												0.5,
 260  																												gel.EmptySpace(
 261  																													0,
 262  																													0,
 263  																												),
 264  																											).Fn,
 265  																										).
 266  																										Rigid(
 267  																											wg.H6("exit").Color("DocText").Fn,
 268  																										).
 269  																										Rigid(
 270  																											wg.Inset(
 271  																												0.5,
 272  																												gel.EmptySpace(
 273  																													0,
 274  																													0,
 275  																												),
 276  																											).Fn,
 277  																										).
 278  																										Fn,
 279  																								).Fn,
 280  																								// l.Center,
 281  																								// wg.TextSize.True/2).Fn,
 282  																							).Fn,
 283  																					).Fn,
 284  																				).
 285  																				Rigid(
 286  																					wg.Inset(
 287  																						0.25,
 288  																						wg.ButtonLayout(
 289  																							unlockButton.SetClick(
 290  																								func() {
 291  																									// pass := wg.unlockPassword.Editor().Text()
 292  																									pass := wg.unlockPassword.GetPassword()
 293  																									D.Ln(
 294  																										">>>>>>>>>>> unlock password",
 295  																										pass,
 296  																									)
 297  																									wg.unlockWallet(pass)
 298  
 299  																								},
 300  																							),
 301  																						).Background("Primary").
 302  																							CornerRadius(0.5).
 303  																							Corners(0).
 304  																							Embed(
 305  																								wg.Inset(
 306  																									0.25,
 307  																									wg.Flex().AlignMiddle().
 308  																										Rigid(
 309  																											wg.Icon().
 310  																												Scale(gel.Scales["H4"]).
 311  																												Color("Light").
 312  																												Src(&icons.ActionLockOpen).Fn,
 313  																										).
 314  																										Rigid(
 315  																											wg.Inset(
 316  																												0.5,
 317  																												gel.EmptySpace(
 318  																													0,
 319  																													0,
 320  																												),
 321  																											).Fn,
 322  																										).
 323  																										Rigid(
 324  																											wg.H6("unlock").Color("Light").Fn,
 325  																										).
 326  																										Rigid(
 327  																											wg.Inset(
 328  																												0.5,
 329  																												gel.EmptySpace(
 330  																													0,
 331  																													0,
 332  																												),
 333  																											).Fn,
 334  																										).
 335  																										Fn,
 336  																								).Fn,
 337  																							).Fn,
 338  																					).Fn,
 339  																				).
 340  																				Fn,
 341  																		).
 342  																		Fn,
 343  																).
 344  																Fn,
 345  														).Fn,
 346  													).Fn,
 347  												).
 348  												Fn,
 349  										).Flexed(0.5, gel.EmptyMaxHeight()).Fn,
 350  								).
 351  								Fn(gtx)
 352  						},
 353  					},
 354  				},
 355  			),
 356  			"settings": wg.Page(
 357  				"settings", gel.Widgets{
 358  					gel.WidgetSize{
 359  						Widget: func(gtx l.Context) l.Dimensions {
 360  							return wg.configs.Widget(wg.config)(gtx)
 361  						},
 362  					},
 363  				},
 364  			),
 365  			"console": wg.Page(
 366  				"console", gel.Widgets{
 367  					gel.WidgetSize{Widget: wg.console.Fn},
 368  				},
 369  			),
 370  			"help": wg.Page(
 371  				"help", gel.Widgets{
 372  					gel.WidgetSize{Widget: wg.HelpPage()},
 373  				},
 374  			),
 375  			"log": wg.Page(
 376  				"log", gel.Widgets{
 377  					gel.WidgetSize{Widget: a.Placeholder("log")},
 378  				},
 379  			),
 380  			"quit": wg.Page(
 381  				"quit", gel.Widgets{
 382  					gel.WidgetSize{
 383  						Widget: func(gtx l.Context) l.Dimensions {
 384  							return wg.VFlex().
 385  								SpaceEvenly().
 386  								AlignMiddle().
 387  								Rigid(
 388  									wg.H4("are you sure?").Color(wg.unlockPage.BodyColorGet()).Alignment(text.Middle).Fn,
 389  								).
 390  								Rigid(
 391  									wg.Flex().
 392  										// SpaceEvenly().
 393  										Flexed(0.5, gel.EmptyMaxWidth()).
 394  										Rigid(
 395  											wg.Button(
 396  												wg.clickables["quit"].SetClick(
 397  													func() {
 398  														wg.gracefulShutdown()
 399  														// close(wg.quit)
 400  													},
 401  												),
 402  											).Color("Light").TextScale(5).Text(
 403  												"yes!!!",
 404  											).Fn,
 405  										).
 406  										Flexed(0.5, gel.EmptyMaxWidth()).
 407  										Fn,
 408  								).
 409  								Fn(gtx)
 410  						},
 411  					},
 412  				},
 413  			),
 414  			// "goroutines": wg.Page(
 415  			// 	"log", p9.Widgets{
 416  			// 		// p9.WidgetSize{Widget: p9.EmptyMaxHeight()},
 417  			//
 418  			// 		p9.WidgetSize{
 419  			// 			Widget: func(gtx l.Context) l.Dimensions {
 420  			// 				le := func(gtx l.Context, index int) l.Dimensions {
 421  			// 					return wg.State.goroutines[index](gtx)
 422  			// 				}
 423  			// 				return func(gtx l.Context) l.Dimensions {
 424  			// 					return wg.ButtonInset(
 425  			// 						0.25,
 426  			// 						wg.Fill(
 427  			// 							"DocBg",
 428  			// 							wg.lists["recent"].
 429  			// 								Vertical().
 430  			// 								// Background("DocBg").Color("DocText").Active("Primary").
 431  			// 								Length(len(wg.State.goroutines)).
 432  			// 								ListElement(le).
 433  			// 								Fn,
 434  			// 						).Fn,
 435  			// 					).
 436  			// 						Fn(gtx)
 437  			// 				}(gtx)
 438  			// 				// wg.NodeRunCommandChan <- "stop"
 439  			// 				// consume.Kill(wg.Worker)
 440  			// 				// consume.Kill(wg.cx.StateCfg.Miner)
 441  			// 				// close(wg.cx.NodeKill)
 442  			// 				// close(wg.cx.KillAll)
 443  			// 				// time.Sleep(time.Second*3)
 444  			// 				// interrupt.Request()
 445  			// 				// os.Exit(0)
 446  			// 				// return l.Dimensions{}
 447  			// 			},
 448  			// 		},
 449  			// 	},
 450  			// ),
 451  			"mining": wg.Page(
 452  				"mining", gel.Widgets{
 453  					gel.WidgetSize{Widget: a.Placeholder("mining")},
 454  				},
 455  			),
 456  			"explorer": wg.Page(
 457  				"explorer", gel.Widgets{
 458  					gel.WidgetSize{Widget: a.Placeholder("explorer")},
 459  				},
 460  			),
 461  		},
 462  	)
 463  	// a.SideBar([]l.Widget{
 464  	// 	wg.SideBarButton("overview", "overview", 0),
 465  	// 	wg.SideBarButton("send", "send", 1),
 466  	// 	wg.SideBarButton("receive", "receive", 2),
 467  	// 	wg.SideBarButton("history", "history", 3),
 468  	// 	wg.SideBarButton("explorer", "explorer", 6),
 469  	// 	wg.SideBarButton("mining", "mining", 7),
 470  	// 	wg.SideBarButton("console", "console", 9),
 471  	// 	wg.SideBarButton("settings", "settings", 5),
 472  	// 	wg.SideBarButton("log", "log", 10),
 473  	// 	wg.SideBarButton("help", "help", 8),
 474  	// 	wg.SideBarButton("quit", "quit", 11),
 475  	// })
 476  	a.ButtonBar(
 477  		[]l.Widget{
 478  			// wg.PageTopBarButton(
 479  			// 	"goroutines", 0, &icons.ActionBugReport, func(name string) {
 480  			// 		wg.unlockPage.ActivePage(name)
 481  			// 	}, wg.unlockPage, "",
 482  			// ),
 483  			wg.PageTopBarButton(
 484  				"help", 1, &icons.ActionHelp, func(name string) {
 485  					wg.unlockPage.ActivePage(name)
 486  				}, wg.unlockPage, "",
 487  			),
 488  			wg.PageTopBarButton(
 489  				"home", 4, &icons.ActionLock, func(name string) {
 490  					wg.unlockPage.ActivePage(name)
 491  				}, wg.unlockPage, "Danger",
 492  			),
 493  			// wg.Flex().Rigid(wg.Inset(0.5, gel.EmptySpace(0, 0)).Fn).Fn,
 494  			// wg.PageTopBarButton(
 495  			// 	"quit", 3, &icons.ActionExitToApp, func(name string) {
 496  			// 		wg.unlockPage.ActivePage(name)
 497  			// 	}, wg.unlockPage, "",
 498  			// ),
 499  		},
 500  	)
 501  	a.StatusBar(
 502  		[]l.Widget{
 503  			// wg.Inset(0.5, gel.EmptySpace(0, 0)).Fn,
 504  			wg.RunStatusPanel,
 505  		},
 506  		[]l.Widget{
 507  			wg.StatusBarButton(
 508  				"console", 3, &p9icons.Terminal, func(name string) {
 509  					wg.MainApp.ActivePage(name)
 510  				}, a,
 511  			),
 512  			wg.StatusBarButton(
 513  				"log", 4, &icons.ActionList, func(name string) {
 514  					D.Ln("click on button", name)
 515  					wg.unlockPage.ActivePage(name)
 516  				}, wg.unlockPage,
 517  			),
 518  			wg.StatusBarButton(
 519  				"settings", 5, &icons.ActionSettings, func(name string) {
 520  					wg.unlockPage.ActivePage(name)
 521  				}, wg.unlockPage,
 522  			),
 523  			// wg.Inset(0.5, gel.EmptySpace(0, 0)).Fn,
 524  		},
 525  	)
 526  	// a.PushOverlay(wg.toasts.DrawToasts())
 527  	// a.PushOverlay(wg.dialog.DrawDialog())
 528  	return
 529  }
 530