Skip to content
Snippets Groups Projects
Select Git revision
  • 04d241f266bb39a5b65e54d9924887571d625b96
  • main default protected
  • development
  • integration
  • v1.1.5
  • v1.1.4
  • v1.1.3
  • v1.1.2
  • v1.1.1
  • v1.1.0
  • v1.0.0
11 results

ClientIdProvider.swift

Blame
  • main.go 7.85 KiB
    package main
    
    import (
    	"github.com/dtylman/gowd"
    	"github.com/dtylman/gowd/bootstrap"
    	jww "github.com/spf13/jwalterweatherman"
    	"gitlab.com/elixxir/client/interfaces/contact"
    	"regexp"
    	"strconv"
    	"strings"
    	"time"
    )
    
    var password = "password"
    var session = ".session"
    var ndfPath = "ndf.json"
    var logPath = "xx-coin-game.log"
    var botContactPath = "botContact.bin"
    var botContact contact.Contact
    
    var singleMngr SingleManager
    var client ClientAPI
    
    var body *gowd.Element
    
    const testMode = false
    
    func main() {
    
    	initLog()
    
    	// creates a new bootstrap fluid container
    	body = bootstrap.NewContainer(false)
    
    	// add some elements using the object model
    	div := bootstrap.NewElement("div", "well")
    	div.SetAttribute("style", "font-size:1.5em;margin-top:25px;")
    	body.AddElement(div)
    
    	logo := bootstrap.NewElement("img", "")
    	logo.SetAttribute("src", "img/xx_logo.svg")
    	logo.SetAttribute("style", "float:right;margin: -10px -10px 0 0;")
    	logo.SetAttribute("id", "logo")
    	div.AddElement(logo)
    
    	progressBarTitle := bootstrap.NewElement(gowd.Heading4, "")
    	progressBarTitle.SetAttribute("style", "text-align:center;")
    	progressBarTitle.SetText("Connecting to network")
    	spinner := bootstrap.NewElement("span", "spinner-grow")
    	spinner.SetAttribute("role", "status")
    	spinner.SetAttribute("style", "width: 3rem; height: 3rem;text-align:center;margin:0 auto;")
    	spinnerContainer := bootstrap.NewElement("div", "")
    	spinnerContainer.SetAttribute("style", "text-align: center")
    	spinnerContainer.AddElement(spinner)
    	div.AddElement(progressBarTitle)
    	div.AddElement(spinnerContainer)
    
    	err := body.Render()
    	if err != nil {
    		jww.ERROR.Printf("Failed to render body: %+v", err)
    	}
    
    	botContact = readBotContact()
    	client, singleMngr = initClient(testMode)
    
    	div.RemoveElement(spinnerContainer)
    	div.RemoveElement(progressBarTitle)
    	progressBarTitle = bootstrap.NewElement(gowd.Heading4, "")
    	progressBarTitle.SetAttribute("style", "text-align:center;")
    	progressBarTitle.SetText("Generating Keys and Registering with Network")
    	div.AddElement(progressBarTitle)
    	progressBar := bootstrap.NewProgressBar()
    	progressBar.Kids[0].SetAttribute("style", "background:#037281;")
    	div.AddElement(progressBar.Element)
    
    	registeredNodes, totalNodes, err := client.GetNodeRegistrationStatus()
    	if err != nil {
    		jww.FATAL.Panicf("Failed to get node registration status: %+v", err)
    	}
    	go func() {
    		for {
    			time.Sleep(100 * time.Millisecond)
    			registeredNodes, _, err = client.GetNodeRegistrationStatus()
    			if err != nil {
    				jww.FATAL.Panicf("Failed to get node registration status: %+v", err)
    			}
    			max := (totalNodes * 8) / 10
    			progressBar.SetText(strconv.Itoa(registeredNodes) + "/" + strconv.Itoa(totalNodes))
    			err = progressBar.SetValue(registeredNodes, totalNodes)
    			if err != nil {
    				jww.ERROR.Printf("Failed to set progress bar value: %+v", err)
    			}
    			err = body.Render()
    			if err != nil {
    				jww.ERROR.Printf("Failed to render body: %+v", err)
    			}
    
    			if registeredNodes >= max {
    				break
    			}
    		}
    
    		div.RemoveElement(progressBarTitle)
    		div.RemoveElement(progressBar.Element)
    
    		printForm(div)
    	}()
    
    	// Start the ui loop
    	err = gowd.Run(body)
    	if err != nil {
    		jww.ERROR.Printf("Failed to start ui loop: %+v", err)
    	}
    }
    
    func printForm(div *gowd.Element) {
    	ethAddr := bootstrap.NewFormInput(bootstrap.InputTypeText, "Ethereum Address:")
    	ethAddr.Element.Kids[1].SetAttribute("style", "font-family:'Roboto Mono', Consolas, 'Courier New', Courier, monospace;")
    	sendText := bootstrap.NewFormInput(bootstrap.InputTypeText, "Message:")
    
    	if testMode {
    		ethAddr.SetValue("0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7")
    	}
    
    	div.AddElement(ethAddr.Element)
    	div.AddElement(sendText.Element)
    
    	// add a button
    	btn := bootstrap.NewButton(bootstrap.ButtonPrimary, "Send over xx")
    	btn.SetAttribute("style", "background:#037281;background-color:#037281")
    	rtnDiv := bootstrap.NewElement("div", "well")
    	body.AddElement(rtnDiv)
    	btnEvent := func(sender *gowd.Element, event *gowd.EventElement) {
    		btnClicked(sender, event, ethAddr.Element.Kids[1], sendText.Element.Kids[1], rtnDiv)
    	}
    	btn.OnEvent(gowd.OnClick, btnEvent)
    	div.AddElement(btn)
    
    	err := body.Render()
    	if err != nil {
    		jww.ERROR.Printf("Failed to render body: %+v", err)
    	}
    }
    
    var lastElement, btnMessage, ethAddrFailure *gowd.Element
    
    // happens when the 'start' button is clicked
    func btnClicked(sender *gowd.Element, _ *gowd.EventElement, ethAddr,
    	sendText *gowd.Element, div *gowd.Element) {
    
    	// makes the body stop responding to user events
    	body.Disable()
    
    	if ethAddrFailure != nil {
    		ethAddr.Parent.RemoveElement(ethAddrFailure)
    	}
    
    	if !validEthereumAddress(ethAddr.GetValue()) {
    		ethAddrFailure = bootstrap.NewElement("span", bootstrap.AlertWarning+" very-small")
    		ethAddrFailure.SetText("Must be valid Ethereum address.")
    		ethAddr.Parent.AddElement(ethAddrFailure)
    		return
    	}
    
    	sender.SetAttribute("disabled", "")
    	spinner := bootstrap.NewElement("span", "spinner-grow")
    	spinner.SetAttribute("role", "status")
    	spinner.SetAttribute("style", "width: 3rem; height: 3rem;text-align:center;margin:0 auto;")
    	div.SetAttribute("style", "text-align: center")
    	div.AddElement(spinner)
    
    	if lastElement != nil {
    		div.RemoveElement(lastElement)
    	}
    	if btnMessage != nil {
    		sender.Parent.RemoveElement(btnMessage)
    	}
    
    	err := body.Render()
    	if err != nil {
    		jww.ERROR.Printf("Failed to render body: %+v", err)
    	}
    
    	// Send the message
    	message := ethAddr.GetValue() + ";" + sendText.GetValue()
    
    	defer func() {
    		time.Sleep(1 * time.Second)
    		sender.RemoveAttribute("disabled")
    		div.RemoveElement(spinner)
    		div.RemoveAttribute("style")
    		err := body.Render()
    		if err != nil {
    			jww.ERROR.Printf("Failed to render body: %+v", err)
    		}
    		body.Enable()
    	}()
    
    	replyString := make(chan string, 1)
    
    	// Inline function to print message from client to page, callback for upcoming function
    	replyFunc := func(payload []byte, err error) {
    		sender.Parent.RemoveElement(btnMessage)
    		btnMessage = bootstrap.NewElement("span", "")
    		var result string
    		if err != nil {
    			btnMessage.SetText("Failed to receive response.")
    			btnMessage.SetAttribute("style", "font-size:0.75em;padding:0.5em;color:#d62424;")
    			result = "ERROR: " + err.Error()
    		} else {
    			btnMessage.SetText("Received response.")
    			btnMessage.SetAttribute("style", "font-size:0.75em;padding:0.5em;color:#24d627;")
    			result = string(payload)
    		}
    		replyString <- result
    		sender.Parent.AddElement(btnMessage)
    	}
    
    	err = singleMngr.TransmitSingleUse(botContact, []byte(message),
    		"xxCoinGame", 10, replyFunc, 30*time.Second)
    	if err != nil {
    		lastElement = div.AddElement(gowd.NewStyledText(err.Error(), gowd.BoldText))
    
    		if btnMessage != nil {
    			sender.Parent.RemoveElement(btnMessage)
    		}
    
    		btnMessage = bootstrap.NewElement("span", "")
    		btnMessage.SetText("Message failed to send.")
    		btnMessage.SetAttribute("style", "font-size:0.75em;padding:0.5em;color:#d62424;")
    		sender.Parent.AddElement(btnMessage)
    		err := body.Render()
    		if err != nil {
    			jww.ERROR.Printf("Failed to render body: %+v", err)
    		}
    		return
    	} else {
    
    		if btnMessage != nil {
    			sender.Parent.RemoveElement(btnMessage)
    		}
    
    		time.Sleep(1 * time.Second)
    		btnMessage = bootstrap.NewElement("span", "")
    		btnMessage.SetAttribute("style", "font-size:0.75em;padding:0.5em;color:#24d627;")
    		sender.Parent.AddElement(btnMessage)
    		btnMessage.SetText("Message sent successfully. Waiting for response.")
    		err = body.Render()
    		if err != nil {
    			jww.ERROR.Printf("Failed to render body: %+v", err)
    		}
    	}
    
    	result := <-replyString
    	lastElement = div.AddElement(gowd.NewStyledText(result, gowd.BoldText))
    	lastElementStyle := "font-size:1.25em;line-height:1.25em;"
    	lastElement.SetAttribute("style", lastElementStyle)
    	if strings.Contains(result, "ERROR: ") {
    		lastElement.SetAttribute("style", lastElementStyle+"color:#d62424;")
    	}
    }
    
    func validEthereumAddress(address string) bool {
    	r, err := regexp.Compile("^0x[0-9a-fA-F]{40}$")
    	if err != nil {
    		jww.ERROR.Print(err)
    	}
    
    	return r.MatchString(address)
    }