Skip to content

Commit

Permalink
Merge pull request #147 from TrueBlocks/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
tjayrush authored Nov 3, 2024
2 parents 4cc34ae + 4dfb9fc commit 9b3330d
Show file tree
Hide file tree
Showing 323 changed files with 7,842 additions and 4,367 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
one
two
TODO.md
cache
unchained
*.csv
changed.toml
trueBlocks.toml
code_gen
build
backup_other
.DS_Store
Expand Down
17 changes: 0 additions & 17 deletions .vscode/launch.json

This file was deleted.

5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,8 @@
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.suggest.autoImports": true,
"javascript.suggest.autoImports": true,
"editor.acceptSuggestionOnEnter": "on"
"editor.acceptSuggestionOnEnter": "on",
"files.associations": {
"*.tbx": "json"
}
}
16 changes: 0 additions & 16 deletions .vscode/tasks.json

This file was deleted.

10 changes: 4 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Web 3.0 Account Browser built on TrueBlocks

## Installing

Clone the repo, then

```[bash]
go mod tidy
cd frontend && yarn install && cd -
Expand All @@ -12,15 +14,11 @@ cd frontend && yarn install && cd -
## Running

```[bash]
wails dev
yarn start
```

## Building

```[bash]
wails build
yarn build
```

## Api Keys

If you intend to use features that require OpenAI, rename the `.env.example` file to `.env` and add your OpenAI API key. The features will not work otherwise.
224 changes: 99 additions & 125 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,172 +5,146 @@ import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
"sync"

"github.com/TrueBlocks/trueblocks-browse/pkg/config"
"github.com/TrueBlocks/trueblocks-browse/pkg/daemons"
"github.com/TrueBlocks/trueblocks-browse/pkg/messages"
"github.com/TrueBlocks/trueblocks-browse/pkg/types"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/file"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/logger"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/names"
"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/output"
coreTypes "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types"
sdk "github.com/TrueBlocks/trueblocks-sdk/v3"
"github.com/joho/godotenv"
"github.com/wailsapp/wails/v2/pkg/runtime"
)

// Since we need App.ctx to display a dialog and we can only get it when Startup method
// is executed, we keep track of the first fatal error that has happened before Startup
var startupError error

// Find: NewViews
type App struct {
ctx context.Context

session config.Session
apiKeys map[string]string
renderCtxs map[base.Address][]*output.RenderCtx
meta coreTypes.MetaData
globals sdk.Globals

// Summaries
abis types.AbiContainer
index types.IndexContainer
manifest types.ManifestContainer
monitors types.MonitorContainer
names types.NameContainer
status types.StatusContainer
project types.ProjectContainer
ScraperController *daemons.DaemonScraper
FreshenController *daemons.DaemonFreshen
IpfsController *daemons.DaemonIpfs
}

// Find: NewViews
func NewApp() *App {
a := App{
apiKeys: make(map[string]string),
renderCtxs: make(map[base.Address][]*output.RenderCtx),
}
a.names.NamesMap = make(map[base.Address]coreTypes.Name)
a.project = types.NewProjectContainer("Untitled.tbx", &types.HistoryMap{}, &sync.Map{}, &sync.Map{})

// it's okay if it's not found
a.session.MustLoadSession()
a.globals = sdk.Globals{
Chain: a.session.Chain,
}

if err := godotenv.Load(); err != nil {
// a.Fatal("Error loading .env file")
logger.Info("Could not load .env file") // we don't need it for this app
// } else if a.apiKeys["openAi"] = os.Getenv("OPENAI_API_KEY"); a.apiKeys["openAi"] == "" {
// log.Fatal("No OPENAI_API_KEY key found")
}

// Initialize your data here

return &a
sdk.Globals

ctx context.Context
meta coreTypes.MetaData
dirty bool

// Containers
projects types.ProjectContainer
monitors types.MonitorContainer
names types.NameContainer
abis types.AbiContainer
indexes types.IndexContainer
manifests types.ManifestContainer
status types.StatusContainer
settings types.SettingsGroup
session types.SessionContainer
config types.ConfigContainer

// Memory caches
ensCache *sync.Map
balanceCache *sync.Map
namesMap map[base.Address]coreTypes.Name
historyCache *types.HistoryMap
renderCtxs map[base.Address][]*output.RenderCtx

// Controllers
scraperController *daemons.DaemonScraper
freshenController *daemons.DaemonFreshen
ipfsController *daemons.DaemonIpfs

// During initialization, we do things that may cause errors, but
// we have not yet opened the window, so we defer them until we can
// decide what to do.
deferredErrors []error
}

func (a *App) String() string {
bytes, _ := json.MarshalIndent(a, "", " ")
bytes, _ := json.Marshal(a)
return string(bytes)
}

func (a *App) GetContext() context.Context {
return a.ctx
func NewApp() *App {
a := &App{
ensCache: &sync.Map{},
balanceCache: &sync.Map{},
namesMap: make(map[base.Address]coreTypes.Name),
historyCache: &types.HistoryMap{},
renderCtxs: make(map[base.Address][]*output.RenderCtx),
}
a.freshenController = daemons.NewFreshen(a, "freshen", 3000, a.IsShowing("freshen"))
a.scraperController = daemons.NewScraper(a, "scraper", 7000, a.IsShowing("scraper"))
a.ipfsController = daemons.NewIpfs(a, "ipfs", 10000, a.IsShowing("ipfs"))
a.session.LastSub = make(map[string]string)

return a
}

// Find: NewViews
var ErrLoadingNames = errors.New("error loading names")
var ErrWindowSize = errors.New("error fixing window size")

func (a *App) Startup(ctx context.Context) {
a.ctx = ctx

if err := a.loadConfig(); err != nil {
messages.SendError(a.ctx, err)
// We do various setups prior to showing the window. Improves interactivity.
// But...something may fail, so we need to keep track of errors.
var err error
if err = a.session.Load(); err != nil {
a.deferredErrors = append(a.deferredErrors, err)
}

go a.loadHistory(a.GetLastAddress(), nil, nil)

a.FreshenController = daemons.NewFreshen(a, "freshen", 3000, a.GetSessionDeamon("daemon-freshen"))
a.ScraperController = daemons.NewScraper(a, "scraper", 7000, a.GetSessionDeamon("daemon-scraper"))
a.IpfsController = daemons.NewIpfs(a, "ipfs", 10000, a.GetSessionDeamon("daemon-ipfs"))
go a.startDaemons()
if startupError != nil {
a.Fatal(startupError.Error())
// Load the trueBlocks.toml file
if err = a.config.Load(); err != nil {
a.deferredErrors = append(a.deferredErrors, err)
}
if a.session.LastChain, err = a.config.IsValidChain(a.session.LastChain); err != nil {
a.deferredErrors = append(a.deferredErrors, err)
}
a.Chain = a.session.LastChain

logger.Info("Starting freshen process...")
a.Refresh(a.GetSession().LastRoute)
// We always need names, so let's load it before showing the window
if a.namesMap, err = names.LoadNamesMap(a.getChain(), coreTypes.All, nil); err == nil {
wErr := fmt.Errorf("%w: %v", ErrLoadingNames, err)
a.deferredErrors = append(a.deferredErrors, wErr)
}
}

// DomReady is called by Wails when the app is ready to go. Adjust the window size and show it.
func (a *App) DomReady(ctx context.Context) {
var err error

// We're ready to open the window, but first we need to make sure it will show...
if a.session.Window, err = a.session.CleanWindowSize(a.ctx); err != nil {
wErr := fmt.Errorf("%w: %v", ErrWindowSize, err)
a.deferredErrors = append(a.deferredErrors, wErr)
}
// DO NOT COLLAPSE - A VALID WINDOW IS RETURNED EVEN ON ERROR
runtime.WindowSetPosition(a.ctx, a.session.Window.X, a.session.Window.Y)
runtime.WindowSetSize(a.ctx, a.session.Window.Width, a.session.Window.Height)
runtime.WindowShow(a.ctx)
}

func (a *App) Shutdown(ctx context.Context) {
a.session.Window.X, a.session.Window.Y = runtime.WindowGetPosition(a.ctx)
a.session.Window.Width, a.session.Window.Height = runtime.WindowGetSize(a.ctx)
a.session.Window.Y += 38 // TODO: This is a hack to account for the menu bar - not sure why it's needed
a.session.Save()
}

func (a *App) GetSession() *config.Session {
if a.session.LastSub == nil {
a.session.LastSub = make(map[string]string)
if err != nil {
a.deferredErrors = append(a.deferredErrors, err)
}
return &a.session
}

func (a *App) Fatal(message string) {
if message == "" {
message = "Fatal error occured. The application cannot continue to run."
}
log.Println(message)

// If a.ctx has not been set yet (i.e. we are before calling Startup), we can't display the
// dialog. Instead, we keep the error and let Startup call this function again when a.ctx is set.
if a.ctx == nil {
// We will only display the first error, since it makes more sense
if startupError == nil {
startupError = errors.New(message)
}
// Return to allow the application to continue starting up, until we get the context
return
// We now have a window, so we can finally show any accumulated errors
for _, err := range a.deferredErrors {
a.emitErrorMsg(err, nil)
}
_, _ = runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
Type: runtime.ErrorDialog,
Title: "Fatal Error",
Message: message,
})
os.Exit(1)
}

func (a *App) GetEnv(key string) string {
return os.Getenv(key)
}
fn := a.getFullPath()
if file.FileExists(fn) {
a.readFile(fn)
} else {
a.newFile()
}

func (a *App) SetEnv(key, value string) {
os.Setenv(key, value)
}
go a.Refresh()

func (a *App) GetMeta() coreTypes.MetaData {
return a.meta
}
go a.freshenController.Run()
go a.scraperController.Run()
go a.ipfsController.Run()

type ModifyData struct {
Operation string `json:"operation"`
Address base.Address `json:"address"`
Value string `json:"value"`
logger.Info("Fininished loading...")
}

func (a *App) ModifyNoop(modData *ModifyData) error {
route := a.GetSessionVal("route")
messages.Send(a.ctx, messages.Info, messages.NewInfoMessage(fmt.Sprintf("%s modify NO-OP %s: %s", route, modData.Operation, modData.Address.Hex())))
return nil
// Shutdown is called by Wails when the app is closed
func (a *App) Shutdown(ctx context.Context) {
a.saveSession()
}
Loading

0 comments on commit 9b3330d

Please sign in to comment.