Skip to content
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.

Commit

Permalink
use bk if wallet file is corrupt & don't hang app if some wallets are…
Browse files Browse the repository at this point in the history
… not loading
  • Loading branch information
g45t345rt committed Sep 5, 2023
1 parent 29056fc commit ae0c9b7
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 39 deletions.
94 changes: 75 additions & 19 deletions pages/wallet_select/select_wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/g45t345rt/g45w/animation"
"github.com/g45t345rt/g45w/app_instance"
"github.com/g45t345rt/g45w/components"
"github.com/g45t345rt/g45w/containers/confirm_modal"
"github.com/g45t345rt/g45w/containers/notification_modals"
"github.com/g45t345rt/g45w/containers/password_modal"
"github.com/g45t345rt/g45w/lang"
Expand Down Expand Up @@ -116,18 +117,23 @@ func (p *PageSelectWallet) Leave() {
}

func (p *PageSelectWallet) Load() {
wallets := wallet_manager.Wallets
items := make([]WalletListItem, 0)
for _, wallet := range wallets {
for _, walletInfo := range wallet_manager.Wallets {
items = append(items,
NewWalletListItem(wallet),
NewWalletListItem(walletInfo),
)
}

sort.Slice(items, func(i, j int) bool {
return items[i].wallet.Timestamp < items[j].wallet.Timestamp
})

for addr, err := range wallet_manager.WalletsErr {
items = append(items,
NewWalletListItemErr(err, addr),
)
}

p.walletList.items = items
}

Expand Down Expand Up @@ -165,8 +171,27 @@ func (p *PageSelectWallet) Layout(gtx layout.Context, th *material.Theme) layout
} else {
for _, item := range p.walletList.items {
if item.Clickable.Clicked() {
p.currentWallet = item.wallet
password_modal.Instance.SetVisible(true)
if item.wallet != nil {
p.currentWallet = item.wallet
password_modal.Instance.SetVisible(true)
} else {
go func() {
yesChan := confirm_modal.Instance.Open(confirm_modal.ConfirmText{
Prompt: lang.Translate("Delete wallet?"),
})

for yes := range yesChan {
if yes {
err := wallet_manager.DeleteWallet(item.addr)
if err == nil {
notification_modals.ErrorInstance.SetText("Error", err.Error())
notification_modals.ErrorInstance.SetVisible(true, notification_modals.CLOSE_AFTER_DEFAULT)
p.Load()
}
}
}
}()
}
}
}

Expand Down Expand Up @@ -369,6 +394,8 @@ type WalletListItem struct {
wallet *wallet_manager.WalletInfo
Clickable *widget.Clickable
rounded unit.Dp
err error
addr string
}

func NewWalletListItem(wallet *wallet_manager.WalletInfo) WalletListItem {
Expand All @@ -379,25 +406,54 @@ func NewWalletListItem(wallet *wallet_manager.WalletInfo) WalletListItem {
}
}

func NewWalletListItemErr(err error, addr string) WalletListItem {
return WalletListItem{
Clickable: &widget.Clickable{},
rounded: unit.Dp(12),
err: err,
addr: addr,
}
}

func (item *WalletListItem) Layout(gtx layout.Context, th *material.Theme) layout.Dimensions {
return item.Clickable.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
dims := layout.UniformInset(item.rounded).Layout(gtx, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Alignment: layout.Start}.Layout(gtx,
layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
name := fmt.Sprintf("%s [%s]", lang.Translate("Wallet"), item.wallet.Name)
lbl := material.Label(th, unit.Sp(18), name)
lbl.Font.Weight = font.Bold
return lbl.Layout(gtx)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
addr := utils.ReduceAddr(item.wallet.Addr)
lbl := material.Label(th, unit.Sp(15), addr)
lbl.Color = theme.Current.TextMuteColor
return lbl.Layout(gtx)
}),
)
if item.err != nil {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
addr := utils.ReduceAddr(item.addr)
lbl := material.Label(th, unit.Sp(18), addr)
lbl.Font.Weight = font.Bold
return lbl.Layout(gtx)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
lbl := material.Label(th, unit.Sp(11), item.err.Error())
lbl.Color = theme.Current.TextMuteColor
return lbl.Layout(gtx)
}),
)
}

if item.wallet != nil {
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
name := fmt.Sprintf("%s [%s]", lang.Translate("Wallet"), item.wallet.Name)
lbl := material.Label(th, unit.Sp(18), name)
lbl.Font.Weight = font.Bold
return lbl.Layout(gtx)
}),
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
addr := utils.ReduceAddr(item.wallet.Addr)
lbl := material.Label(th, unit.Sp(15), addr)
lbl.Color = theme.Current.TextMuteColor
return lbl.Layout(gtx)
}),
)
}

return layout.Dimensions{}
}),
)
})
Expand Down
87 changes: 67 additions & 20 deletions wallet_manager/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"io"
"io/fs"
"math"
"math/rand"
Expand Down Expand Up @@ -44,46 +45,53 @@ type WalletInfo struct {
}

var Wallets map[string]*WalletInfo
var WalletsErr map[string]error
var OpenedWallet *Wallet

func Load() error {
walletsDir := settings.WalletsDir
Wallets = make(map[string]*WalletInfo)
WalletsErr = make(map[string]error)

err := os.MkdirAll(walletsDir, os.ModePerm)
if err != nil {
return err
}

return filepath.Walk(walletsDir, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}

filepath.Walk(walletsDir, func(path string, info fs.FileInfo, fileErr error) error {
if walletsDir == path {
return nil
}

if info.IsDir() {
addr := info.Name()

path := filepath.Join(walletsDir, addr, "info.json")
data, err := os.ReadFile(path)
_, err := globals.ParseValidateAddress(addr)
if err != nil {
return err
return nil
}

fileInfo := filepath.Join(walletsDir, addr, "info.json")
data, err := os.ReadFile(fileInfo)
if err != nil {
WalletsErr[addr] = err
return nil
}

walletInfo := &WalletInfo{}
err = json.Unmarshal(data, walletInfo)
if err != nil {
return err
WalletsErr[addr] = err
return nil
}

Wallets[walletInfo.Addr] = walletInfo
Wallets[addr] = walletInfo
}

return nil
})

return nil
}

func CloseOpenedWallet() {
Expand All @@ -98,18 +106,53 @@ func CloseOpenedWallet() {
}
}

func GetWallet(addr string) (*WalletInfo, error) {
for _, walletInfo := range Wallets {
if walletInfo.Addr == addr {
return walletInfo, nil
}
}

return nil, fmt.Errorf("wallet [%s] not found", addr)
}

func OpenWallet(addr string, password string) error {
info, ok := Wallets[addr]
if !ok {
return fmt.Errorf("wallet [%s] does not exists", addr)
walletInfo, err := GetWallet(addr)
if err != nil {
return err
}

walletsDir := settings.WalletsDir
walletPath := filepath.Join(walletsDir, addr, "wallet.db")

bkCopied := false
open_wallet:
memory, err := walletapi.Open_Encrypted_Wallet(walletPath, password)
if err != nil {
return err
if bkCopied {
return err
}

// maybe the wallet file is corrupt or does not exists
// we will try to use backup file and copy as last resort
walletBkPath := filepath.Join(walletsDir, addr, "wallet.db.bak")
bkFile, err := os.Open(walletBkPath)
if err != nil {
return err
}

walletFile, err := os.Create(walletPath)
if err != nil {
return err
}

_, err = io.Copy(walletFile, bkFile)
if err != nil {
return err
}

bkCopied = true
goto open_wallet
}

memory.SetNetwork(globals.IsMainnet())
Expand Down Expand Up @@ -148,7 +191,7 @@ func OpenWallet(addr string, password string) error {
}

wallet := &Wallet{
Info: info,
Info: walletInfo,
Memory: memory,
DB: db,
}
Expand Down Expand Up @@ -521,9 +564,13 @@ func (w *Wallet) CalculateTxFees(sizeInBytes uint64) (fees uint64) {

func StoreRegistrationTx(addr string, tx *transaction.Transaction) error {
txHex := hex.EncodeToString(tx.Serialize())
wallet := Wallets[addr]
wallet.RegistrationTxHex = txHex
return saveWalletInfo(addr, wallet)
walletInfo, err := GetWallet(addr)
if err != nil {
return err
}

walletInfo.RegistrationTxHex = txHex
return saveWalletInfo(addr, walletInfo)
}

func saveWallet(wallet *walletapi.Wallet_Memory, name string) error {
Expand Down Expand Up @@ -563,8 +610,8 @@ func saveWalletInfo(addr string, walletInfo *WalletInfo) error {
return err
}

path = filepath.Join(walletsDir, addr, "info.json")
err = os.WriteFile(path, data, fs.ModePerm)
infoPath := filepath.Join(walletsDir, addr, "info.json")
err = os.WriteFile(infoPath, data, fs.ModePerm)
if err != nil {
return err
}
Expand Down

0 comments on commit ae0c9b7

Please sign in to comment.