diff --git a/api/api_full.go b/api/api_full.go index b91ecd3e7..06d0c0d39 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -515,6 +515,8 @@ type FullNode interface { // along with the address removal. MsigRemoveSigner(ctx context.Context, msig address.Address, proposer address.Address, toRemove address.Address, decrease bool) (cid.Cid, error) + // MarketAddBalance adds funds to the market actor + MarketAddBalance(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) // MarketReserveFunds reserves funds for a deal MarketReserveFunds(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) // MarketReleaseFunds releases funds reserved by MarketReserveFunds diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 6d84675ef..5e6875c32 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -247,6 +247,7 @@ type FullNodeStruct struct { MarketReserveFunds func(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) `perm:"sign"` MarketReleaseFunds func(ctx context.Context, addr address.Address, amt types.BigInt) error `perm:"sign"` MarketWithdraw func(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) `perm:"sign"` + MarketAddBalance func(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) `perm:"sign"` PaychGet func(ctx context.Context, from, to address.Address, amt types.BigInt) (*api.ChannelInfo, error) `perm:"sign"` PaychGetWaitReady func(context.Context, cid.Cid) (address.Address, error) `perm:"sign"` @@ -1148,6 +1149,10 @@ func (c *FullNodeStruct) MsigRemoveSigner(ctx context.Context, msig address.Addr return c.Internal.MsigRemoveSigner(ctx, msig, proposer, toRemove, decrease) } +func (c *FullNodeStruct) MarketAddBalance(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) { + return c.Internal.MarketAddBalance(ctx, wallet, addr, amt) +} + func (c *FullNodeStruct) MarketReserveFunds(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) { return c.Internal.MarketReserveFunds(ctx, wallet, addr, amt) } diff --git a/cli/wallet.go b/cli/wallet.go index e9b8e6ece..1c7181bd5 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -509,6 +509,7 @@ var walletMarket = &cli.Command{ Usage: "Interact with market balances", Subcommands: []*cli.Command{ walletMarketWithdraw, + walletMarketAdd, }, } @@ -593,3 +594,74 @@ var walletMarketWithdraw = &cli.Command{ return nil }, } + +var walletMarketAdd = &cli.Command{ + Name: "add", + Usage: "Add funds to the Storage Market Actor", + ArgsUsage: "", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "from", + Usage: "Specify address to move funds from, otherwise it will use the default wallet address", + Aliases: []string{"f"}, + }, + &cli.StringFlag{ + Name: "address", + Usage: "Market address to move funds to (account or miner actor address, defaults to --from address)", + Aliases: []string{"a"}, + }, + }, + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return xerrors.Errorf("getting node API: %w", err) + } + defer closer() + ctx := ReqContext(cctx) + + // Get amount param + if !cctx.Args().Present() { + return fmt.Errorf("must pass amount to add") + } + f, err := types.ParseFIL(cctx.Args().First()) + if err != nil { + return xerrors.Errorf("parsing 'amount' argument: %w", err) + } + + amt := abi.TokenAmount(f) + + // Get from param + var from address.Address + if cctx.String("from") != "" { + from, err = address.NewFromString(cctx.String("from")) + if err != nil { + return xerrors.Errorf("parsing from address: %w", err) + } + } else { + from, err = api.WalletDefaultAddress(ctx) + if err != nil { + return xerrors.Errorf("getting default wallet address: %w", err) + } + } + + // Get address param + addr := from + if cctx.String("address") != "" { + addr, err = address.NewFromString(cctx.String("address")) + if err != nil { + return xerrors.Errorf("parsing market address: %w", err) + } + } + + // Add balance to market actor + fmt.Printf("Submitting Add Balance message for amount %s for address %s\n", types.FIL(amt), addr) + smsg, err := api.MarketAddBalance(ctx, from, addr, amt) + if err != nil { + return xerrors.Errorf("add balance error: %w", err) + } + + fmt.Printf("AddBalance message cid: %s\n", smsg) + + return nil + }, +} diff --git a/documentation/en/api-methods.md b/documentation/en/api-methods.md index 9f46460f1..183a6aed4 100644 --- a/documentation/en/api-methods.md +++ b/documentation/en/api-methods.md @@ -68,6 +68,7 @@ * [LogList](#LogList) * [LogSetLevel](#LogSetLevel) * [Market](#Market) + * [MarketAddBalance](#MarketAddBalance) * [MarketReleaseFunds](#MarketReleaseFunds) * [MarketReserveFunds](#MarketReserveFunds) * [MarketWithdraw](#MarketWithdraw) @@ -1653,6 +1654,28 @@ Response: `{}` ## Market +### MarketAddBalance +MarketAddBalance adds funds to the market actor + + +Perms: sign + +Inputs: +```json +[ + "f01234", + "f01234", + "0" +] +``` + +Response: +```json +{ + "/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4" +} +``` + ### MarketReleaseFunds MarketReleaseFunds releases funds reserved by MarketReserveFunds diff --git a/node/impl/market/market.go b/node/impl/market/market.go index e7fccc9ba..2c6098fbd 100644 --- a/node/impl/market/market.go +++ b/node/impl/market/market.go @@ -3,21 +3,45 @@ package market import ( "context" + "github.com/ipfs/go-cid" "go.uber.org/fx" - "github.com/ipfs/go-cid" - "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lotus/chain/actors" + marketactor "github.com/filecoin-project/lotus/chain/actors/builtin/market" "github.com/filecoin-project/lotus/chain/market" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/lotus/node/impl/full" ) type MarketAPI struct { fx.In + full.MpoolAPI FMgr *market.FundManager } +func (a *MarketAPI) MarketAddBalance(ctx context.Context, wallet, addr address.Address, amt types.BigInt) (cid.Cid, error) { + params, err := actors.SerializeParams(&addr) + if err != nil { + return cid.Undef, err + } + + smsg, aerr := a.MpoolPushMessage(ctx, &types.Message{ + To: marketactor.Address, + From: wallet, + Value: amt, + Method: marketactor.Methods.AddBalance, + Params: params, + }, nil) + + if aerr != nil { + return cid.Undef, aerr + } + + return smsg.Cid(), nil +} + func (a *MarketAPI) MarketReserveFunds(ctx context.Context, wallet address.Address, addr address.Address, amt types.BigInt) (cid.Cid, error) { return a.FMgr.Reserve(ctx, wallet, addr, amt) }