-
Notifications
You must be signed in to change notification settings - Fork 13
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
Add command marketplace #817
Changes from 6 commits
fb456b0
3ba7807
3549980
9fa5c02
483c20e
a56eb0e
f80f289
63da140
a3da26d
659629a
c377038
f83d3f4
bf4f214
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,4 +22,3 @@ node_modules | |
# do not store vendor dir | ||
vendor | ||
tmp-systemservices | ||
node_modules |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package commands | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/mesg-foundation/core/commands/provider" | ||
"github.com/mesg-foundation/core/utils/pretty" | ||
"github.com/spf13/cobra" | ||
survey "gopkg.in/AlecAivazis/survey.v1" | ||
) | ||
|
||
type marketplaceCreateOfferCmd struct { | ||
baseMarketplaceCmd | ||
|
||
service provider.MarketplaceService | ||
price string // in MESG token | ||
duration string | ||
|
||
e Executor | ||
} | ||
|
||
func newMarketplaceCreateOfferCmd(e Executor) *marketplaceCreateOfferCmd { | ||
c := &marketplaceCreateOfferCmd{e: e} | ||
c.cmd = newCommand(&cobra.Command{ | ||
Use: "create-offer", | ||
Short: "Create a new offer on a service on the MESG Marketplace", | ||
Example: `mesg-core marketplace create-offer SID`, | ||
PreRunE: c.preRunE, | ||
RunE: c.runE, | ||
Args: cobra.MinimumNArgs(1), | ||
}) | ||
c.setupFlags() | ||
c.cmd.Flags().StringVarP(&c.price, "price", "", c.price, "Price (in MESG token) of the offer to create") | ||
c.cmd.Flags().StringVarP(&c.duration, "duration", "", c.duration, "Duration (in second) of the offer to create") | ||
return c | ||
} | ||
|
||
func (c *marketplaceCreateOfferCmd) preRunE(cmd *cobra.Command, args []string) error { | ||
var ( | ||
err error | ||
) | ||
|
||
if err := c.askAccountAndPassphrase(); err != nil { | ||
return err | ||
} | ||
|
||
if c.price == "" { | ||
if err := askInput("Enter the price (in MESG Token) of the offer", &c.price); err != nil { | ||
return err | ||
} | ||
} | ||
// if c.price < 0 { | ||
// return fmt.Errorf("Price cannot be negative") | ||
// } | ||
if c.duration == "" { | ||
if err := askInput("Enter the duration (in second) of the offer", &c.duration); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
pretty.Progress("Getting service data...", func() { | ||
c.service, err = c.e.GetService(args[0]) | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if !strings.EqualFold(c.service.Owner, c.account) { | ||
return fmt.Errorf("the service's owner %q is different than the specified account", c.service.Owner) | ||
} | ||
|
||
var confirmed bool | ||
if err := survey.AskOne(&survey.Confirm{ | ||
Message: fmt.Sprintf("Are you sure to create offer on service %q with price %q and duration %q?", args[0], c.price, c.duration), | ||
}, &confirmed, nil); err != nil { | ||
return err | ||
} | ||
if !confirmed { | ||
return fmt.Errorf("cancelled") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c *marketplaceCreateOfferCmd) runE(cmd *cobra.Command, args []string) error { | ||
var ( | ||
tx provider.Transaction | ||
err error | ||
) | ||
pretty.Progress("Creating offer on the marketplace...", func() { | ||
tx, err = c.e.CreateServiceOffer(args[0], c.price, c.duration, c.account) | ||
if err != nil { | ||
return | ||
} | ||
_, err = c.signAndSendTransaction(c.e, tx) | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("%s Offer created with success\n", pretty.SuccessSign) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we have these commands in the CLI we need to display all relevant information. Here for example the index of the offer. Here I cannot from the CLI only do anything after that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes you are right. The complicated thing is the marketplace service is returning a generic transaction receipt. It is not properly decoded because it doesn't know which method / event has been called or triggered. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not blocking for this PR for sure but one solution is to listen at the event from the marketplace. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. here is an example for this implementation based on event |
||
fmt.Printf("%s See it on the marketplace: https://marketplace.mesg.com/services/%s\n", pretty.SuccessSign, c.service.Sid) | ||
|
||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package commands | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/mesg-foundation/core/commands/provider" | ||
"github.com/mesg-foundation/core/utils/pretty" | ||
"github.com/spf13/cobra" | ||
survey "gopkg.in/AlecAivazis/survey.v1" | ||
) | ||
|
||
type marketplacePublishCmd struct { | ||
baseMarketplaceCmd | ||
|
||
path string | ||
manifest provider.MarketplaceManifestData | ||
service provider.MarketplaceService | ||
|
||
e Executor | ||
} | ||
|
||
func newMarketplacePublishCmd(e Executor) *marketplacePublishCmd { | ||
c := &marketplacePublishCmd{e: e} | ||
c.cmd = newCommand(&cobra.Command{ | ||
Use: "publish", | ||
Short: "Publish a service on the MESG Marketplace", | ||
Example: `mesg-core marketplace publish PATH_TO_SERVICE`, | ||
PreRunE: c.preRunE, | ||
RunE: c.runE, | ||
Args: cobra.MinimumNArgs(1), | ||
}) | ||
c.setupFlags() | ||
return c | ||
} | ||
|
||
func (c *marketplacePublishCmd) preRunE(cmd *cobra.Command, args []string) error { | ||
var ( | ||
err error | ||
question = "a new service" | ||
) | ||
|
||
if err := c.askAccountAndPassphrase(); err != nil { | ||
return err | ||
} | ||
|
||
c.path = getFirstOrCurrentPath(args) | ||
|
||
sid, hash, err := deployService(c.e, c.path, map[string]string{}) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("%s Service deployed with sid %s and hash %s\n", pretty.SuccessSign, pretty.Success(sid), pretty.Success(hash)) | ||
|
||
c.manifest, err = c.e.CreateManifest(c.path, hash) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
pretty.Progress("Getting service data...", func() { | ||
c.service, err = c.e.GetService(c.manifest.Service.Definition.Sid) | ||
}) | ||
outputError, isMarketplaceError := err.(provider.MarketplaceErrorOutput) | ||
if err != nil && !isMarketplaceError { | ||
return err | ||
} | ||
if outputError.Code != "notFound" { | ||
question = "a new version of service" | ||
if !strings.EqualFold(c.service.Owner, c.account) { | ||
return fmt.Errorf("the service's owner %q is different than the specified account", c.service.Owner) | ||
} | ||
} | ||
|
||
var confirmed bool | ||
if err := survey.AskOne(&survey.Confirm{ | ||
Message: fmt.Sprintf("Are you sure to publish %s %q from path %q using account %q?", question, c.manifest.Service.Definition.Sid, c.path, c.account), | ||
}, &confirmed, nil); err != nil { | ||
return err | ||
} | ||
if !confirmed { | ||
return fmt.Errorf("cancelled") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c *marketplacePublishCmd) runE(cmd *cobra.Command, args []string) error { | ||
var ( | ||
tx provider.Transaction | ||
err error | ||
manifestProtocol string | ||
manifestSource string | ||
) | ||
|
||
pretty.Progress("Uploading service source code on the marketplace...", func() { | ||
// TODO: add a progress for the upload | ||
manifestProtocol, manifestSource, err = c.e.UploadServiceFiles(c.path, c.manifest) | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
pretty.Progress("Publishing service on the marketplace...", func() { | ||
tx, err = c.e.PublishServiceVersion(c.manifest.Service.Definition.Sid, manifestSource, manifestProtocol, c.account) | ||
if err != nil { | ||
return | ||
} | ||
_, err = c.signAndSendTransaction(c.e, tx) | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("%s Service published with success\n", pretty.SuccessSign) | ||
fmt.Printf("%s See it on the marketplace: https://marketplace.mesg.com/services/%s\n", pretty.SuccessSign, c.manifest.Service.Definition.Sid) | ||
|
||
fmt.Printf("%s To create a service offer, execute the command:\n\tmesg-core marketplace create-offer %s\n", pretty.SuccessSign, c.manifest.Service.Definition.Sid) | ||
antho1404 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package commands | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
|
||
"github.com/mesg-foundation/core/commands/provider" | ||
"github.com/mesg-foundation/core/utils/pretty" | ||
"github.com/spf13/cobra" | ||
survey "gopkg.in/AlecAivazis/survey.v1" | ||
) | ||
|
||
type marketplacePurchaseCmd struct { | ||
baseMarketplaceCmd | ||
|
||
offerIndex string | ||
|
||
e Executor | ||
} | ||
|
||
func newMarketplacePurchaseCmd(e Executor) *marketplacePurchaseCmd { | ||
c := &marketplacePurchaseCmd{e: e} | ||
c.cmd = newCommand(&cobra.Command{ | ||
Use: "purchase", | ||
Short: "Purchase a service on the MESG Marketplace", | ||
Example: `mesg-core marketplace purchase SID`, | ||
PreRunE: c.preRunE, | ||
RunE: c.runE, | ||
Args: cobra.ExactArgs(1), | ||
}) | ||
c.setupFlags() | ||
c.cmd.Flags().StringVarP(&c.offerIndex, "offerIndex", "i", c.offerIndex, "Offer index to purchase") | ||
NicolasMahe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return c | ||
} | ||
|
||
func (c *marketplacePurchaseCmd) preRunE(cmd *cobra.Command, args []string) error { | ||
var ( | ||
service provider.MarketplaceService | ||
err error | ||
) | ||
|
||
if err := c.askAccountAndPassphrase(); err != nil { | ||
return err | ||
} | ||
|
||
if c.offerIndex == "" { | ||
// TODO: should display the list of offers and ask to select one | ||
if err := askInput("Enter the offer index to purchase", &c.offerIndex); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
pretty.Progress("Getting service data...", func() { | ||
service, err = c.e.GetService(args[0]) | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
offerIndex, err := strconv.Atoi(c.offerIndex) | ||
if err != nil { | ||
return err | ||
} | ||
if offerIndex >= len(service.Offers) { | ||
return fmt.Errorf("offer index %d doesn't exist", offerIndex) | ||
} | ||
offer := service.Offers[offerIndex] | ||
if !offer.Active { | ||
return fmt.Errorf("cannot purchase this offer because it is not active") | ||
} | ||
|
||
var confirmed bool | ||
if err := survey.AskOne(&survey.Confirm{ | ||
Message: fmt.Sprintf("Are you sure to purchase service %q for price %q and duration %q?", args[0], offer.Price, offer.Duration), | ||
}, &confirmed, nil); err != nil { | ||
return err | ||
} | ||
if !confirmed { | ||
return fmt.Errorf("cancelled") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c *marketplacePurchaseCmd) runE(cmd *cobra.Command, args []string) error { | ||
var ( | ||
transactions []provider.Transaction | ||
err error | ||
) | ||
pretty.Progress("Purchasing offer on the marketplace...", func() { | ||
transactions, err = c.e.Purchase(args[0], c.offerIndex, c.account) | ||
if err != nil { | ||
return | ||
} | ||
for _, tx := range transactions { | ||
_, err = c.signAndSendTransaction(c.e, tx) | ||
if err != nil { | ||
return | ||
} | ||
} | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("%s Offer purchased with success\n", pretty.SuccessSign) | ||
|
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine but I think this check should be done by the system service marketplace, the CLI should just call the
createOffer
task without having to do any check on the data