Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/delegation/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ var createCmd = &cobra.Command{
return fmt.Errorf("creating delegation: %w", err)
}

if err := c.AddProofs(dlg); err != nil {
return fmt.Errorf("saving delegation to local store: %w", err)
}

if createFlags.output != "" {
data, err := io.ReadAll(delegation.Archive(dlg))
if err != nil {
Expand Down
57 changes: 57 additions & 0 deletions cmd/delegation/ls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package delegation

import (
"fmt"

"github.com/spf13/cobra"
"github.com/storacha/guppy/internal/cmdutil"
"github.com/storacha/guppy/pkg/config"
)

var lsCmd = &cobra.Command{
Use: "ls",
Short: "List delegations created by this agent for others.",
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.Load[config.Config]()
if err != nil {
return err
}
c := cmdutil.MustGetClient(cfg.Repo.Dir)

proofs, err := c.Proofs()
if err != nil {
return fmt.Errorf("getting proofs: %w", err)
}

myDID := c.DID().String()
count := 0

for _, p := range proofs {
issuer := p.Issuer().DID().String()
audience := p.Audience().DID().String()

if issuer == myDID && audience != myDID {
if count == 0 {
fmt.Println("Delegations created by this agent:")
}
count++

fmt.Printf("CID: %s\n", p.Link().String())
fmt.Printf("Audience: %s\n", audience)
fmt.Printf("Capabilities:\n")
for _, cap := range p.Capabilities() {
fmt.Printf(" - %s (with: %s)\n", cap.Can(), cap.With())
}
fmt.Println()
}
}

if count == 0 {
fmt.Println("No external delegations created by this agent found.")
} else {
fmt.Printf("Total: %d delegation(s)\n", count)
}

return nil
},
}
37 changes: 37 additions & 0 deletions cmd/delegation/revoke.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package delegation

import (
"fmt"

"github.com/ipfs/go-cid"
"github.com/spf13/cobra"
"github.com/storacha/guppy/internal/cmdutil"
"github.com/storacha/guppy/pkg/config"
)

var revokeCmd = &cobra.Command{
Use: "revoke <cid>",
Short: "Revoke a delegation by CID.",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.Load[config.Config]()
if err != nil {
return err
}
c := cmdutil.MustGetClient(cfg.Repo.Dir)

targetCid, err := cid.Parse(args[0])
if err != nil {
return fmt.Errorf("invalid CID format: %w", err)
}

fmt.Printf("Revoking delegation %s...\n", targetCid.String())

if err := c.Revoke(cmd.Context(), targetCid); err != nil {
return fmt.Errorf("failed to revoke delegation: %w", err)
}

fmt.Println("Success! Delegation has been revoked.")
return nil
},
}
2 changes: 2 additions & 0 deletions cmd/delegation/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ var Cmd = &cobra.Command{

func init() {
Cmd.AddCommand(createCmd)
Cmd.AddCommand(lsCmd)
Cmd.AddCommand(revokeCmd)
}
91 changes: 91 additions & 0 deletions cmd/plan/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package plan

import (
"encoding/json"
"fmt"
"strings"

"github.com/mitchellh/go-wordwrap"
"github.com/spf13/cobra"
"github.com/storacha/go-ucanto/did"

"github.com/storacha/guppy/internal/cmdutil"
"github.com/storacha/guppy/pkg/config"
"github.com/storacha/guppy/pkg/didmailto"
)

var getFlags struct {
jsonOutput bool
}

func init() {
getCmd.Flags().BoolVar(&getFlags.jsonOutput, "json", false, "Output in JSON format")
}

var getCmd = &cobra.Command{
Use: "get [account-did]",
Short: "Get the billing plan for an account",
Long: wordwrap.WrapString(
"Displays the billing plan the current account is subscribed to. "+
"If no account DID is provided, it defaults to the currently logged-in account.",
80),
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()

cfg, err := config.Load[config.Config]()
if err != nil {
return err
}
c := cmdutil.MustGetClient(cfg.Repo.Dir)

var accountDID did.DID

if len(args) > 0 {
accountDID, err = didmailto.FromInput(args[0])
if err != nil {
return fmt.Errorf("invalid account DID: %w", err)
}
} else {
accounts, err := c.Accounts()
if err != nil {
return fmt.Errorf("listing accounts: %w", err)
}
if len(accounts) == 0 {
return fmt.Errorf("no accounts found. Please login with 'guppy login'")
}
accountDID = accounts[0]
}

plan, err := c.PlanGet(ctx, accountDID)
if err != nil {
if strings.Contains(err.Error(), "billing profile not found") {
if getFlags.jsonOutput {
fmt.Println(`{"error": "No billing profile found"}`)
return nil
}
fmt.Printf(" No billing profile found for %s\n", accountDID)
fmt.Println(" Please visit the console to set up a plan: https://console.storacha.network")
return nil
}
return fmt.Errorf("getting plan: %w", err)
}

if getFlags.jsonOutput {
jsonBytes, err := json.MarshalIndent(plan, "", " ")
if err != nil {
return fmt.Errorf("marshaling output: %w", err)
}
fmt.Println(string(jsonBytes))
} else {
fmt.Printf("Plan Details for %s:\n", accountDID)
fmt.Printf(" Product: %s\n", plan.Product)
fmt.Printf(" Limit: %s\n", plan.Limit)
if plan.UpdatedAt != "" {
fmt.Printf(" Updated: %s\n", plan.UpdatedAt)
}
}

return nil
},
}
20 changes: 20 additions & 0 deletions cmd/plan/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package plan

import (
"github.com/mitchellh/go-wordwrap"
"github.com/spf13/cobra"
)

var Cmd = &cobra.Command{
Use: "plan",
Short: "Manage billing plans",
Long: wordwrap.WrapString(
"Inspect and manage the billing plan associated with your Storacha account.",
80),
}

func init() {
Cmd.AddCommand(
getCmd,
)
}
78 changes: 78 additions & 0 deletions cmd/plan/set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package plan

import (
"fmt"
"strings"

"github.com/mitchellh/go-wordwrap"
"github.com/spf13/cobra"
"github.com/storacha/go-ucanto/did"

"github.com/storacha/guppy/internal/cmdutil"
"github.com/storacha/guppy/pkg/config"
"github.com/storacha/guppy/pkg/didmailto"
)

var setCmd = &cobra.Command{
Use: "set <product-did>",
Short: "Set the billing plan for an account",
Long: wordwrap.WrapString(
"Sets the billing plan for the account. You must provide the Product DID (e.g., did:web:starter.storacha.network). "+
"Optionally provide the account DID via --account, otherwise it defaults to the current account.",
80),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
productDIDStr := args[0]

productDID, err := did.Parse(productDIDStr)
if err != nil {
return fmt.Errorf("invalid product DID: %w", err)
}

cfg, err := config.Load[config.Config]()
if err != nil {
return err
}
c := cmdutil.MustGetClient(cfg.Repo.Dir)

var accountDID did.DID
if cmd.Flag("account").Changed {
val, _ := cmd.Flags().GetString("account")
accountDID, err = didmailto.FromInput(val)
if err != nil {
return fmt.Errorf("invalid account DID: %w", err)
}
} else {
accounts, err := c.Accounts()
if err != nil {
return err
}
if len(accounts) == 0 {
return fmt.Errorf("no accounts found")
}
accountDID = accounts[0]
}

fmt.Printf("Setting plan for %s to %s...\n", accountDID, productDID)
_, err = c.PlanSet(ctx, accountDID, productDID)

if err != nil {
if strings.Contains(err.Error(), "billing profile not found") {
fmt.Println("\n Update Failed: No Billing Profile Found")
fmt.Println(" To change plans, you must first set up a payment method.")
fmt.Println(" Please visit the console: https://console.storacha.network")
return nil
}
return err
}

fmt.Println("Success! Plan updated.")
return nil
},
}

func init() {
setCmd.Flags().String("account", "", "The account DID to update")
Cmd.AddCommand(setCmd)
}
48 changes: 48 additions & 0 deletions cmd/proof/ls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package proof

import (
"fmt"

"github.com/spf13/cobra"

"github.com/storacha/guppy/internal/cmdutil"
"github.com/storacha/guppy/pkg/config"
)

var lsCmd = &cobra.Command{
Use: "ls",
Short: "List proofs of capabilities delegated to this agent.",
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := config.Load[config.Config]()
if err != nil {
return err
}

c := cmdutil.MustGetClient(cfg.Repo.Dir)

proofs, err := c.Proofs()
if err != nil {
return fmt.Errorf("getting proofs: %w", err)
}

if len(proofs) == 0 {
fmt.Println("No proofs found in the local agent store.")
return nil
}

fmt.Printf("Found %d proof(s):\n", len(proofs))

for _, p := range proofs {
fmt.Printf("CID: %s\n", p.Link().String())
fmt.Printf("Issuer: %s\n", p.Issuer().DID().String())
fmt.Println("Capabilities:")

for _, cap := range p.Capabilities() {
fmt.Printf(" - %v (with: %v)\n", cap.Can(), cap.With())
}
}

return nil
},
}
1 change: 1 addition & 0 deletions cmd/proof/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ var Cmd = &cobra.Command{

func init() {
Cmd.AddCommand(addCmd)
Cmd.AddCommand(lsCmd)
}
4 changes: 4 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ import (
"github.com/storacha/guppy/cmd/account"
"github.com/storacha/guppy/cmd/delegation"
"github.com/storacha/guppy/cmd/gateway"
"github.com/storacha/guppy/cmd/plan"
"github.com/storacha/guppy/cmd/proof"
"github.com/storacha/guppy/cmd/space"
"github.com/storacha/guppy/cmd/upload"
"github.com/storacha/guppy/cmd/usage"
)

var (
Expand Down Expand Up @@ -103,6 +105,8 @@ func init() {
delegation.Cmd,
account.Cmd,
blob.Cmd,
plan.Cmd,
usage.Cmd,
)
}

Expand Down
Loading
Loading