remove interactive UX; add inspect-deal
cmd
This commit is contained in:
parent
84803f82ab
commit
9d6c77d93f
@ -605,7 +605,7 @@ type DealInfo struct {
|
|||||||
ProposalCid cid.Cid
|
ProposalCid cid.Cid
|
||||||
State storagemarket.StorageDealStatus
|
State storagemarket.StorageDealStatus
|
||||||
Message string // more information about deal state, particularly errors
|
Message string // more information about deal state, particularly errors
|
||||||
DealStages storagemarket.DealStages
|
DealStages *storagemarket.DealStages
|
||||||
Provider address.Address
|
Provider address.Address
|
||||||
|
|
||||||
DataRef *storagemarket.DataRef
|
DataRef *storagemarket.DataRef
|
||||||
|
@ -60,6 +60,7 @@ type DataTransferChannel struct {
|
|||||||
Message string
|
Message string
|
||||||
OtherPeer peer.ID
|
OtherPeer peer.ID
|
||||||
Transferred uint64
|
Transferred uint64
|
||||||
|
Stages *datatransfer.ChannelStages
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDataTransferChannel constructs an API DataTransferChannel type from full channel state snapshot and a host id
|
// NewDataTransferChannel constructs an API DataTransferChannel type from full channel state snapshot and a host id
|
||||||
@ -70,6 +71,7 @@ func NewDataTransferChannel(hostID peer.ID, channelState datatransfer.ChannelSta
|
|||||||
BaseCID: channelState.BaseCID(),
|
BaseCID: channelState.BaseCID(),
|
||||||
IsSender: channelState.Sender() == hostID,
|
IsSender: channelState.Sender() == hostID,
|
||||||
Message: channelState.Message(),
|
Message: channelState.Message(),
|
||||||
|
Stages: channelState.Stages(),
|
||||||
}
|
}
|
||||||
stringer, ok := channelState.Voucher().(fmt.Stringer)
|
stringer, ok := channelState.Voucher().(fmt.Stringer)
|
||||||
if ok {
|
if ok {
|
||||||
|
@ -38,6 +38,9 @@ func init() {
|
|||||||
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
|
policy.SetConsensusMinerMinPower(abi.NewStoragePower(2048))
|
||||||
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
policy.SetMinVerifiedDealSize(abi.NewStoragePower(256))
|
||||||
|
|
||||||
|
//policy.SetWPoStChallengeWindow(abi.ChainEpoch(5))
|
||||||
|
policy.SetPreCommitChallengeDelay(abi.ChainEpoch(10))
|
||||||
|
|
||||||
BuildType |= Build2k
|
BuildType |= Build2k
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ var clientCmd = &cli.Command{
|
|||||||
WithCategory("storage", clientGetDealCmd),
|
WithCategory("storage", clientGetDealCmd),
|
||||||
WithCategory("storage", clientListAsksCmd),
|
WithCategory("storage", clientListAsksCmd),
|
||||||
WithCategory("storage", clientDealStatsCmd),
|
WithCategory("storage", clientDealStatsCmd),
|
||||||
WithCategory("storage", clientShowDealsCmd),
|
WithCategory("storage", clientInspectDealCmd),
|
||||||
WithCategory("data", clientImportCmd),
|
WithCategory("data", clientImportCmd),
|
||||||
WithCategory("data", clientDropCmd),
|
WithCategory("data", clientDropCmd),
|
||||||
WithCategory("data", clientLocalCmd),
|
WithCategory("data", clientLocalCmd),
|
||||||
@ -1116,20 +1116,26 @@ var clientRetrieveCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var clientShowDealsCmd = &cli.Command{
|
var clientInspectDealCmd = &cli.Command{
|
||||||
Name: "show-deals",
|
Name: "inspect-deal",
|
||||||
Usage: "Show storage deals",
|
Usage: "Inspect storage deal",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.IntFlag{
|
||||||
|
Name: "deal-id",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "proposal-cid",
|
||||||
|
},
|
||||||
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
//api, closer, err := GetFullNodeAPI(cctx)
|
api, closer, err := GetFullNodeAPI(cctx)
|
||||||
//if err != nil {
|
if err != nil {
|
||||||
// return err
|
return err
|
||||||
//}
|
}
|
||||||
//defer closer()
|
defer closer()
|
||||||
var api api.FullNode
|
|
||||||
|
|
||||||
ctx := ReqContext(cctx)
|
ctx := ReqContext(cctx)
|
||||||
//afmt := NewAppFmt(cctx.App)
|
return dealcli.InspectDealCmd(ctx, api, cctx.String("proposal-cid"), cctx.Int("deal-id"))
|
||||||
return dealcli.ShowDealsCmd(ctx, api)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,270 +2,85 @@ package deal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
tm "github.com/buger/goterm"
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
"github.com/filecoin-project/go-fil-markets/storagemarket"
|
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
|
||||||
lapi "github.com/filecoin-project/lotus/api"
|
lapi "github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/lib/tablewriter"
|
|
||||||
"github.com/ipfs/go-cid"
|
|
||||||
term "github.com/nsf/termbox-go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var mockDealInfos []lapi.DealInfo
|
var mockDealInfos []lapi.DealInfo
|
||||||
|
|
||||||
func init() {
|
func InspectDealCmd(ctx context.Context, api lapi.FullNode, proposalCid string, dealId int) error {
|
||||||
dummyCid, err := cid.Parse("bafkqaaa")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mockDealStages := storagemarket.DealStages{
|
|
||||||
At: time.Now(),
|
|
||||||
Stages: []storagemarket.DealStage{{
|
|
||||||
Name: "Reserving Funds",
|
|
||||||
ExpectedDuration: "5 epochs",
|
|
||||||
StartedAt: time.Now().Add(-5 * time.Minute),
|
|
||||||
Logs: []string{
|
|
||||||
"Sending AddBalance message for 0.3FIL",
|
|
||||||
"Waiting 5 epochs (2:30) for confirmation",
|
|
||||||
"Funds for deal reserved successfully",
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
Name: "Sending Deal Proposal to Provider",
|
|
||||||
ExpectedDuration: "5 epochs",
|
|
||||||
StartedAt: time.Now().Add(-2 * time.Minute),
|
|
||||||
Logs: []string{
|
|
||||||
"Proposal: 512MB for 300 days @ 0.1FIL / GB / epoch",
|
|
||||||
"Deal proposal accepted by provider",
|
|
||||||
"Funds for deal reserved successfully",
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
Name: "Sending deal data to Provider",
|
|
||||||
ExpectedDuration: "13 minutes",
|
|
||||||
StartedAt: time.Now().Add(-53 * time.Second),
|
|
||||||
Logs: []string{
|
|
||||||
"Progress: 4:02 254MB / 1024MB (1MB / sec)",
|
|
||||||
"Connection to Provider f01234 disconnected, retrying in 8s",
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
Name: "Waiting for deal to be published by Provider",
|
|
||||||
ExpectedDuration: "several hours",
|
|
||||||
}, {
|
|
||||||
Name: "Waiting for pre-commit message from Provider",
|
|
||||||
ExpectedDuration: "several hours",
|
|
||||||
}, {
|
|
||||||
Name: "Waiting for prove-commit message from Provider",
|
|
||||||
ExpectedDuration: "several hours",
|
|
||||||
}},
|
|
||||||
}
|
|
||||||
|
|
||||||
mockDealInfos = []lapi.DealInfo{{
|
|
||||||
State: 3,
|
|
||||||
Message: "Reserving Client Funds",
|
|
||||||
DealStages: mockDealStages,
|
|
||||||
Provider: address.TestAddress,
|
|
||||||
DataRef: nil,
|
|
||||||
PieceCID: dummyCid,
|
|
||||||
Size: 512 * 1024 * 1024,
|
|
||||||
PricePerEpoch: abi.NewTokenAmount(10),
|
|
||||||
Duration: 300,
|
|
||||||
DealID: 10,
|
|
||||||
CreationTime: time.Now().Add(-5 * time.Second),
|
|
||||||
Verified: false,
|
|
||||||
TransferChannelID: nil,
|
|
||||||
DataTransfer: nil,
|
|
||||||
}, {
|
|
||||||
State: 5,
|
|
||||||
Message: "Publishing Deal",
|
|
||||||
DealStages: mockDealStages,
|
|
||||||
Provider: address.TestAddress,
|
|
||||||
DataRef: nil,
|
|
||||||
PieceCID: dummyCid,
|
|
||||||
Size: 482 * 1024 * 1024,
|
|
||||||
PricePerEpoch: abi.NewTokenAmount(12),
|
|
||||||
Duration: 323,
|
|
||||||
DealID: 14,
|
|
||||||
CreationTime: time.Now().Add(-23 * time.Minute),
|
|
||||||
Verified: false,
|
|
||||||
TransferChannelID: nil,
|
|
||||||
DataTransfer: nil,
|
|
||||||
}, {
|
|
||||||
State: 7,
|
|
||||||
Message: "Waiting for Pre-Commit",
|
|
||||||
DealStages: mockDealStages,
|
|
||||||
Provider: address.TestAddress,
|
|
||||||
DataRef: nil,
|
|
||||||
PieceCID: dummyCid,
|
|
||||||
Size: 2 * 1024 * 1024 * 1024,
|
|
||||||
PricePerEpoch: abi.NewTokenAmount(8),
|
|
||||||
Duration: 298,
|
|
||||||
DealID: 8,
|
|
||||||
CreationTime: time.Now().Add(-3 * time.Hour),
|
|
||||||
Verified: false,
|
|
||||||
TransferChannelID: nil,
|
|
||||||
DataTransfer: nil,
|
|
||||||
}, {
|
|
||||||
State: 2,
|
|
||||||
Message: "Transferring Data",
|
|
||||||
DealStages: mockDealStages,
|
|
||||||
Provider: address.TestAddress,
|
|
||||||
DataRef: nil,
|
|
||||||
PieceCID: dummyCid,
|
|
||||||
Size: 23 * 1024 * 1024,
|
|
||||||
PricePerEpoch: abi.NewTokenAmount(11),
|
|
||||||
Duration: 328,
|
|
||||||
DealID: 3,
|
|
||||||
CreationTime: time.Now().Add(-49 * time.Hour),
|
|
||||||
Verified: false,
|
|
||||||
TransferChannelID: nil,
|
|
||||||
DataTransfer: nil,
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ShowDealsCmd(ctx context.Context, api lapi.FullNode) error {
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
//localDeals, err := api.ClientListDeals(ctx)
|
deals, err := api.ClientListDeals(ctx)
|
||||||
//if err != nil {
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
localDeals := mockDealInfos
|
|
||||||
|
|
||||||
return showDealsUX(ctx, localDeals)
|
|
||||||
}
|
|
||||||
|
|
||||||
func showDealsUX(ctx context.Context, deals []lapi.DealInfo) error {
|
|
||||||
err := term.Init()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer term.Close()
|
|
||||||
|
|
||||||
renderer := dealRenderer{out: tm.Screen}
|
var di lapi.DealInfo
|
||||||
|
found := false
|
||||||
dealIdx := -1
|
for _, cdi := range deals {
|
||||||
state := "main"
|
if proposalCid != "" && cdi.ProposalCid.String() == proposalCid {
|
||||||
highlighted := -1
|
di = cdi
|
||||||
for {
|
found = true
|
||||||
if err := ctx.Err(); err != nil {
|
break
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch state {
|
if dealId != 0 && int(cdi.DealID) == dealId {
|
||||||
case "main":
|
di = cdi
|
||||||
renderMain := func(hlite int) error {
|
found = true
|
||||||
tm.Clear()
|
break
|
||||||
tm.MoveCursor(1, 1)
|
|
||||||
err := renderer.renderDeals(deals, hlite)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tm.Flush()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := renderMain(highlighted)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ev := term.PollEvent(); ev.Type {
|
|
||||||
case term.EventKey:
|
|
||||||
switch {
|
|
||||||
case ev.Ch == 'q', ev.Key == term.KeyEsc:
|
|
||||||
return nil
|
|
||||||
case ev.Key == term.KeyArrowUp:
|
|
||||||
term.Sync()
|
|
||||||
if highlighted > 0 {
|
|
||||||
highlighted--
|
|
||||||
}
|
|
||||||
case ev.Key == term.KeyArrowDown:
|
|
||||||
term.Sync()
|
|
||||||
highlighted++
|
|
||||||
case ev.Key == term.KeyEnter:
|
|
||||||
term.Sync()
|
|
||||||
dealIdx = highlighted
|
|
||||||
state = "deal"
|
|
||||||
}
|
|
||||||
case term.EventError:
|
|
||||||
return ev.Err
|
|
||||||
}
|
|
||||||
case "deal":
|
|
||||||
tm.Clear()
|
|
||||||
tm.MoveCursor(1, 1)
|
|
||||||
renderer.renderDeal(deals[dealIdx])
|
|
||||||
tm.Flush()
|
|
||||||
|
|
||||||
switch ev := term.PollEvent(); ev.Type {
|
|
||||||
case term.EventKey:
|
|
||||||
if ev.Ch == 'q' || ev.Key == term.KeyEsc || ev.Key == term.KeyEnter || ev.Key == term.KeyArrowLeft {
|
|
||||||
term.Sync()
|
|
||||||
state = "main"
|
|
||||||
}
|
|
||||||
case term.EventError:
|
|
||||||
return ev.Err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
type dealRenderer struct {
|
if !found {
|
||||||
out io.Writer
|
if proposalCid != "" {
|
||||||
}
|
return fmt.Errorf("cannot find deal with proposal cid: %s", proposalCid)
|
||||||
|
}
|
||||||
|
if dealId != 0 {
|
||||||
|
return fmt.Errorf("cannot find deal with deal id: %v", dealId)
|
||||||
|
}
|
||||||
|
return errors.New("you must specify proposal cid or deal id in order to inspect a deal")
|
||||||
|
}
|
||||||
|
|
||||||
func (r *dealRenderer) renderDeals(deals []lapi.DealInfo, highlighted int) error {
|
renderDeal(di)
|
||||||
tw := tablewriter.New(
|
|
||||||
tablewriter.Col(""),
|
|
||||||
tablewriter.Col("Created"),
|
|
||||||
tablewriter.Col("Provider"),
|
|
||||||
tablewriter.Col("Size"),
|
|
||||||
tablewriter.Col("State"),
|
|
||||||
)
|
|
||||||
for i, di := range deals {
|
|
||||||
lineNum := fmt.Sprintf("%d", i+1)
|
|
||||||
cols := map[string]interface{}{
|
|
||||||
"": lineNum,
|
|
||||||
"Created": time.Since(di.CreationTime).Round(time.Second),
|
|
||||||
"Provider": di.Provider,
|
|
||||||
"Size": di.Size,
|
|
||||||
"State": di.Message,
|
|
||||||
}
|
|
||||||
if i == highlighted {
|
|
||||||
for k, v := range cols {
|
|
||||||
cols[k] = color.YellowString(fmt.Sprint(v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tw.Write(cols)
|
|
||||||
}
|
|
||||||
return tw.Flush(r.out)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *dealRenderer) renderDeal(di lapi.DealInfo) error {
|
|
||||||
_, err := fmt.Fprintf(r.out, "Deal %d\n", di.DealID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, stg := range di.DealStages.Stages {
|
|
||||||
msg := fmt.Sprintf("%s (%s)", stg.Name, stg.ExpectedDuration)
|
|
||||||
if stg.StartedAt.IsZero() {
|
|
||||||
msg = color.YellowString(msg)
|
|
||||||
}
|
|
||||||
_, err := fmt.Fprintf(r.out, "%s\n", msg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, l := range stg.Logs {
|
|
||||||
_, err = fmt.Fprintf(r.out, " %s\n", l)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renderDeal(di lapi.DealInfo) {
|
||||||
|
color.Blue("Deal ID: %d\n", int(di.DealID))
|
||||||
|
color.Blue("Proposal CID: %s\n\n", di.ProposalCid.String())
|
||||||
|
|
||||||
|
for _, stg := range di.DealStages.Stages {
|
||||||
|
msg := fmt.Sprintf("%s %s: %s (%s)", color.BlueString("Stage:"), color.BlueString(strings.TrimPrefix(stg.Name, "StorageDeal")), stg.Description, color.GreenString(stg.ExpectedDuration))
|
||||||
|
if stg.UpdatedTime.Time().IsZero() {
|
||||||
|
msg = color.YellowString(msg)
|
||||||
|
}
|
||||||
|
fmt.Println(msg)
|
||||||
|
|
||||||
|
for _, l := range stg.Logs {
|
||||||
|
fmt.Printf(" %s %s\n", color.YellowString(l.UpdatedTime.Time().UTC().Round(time.Second).Format(time.Stamp)), l.Log)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stg.Name == "StorageDealStartDataTransfer" {
|
||||||
|
for _, dt_stg := range di.DataTransfer.Stages.Stages {
|
||||||
|
|
||||||
|
msg := fmt.Sprintf("Data transfer stage: %s", dt_stg.Name)
|
||||||
|
msg = color.BlueString(msg)
|
||||||
|
if stg.UpdatedTime.Time().IsZero() {
|
||||||
|
msg = color.YellowString(msg)
|
||||||
|
}
|
||||||
|
fmt.Printf(" %s\n", msg)
|
||||||
|
for _, l := range dt_stg.Logs {
|
||||||
|
fmt.Printf(" %s %s\n", color.YellowString(l.UpdatedTime.Time().UTC().Round(time.Second).Format(time.Stamp)), l.Log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
3
go.mod
3
go.mod
@ -15,6 +15,7 @@ require (
|
|||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||||
github.com/cockroachdb/pebble v0.0.0-20201001221639-879f3bfeef07
|
github.com/cockroachdb/pebble v0.0.0-20201001221639-879f3bfeef07
|
||||||
github.com/coreos/go-systemd/v22 v22.1.0
|
github.com/coreos/go-systemd/v22 v22.1.0
|
||||||
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e
|
github.com/detailyang/go-fallocate v0.0.0-20180908115635-432fa640bd2e
|
||||||
github.com/dgraph-io/badger/v2 v2.2007.2
|
github.com/dgraph-io/badger/v2 v2.2007.2
|
||||||
github.com/docker/go-units v0.4.0
|
github.com/docker/go-units v0.4.0
|
||||||
@ -163,3 +164,5 @@ replace github.com/filecoin-project/filecoin-ffi => ./extern/filecoin-ffi
|
|||||||
replace github.com/filecoin-project/test-vectors => ./extern/test-vectors
|
replace github.com/filecoin-project/test-vectors => ./extern/test-vectors
|
||||||
|
|
||||||
replace github.com/filecoin-project/go-fil-markets => ../go-fil-markets
|
replace github.com/filecoin-project/go-fil-markets => ../go-fil-markets
|
||||||
|
|
||||||
|
replace github.com/filecoin-project/go-data-transfer => ../go-data-transfer
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||||
|
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
@ -215,6 +216,8 @@ func (a *API) ClientListDeals(ctx context.Context) ([]api.DealInfo, error) {
|
|||||||
out[k] = a.newDealInfoWithTransfer(transferCh, v)
|
out[k] = a.newDealInfoWithTransfer(transferCh, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spew.Dump(out)
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +292,7 @@ func (a *API) newDealInfoWithTransfer(transferCh *api.DataTransferChannel, v sto
|
|||||||
Verified: v.Proposal.VerifiedDeal,
|
Verified: v.Proposal.VerifiedDeal,
|
||||||
TransferChannelID: v.TransferChannelID,
|
TransferChannelID: v.TransferChannelID,
|
||||||
DataTransfer: transferCh,
|
DataTransfer: transferCh,
|
||||||
|
DealStages: v.DealStages,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user