Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add sample model to retrieve user input #20

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions pkg/config/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ const (
MsgChainAddAddress
// MsgSSIAddVC add a vc to the ssi wallet
MsgSSIAddVC
// MsgPaymentRequest receive a payment request
MsgPaymentRequest
)

// AppMsg are messages that are exchanged within the app
Expand Down
13 changes: 13 additions & 0 deletions pkg/helpers/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package helpers

import (
"time"
)

func DelayExec(delay int, fn func()) {
t1 := time.NewTicker(time.Duration(delay) * time.Second)
go func() {
<-t1.C
fn()
}()
}
86 changes: 86 additions & 0 deletions pkg/model/presentations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package model

import (
"github.com/hyperledger/aries-framework-go/pkg/doc/verifiable"
log "github.com/sirupsen/logrus"
)

// SchemaField is a field within the credential schema
type SchemaField struct {
Name string
Title string
Description string
Value string
ReadOnly bool
}

func NewSchemaField(name, title, description string) SchemaField {
return SchemaField{
Name: name,
Title: title,
Description: description,
ReadOnly: false,
}
}
func NewSchemaLabel(name, title, description, value string) SchemaField {
return SchemaField{
Name: name,
Title: title,
Description: description,
Value: value,
ReadOnly: true,
}
}

// PresentationRequest represent a verifiable credential schema
type PresentationRequest struct {
// The name of the presentation request
Name string
// Credential Should match the Verifiable Credentials that belongs to
Credential string
// Describe the request
Fields []SchemaField
}

// LicenseSchema returns a license schema
func LicenseSchema(licenseType, authority string) PresentationRequest {
//"license_type": "MICAEMI",
//"country": "EU",
//"authority": "Another Financial Services Body (AFFB)",
//"circulation_limit": {
// "denom": "sEUR",
// "amount": "1000000000"
//}
return PresentationRequest{
Name: "LicensePresentationRequest",
Credential: "LicenseCredential",
Fields: []SchemaField{
NewSchemaLabel("license_type", "License Type", "license acronym", licenseType),
NewSchemaLabel("authority", "Authority", "authority issuing the license", authority),
NewSchemaField("country", "Country", "country where the license applies"),
NewSchemaField("denom", "Token denomination", "the token symbol"),
NewSchemaField("amount", "Amount", "amount approved by the license"),
},
}
}

func PaymentRequest(address, denom, reason string) PresentationRequest {
return PresentationRequest{
Name: "PaymentPresentationRequest",
Credential: "ReceiptCredential",
Fields: []SchemaField{
NewSchemaLabel("reason", "Payment reason", "reason for the payment request", address),
NewSchemaLabel("recipient_address", "Recipient Address", "address to send the payment to", address),
NewSchemaLabel("denom", "Token denomination", "the token symbol requested by the recipient", denom),
NewSchemaField("amount", "Amount", "payment request amount"),
},
}
}

func LicensePresentation(license *verifiable.Credential) {
vp, err := verifiable.NewPresentation(verifiable.WithCredentials(license))
if err != nil {
log.Errorln(err)
}
log.Debugln(vp)
}
22 changes: 22 additions & 0 deletions pkg/ui/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ func dispatcher(in chan config.AppMsg) {
contact, _ := state.Contacts[tm.Channel]
contact.Texts = append(contact.Texts, tm) // refresh view
state.Contacts[tm.Channel] = contact
// process the incoming message to see if matches a schema

// process the incoming message to see if matches a verifiable credential

// save the state
appCfg.RuntimeMsgs.Notification <- config.NewAppMsg(config.MsgSaveState, nil)
Expand Down Expand Up @@ -259,6 +262,25 @@ func executeCmd() {
}

//hub.Notification <- "chain"
case "debug", "d":
switch s[1] {
case "show-license-credentials", "lc":
ls := model.LicenseSchema("MICAEMI", "Dredd")
RenderPresentationRequest("Please supply license information", ls, func(m map[string]string) {
// todo Create verifiable Credential
})
}
case "payment-request", "pr":
// TODO: the recipientAddress should be chose by the person making the payment request
// in this case is the account used for the resolver demo did. see github.com/allinbits/cosmos-cash-misc
recipientAddress := "cosmos1lcc4s4qkv0yg7ntmws6v44z5r5py27hap7pfw3"
pr := model.PaymentRequest(recipientAddress, "cash", "Demo Payment")
RenderPresentationRequest("Please fill the payment request", pr, func(m map[string]string) {
helpers.DelayExec(10, func() {
appCfg.RuntimeMsgs.Notification <- config.NewAppMsg(config.MsgPaymentRequest, nil)
})
})

}

// FINALLY RECORD THE MESSAGE IN THE CHAT
Expand Down
73 changes: 65 additions & 8 deletions pkg/ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,21 @@ import (
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/allinbits/cosmos-cash-agent/pkg/config"
"github.com/allinbits/cosmos-cash-agent/pkg/model"
log "github.com/sirupsen/logrus"
)

var (
mainApp fyne.App
mainWindow fyne.Window
)

func Render(cfg *config.EdgeConfigSchema) {

appCfg = cfg

myApp := app.New()
myWindow := myApp.NewWindow(cfg.ControllerName)
mainApp = app.New()
mainWindow = mainApp.NewWindow(cfg.ControllerName)

// main content
tabs := container.NewAppTabs(
Expand All @@ -30,22 +36,22 @@ func Render(cfg *config.EdgeConfigSchema) {
getLogTab(),
)

myWindow.SetContent(
mainWindow.SetContent(
container.NewMax(
tabs,
//footer,
),
)

myWindow.SetOnClosed(func() {
mainWindow.SetOnClosed(func() {
log.Infoln(">>>>>>> TERMINATING <<<<<<<")
})

// run the dispatcher that updates the ui
go dispatcher(cfg.RuntimeMsgs.Notification)
// lanuch the app
myWindow.Resize(fyne.NewSize(940, 660))
myWindow.ShowAndRun()
mainWindow.Resize(fyne.NewSize(940, 660))
mainWindow.ShowAndRun()
}

func getMessagesTab() *container.TabItem {
Expand Down Expand Up @@ -75,6 +81,11 @@ func getMessagesTab() *container.TabItem {
//msgPanel := container.NewVBox()
msgScroll := container.NewScroll(msgList)

input := widget.NewEntryWithData(userCommand)
input.OnSubmitted = func(_ string) {
executeCmd()
}

// footer stuff
rightPanel := container.NewBorder(
nil,
Expand Down Expand Up @@ -149,8 +160,6 @@ func getCredentialsTab() *container.TabItem {
)

// right panel


msgPanel := widget.NewEntryWithData(credentialData)
rightPanel := container.NewScroll(msgPanel)

Expand Down Expand Up @@ -212,3 +221,51 @@ func getLogTab() *container.TabItem {
main := container.NewScroll(msgPanel)
return container.NewTabItem("Logs", main)
}

func RenderPresentationRequest(title string, schema model.PresentationRequest, onSubmit func(map[string]string)) {
answers := make(map[string]binding.String)

var popUp *widget.PopUp
var fields []*widget.FormItem
for _, s := range schema.Fields {
// data
b := binding.NewString()
e := widget.NewEntryWithData(b)
if s.ReadOnly {
b.Set(s.Value)
e.Disable()
}
answers[s.Name] = b
// form item
w := widget.NewFormItem(s.Title, e)
w.HintText = s.Description
// fields
fields = append(fields, w)
}
form := &widget.Form{
Items: fields,
OnSubmit: func() {
// hide the popUp
popUp.Hide()
// convert data to string
data := make(map[string]string, len(fields))
for k, b := range answers {
s, _ := b.Get()
data[k] = s
}
// execute the callback
log.Debugln("form data", data)
onSubmit(data)
},
OnCancel: func() { popUp.Hide() },
SubmitText: "Submit",
CancelText: "Cancel",
}

// create the popUp
popUp = widget.NewModalPopUp(
widget.NewCard(title, "", form),
mainWindow.Canvas(),
)
popUp.Show()
}