diff --git a/go/client/cmd_wallet.go b/go/client/cmd_wallet.go index ae90e2ef1932..558895bf0d9a 100644 --- a/go/client/cmd_wallet.go +++ b/go/client/cmd_wallet.go @@ -25,6 +25,7 @@ func newCmdWallet(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Comman newCmdWalletHistory(cl, g), newCmdWalletImport(cl, g), newCmdWalletLookup(cl, g), + newCmdWalletPopularAssets(cl, g), newCmdWalletRename(cl, g), newCmdWalletRequest(cl, g), newCmdWalletSend(cl, g), diff --git a/go/client/cmd_wallet_popular_assets.go b/go/client/cmd_wallet_popular_assets.go new file mode 100644 index 000000000000..0bc6566a2c9b --- /dev/null +++ b/go/client/cmd_wallet_popular_assets.go @@ -0,0 +1,62 @@ +package client + +import ( + "errors" + + "github.com/keybase/cli" + "github.com/keybase/client/go/libcmdline" + "github.com/keybase/client/go/libkb" + "golang.org/x/net/context" +) + +func (c *cmdWalletPopularAssets) GetUsage() libkb.Usage { + return libkb.Usage{ + API: true, + KbKeyring: true, + Config: true, + } +} + +type cmdWalletPopularAssets struct { + libkb.Contextified +} + +func newCmdWalletPopularAssets(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command { + cmd := &cmdWalletPopularAssets{ + Contextified: libkb.NewContextified(g), + } + return cli.Command{ + Name: "popular-assets", + Usage: "List popular assets", + Action: func(c *cli.Context) { + cl.ChooseCommand(cmd, "popular-assets", c) + }, + } +} + +func (c *cmdWalletPopularAssets) ParseArgv(ctx *cli.Context) error { + if len(ctx.Args()) != 0 { + return errors.New("listing popular assets expects no args") + } + return nil +} + +func (c *cmdWalletPopularAssets) Run() (err error) { + defer transformStellarCLIError(&err) + + cli, err := GetWalletClient(c.G()) + if err != nil { + return err + } + + assets, err := cli.ListPopularAssetsLocal(context.Background(), 0) + if err != nil { + return err + } + dui := c.G().UI.GetDumbOutputUI() + dui.Printf("popular assets:\n") + for _, asset := range assets { + dui.Printf(buildOutputStringForAsset(asset) + "\n") + } + return nil +} diff --git a/go/protocol/stellar1/local.go b/go/protocol/stellar1/local.go index bed7a6388079..f4252ebe36bf 100644 --- a/go/protocol/stellar1/local.go +++ b/go/protocol/stellar1/local.go @@ -1444,6 +1444,10 @@ type FuzzyAssetSearchLocalArg struct { SearchString string `codec:"searchString" json:"searchString"` } +type ListPopularAssetsLocalArg struct { + SessionID int `codec:"sessionID" json:"sessionID"` +} + type AddTrustlineLocalArg struct { SessionID int `codec:"sessionID" json:"sessionID"` AccountID AccountID `codec:"accountID" json:"accountID"` @@ -1653,6 +1657,7 @@ type LocalInterface interface { AirdropStatusLocal(context.Context, int) (AirdropStatus, error) AirdropRegisterLocal(context.Context, AirdropRegisterLocalArg) error FuzzyAssetSearchLocal(context.Context, FuzzyAssetSearchLocalArg) ([]Asset, error) + ListPopularAssetsLocal(context.Context, int) ([]Asset, error) AddTrustlineLocal(context.Context, AddTrustlineLocalArg) error DeleteTrustlineLocal(context.Context, DeleteTrustlineLocalArg) error ChangeTrustlineLimitLocal(context.Context, ChangeTrustlineLimitLocalArg) error @@ -2364,6 +2369,21 @@ func LocalProtocol(i LocalInterface) rpc.Protocol { return }, }, + "listPopularAssetsLocal": { + MakeArg: func() interface{} { + var ret [1]ListPopularAssetsLocalArg + return &ret + }, + Handler: func(ctx context.Context, args interface{}) (ret interface{}, err error) { + typedArgs, ok := args.(*[1]ListPopularAssetsLocalArg) + if !ok { + err = rpc.NewTypeError((*[1]ListPopularAssetsLocalArg)(nil), args) + return + } + ret, err = i.ListPopularAssetsLocal(ctx, typedArgs[0].SessionID) + return + }, + }, "addTrustlineLocal": { MakeArg: func() interface{} { var ret [1]AddTrustlineLocalArg @@ -3035,6 +3055,12 @@ func (c LocalClient) FuzzyAssetSearchLocal(ctx context.Context, __arg FuzzyAsset return } +func (c LocalClient) ListPopularAssetsLocal(ctx context.Context, sessionID int) (res []Asset, err error) { + __arg := ListPopularAssetsLocalArg{SessionID: sessionID} + err = c.Cli.Call(ctx, "stellar.1.local.listPopularAssetsLocal", []interface{}{__arg}, &res) + return +} + func (c LocalClient) AddTrustlineLocal(ctx context.Context, __arg AddTrustlineLocalArg) (err error) { err = c.Cli.Call(ctx, "stellar.1.local.addTrustlineLocal", []interface{}{__arg}, nil) return diff --git a/go/protocol/stellar1/remote.go b/go/protocol/stellar1/remote.go index 15df5d5bc454..0059366f6473 100644 --- a/go/protocol/stellar1/remote.go +++ b/go/protocol/stellar1/remote.go @@ -1014,6 +1014,10 @@ type FuzzyAssetSearchArg struct { SearchString string `codec:"searchString" json:"searchString"` } +type ListPopularAssetsArg struct { + Caller keybase1.UserVersion `codec:"caller" json:"caller"` +} + type ChangeTrustlineArg struct { Caller keybase1.UserVersion `codec:"caller" json:"caller"` SignedTransaction string `codec:"signedTransaction" json:"signedTransaction"` @@ -1055,6 +1059,7 @@ type RemoteInterface interface { DetailsPlusPayments(context.Context, DetailsPlusPaymentsArg) (DetailsPlusPayments, error) AssetSearch(context.Context, AssetSearchArg) ([]Asset, error) FuzzyAssetSearch(context.Context, FuzzyAssetSearchArg) ([]Asset, error) + ListPopularAssets(context.Context, keybase1.UserVersion) ([]Asset, error) ChangeTrustline(context.Context, ChangeTrustlineArg) error FindPaymentPath(context.Context, FindPaymentPathArg) (PaymentPath, error) PostAnyTransaction(context.Context, PostAnyTransactionArg) error @@ -1434,6 +1439,21 @@ func RemoteProtocol(i RemoteInterface) rpc.Protocol { return }, }, + "listPopularAssets": { + MakeArg: func() interface{} { + var ret [1]ListPopularAssetsArg + return &ret + }, + Handler: func(ctx context.Context, args interface{}) (ret interface{}, err error) { + typedArgs, ok := args.(*[1]ListPopularAssetsArg) + if !ok { + err = rpc.NewTypeError((*[1]ListPopularAssetsArg)(nil), args) + return + } + ret, err = i.ListPopularAssets(ctx, typedArgs[0].Caller) + return + }, + }, "changeTrustline": { MakeArg: func() interface{} { var ret [1]ChangeTrustlineArg @@ -1615,6 +1635,12 @@ func (c RemoteClient) FuzzyAssetSearch(ctx context.Context, __arg FuzzyAssetSear return } +func (c RemoteClient) ListPopularAssets(ctx context.Context, caller keybase1.UserVersion) (res []Asset, err error) { + __arg := ListPopularAssetsArg{Caller: caller} + err = c.Cli.Call(ctx, "stellar.1.remote.listPopularAssets", []interface{}{__arg}, &res) + return +} + func (c RemoteClient) ChangeTrustline(ctx context.Context, __arg ChangeTrustlineArg) (err error) { err = c.Cli.Call(ctx, "stellar.1.remote.changeTrustline", []interface{}{__arg}, nil) return diff --git a/go/stellar/remote/interface.go b/go/stellar/remote/interface.go index 14c0293af837..6241ed948ad6 100644 --- a/go/stellar/remote/interface.go +++ b/go/stellar/remote/interface.go @@ -49,4 +49,5 @@ type Remoter interface { FindPaymentPath(mctx libkb.MetaContext, query stellar1.PaymentPathQuery) (stellar1.PaymentPath, error) PostAnyTransaction(mctx libkb.MetaContext, signedTx string) error FuzzyAssetSearch(mctx libkb.MetaContext, arg stellar1.FuzzyAssetSearchArg) ([]stellar1.Asset, error) + ListPopularAssets(mctx libkb.MetaContext, arg stellar1.ListPopularAssetsArg) ([]stellar1.Asset, error) } diff --git a/go/stellar/remote/remote.go b/go/stellar/remote/remote.go index b31dea110ba0..29da5ee6d77b 100644 --- a/go/stellar/remote/remote.go +++ b/go/stellar/remote/remote.go @@ -1133,3 +1133,21 @@ func FuzzyAssetSearch(mctx libkb.MetaContext, arg stellar1.FuzzyAssetSearchArg) } return apiRes.Assets, nil } + +type popularAssetsResult struct { + libkb.AppStatusEmbed + Assets []stellar1.Asset `json:"assets"` +} + +func ListPopularAssets(mctx libkb.MetaContext, arg stellar1.ListPopularAssetsArg) ([]stellar1.Asset, error) { + apiArg := libkb.APIArg{ + Endpoint: "stellar/list_popular_assets", + SessionType: libkb.APISessionTypeREQUIRED, + Args: libkb.HTTPArgs{}, + } + var apiRes popularAssetsResult + if err := mctx.G().API.GetDecode(mctx, apiArg, &apiRes); err != nil { + return []stellar1.Asset{}, err + } + return apiRes.Assets, nil +} diff --git a/go/stellar/remote/remote_net.go b/go/stellar/remote/remote_net.go index a2921fc6ec15..0758d2092fe4 100644 --- a/go/stellar/remote/remote_net.go +++ b/go/stellar/remote/remote_net.go @@ -149,3 +149,7 @@ func (r *RemoteNet) PostAnyTransaction(mctx libkb.MetaContext, signedTx string) func (r *RemoteNet) FuzzyAssetSearch(mctx libkb.MetaContext, arg stellar1.FuzzyAssetSearchArg) ([]stellar1.Asset, error) { return FuzzyAssetSearch(mctx, arg) } + +func (r *RemoteNet) ListPopularAssets(mctx libkb.MetaContext, arg stellar1.ListPopularAssetsArg) ([]stellar1.Asset, error) { + return ListPopularAssets(mctx, arg) +} diff --git a/go/stellar/stellar.go b/go/stellar/stellar.go index b6864012465d..8ab790553c75 100644 --- a/go/stellar/stellar.go +++ b/go/stellar/stellar.go @@ -2327,3 +2327,7 @@ func FindPaymentPath(mctx libkb.MetaContext, remoter remote.Remoter, source stel func FuzzyAssetSearch(mctx libkb.MetaContext, remoter remote.Remoter, arg stellar1.FuzzyAssetSearchArg) ([]stellar1.Asset, error) { return remoter.FuzzyAssetSearch(mctx, arg) } + +func ListPopularAssets(mctx libkb.MetaContext, remoter remote.Remoter, arg stellar1.ListPopularAssetsArg) ([]stellar1.Asset, error) { + return remoter.ListPopularAssets(mctx, arg) +} diff --git a/go/stellar/stellarsvc/frontend.go b/go/stellar/stellarsvc/frontend.go index edf6b2d35112..cbe0f03ff39c 100644 --- a/go/stellar/stellarsvc/frontend.go +++ b/go/stellar/stellarsvc/frontend.go @@ -1236,3 +1236,18 @@ func (s *Server) FuzzyAssetSearchLocal(ctx context.Context, arg stellar1.FuzzyAs } return stellar.FuzzyAssetSearch(mctx, s.remoter, remoteArg) } + +func (s *Server) ListPopularAssetsLocal(ctx context.Context, sessionID int) (res []stellar1.Asset, err error) { + mctx, fin, err := s.Preamble(ctx, preambleArg{ + RPCName: "ListPopularAssetsLocal", + Err: &err, + RequireWallet: true, + }) + defer fin() + if err != nil { + return res, err + } + + remoteArg := stellar1.ListPopularAssetsArg{} + return stellar.ListPopularAssets(mctx, s.remoter, remoteArg) +} diff --git a/go/stellar/stellarsvc/remote_mock_test.go b/go/stellar/stellarsvc/remote_mock_test.go index 03de2b48f98e..517d00735d97 100644 --- a/go/stellar/stellarsvc/remote_mock_test.go +++ b/go/stellar/stellarsvc/remote_mock_test.go @@ -570,6 +570,10 @@ func (r *RemoteClientMock) FuzzyAssetSearch(_ libkb.MetaContext, _ stellar1.Fuzz return nil, errors.New("not mocked") } +func (r *RemoteClientMock) ListPopularAssets(_ libkb.MetaContext, _ stellar1.ListPopularAssetsArg) ([]stellar1.Asset, error) { + return nil, errors.New("not mocked") +} + func (r *RemoteClientMock) PostAnyTransaction(_ libkb.MetaContext, _ string) error { return errors.New("post any transaction is not mocked") } diff --git a/go/systests/stellar_client_test.go b/go/systests/stellar_client_test.go index b30526c5d7b5..35066005dc06 100644 --- a/go/systests/stellar_client_test.go +++ b/go/systests/stellar_client_test.go @@ -732,4 +732,8 @@ func (s *stellarRetryClient) FuzzyAssetSearchLocal(ctx context.Context, arg stel return s.cli.FuzzyAssetSearchLocal(ctx, arg) } +func (s *stellarRetryClient) ListPopularAssetsLocal(ctx context.Context, sessionID int) (res []stellar1.Asset, err error) { + return s.cli.ListPopularAssetsLocal(ctx, sessionID) +} + var _ stellar1.LocalInterface = (*stellarRetryClient)(nil) diff --git a/protocol/avdl/stellar1/local.avdl b/protocol/avdl/stellar1/local.avdl index 5655538a3843..4b9db97fdafb 100644 --- a/protocol/avdl/stellar1/local.avdl +++ b/protocol/avdl/stellar1/local.avdl @@ -546,6 +546,7 @@ protocol local { // search by user search string array fuzzyAssetSearchLocal(int sessionID, string searchString); + array listPopularAssetsLocal(int sessionID); // Trustline operations: // In addTrustline, limit is optional, if not supplied, max limit will be used. diff --git a/protocol/avdl/stellar1/remote.avdl b/protocol/avdl/stellar1/remote.avdl index 4f80367ad584..d74a43215c72 100644 --- a/protocol/avdl/stellar1/remote.avdl +++ b/protocol/avdl/stellar1/remote.avdl @@ -325,6 +325,7 @@ protocol remote { array assetSearch(string assetCode, string issuerAccountID); // search by user search string array fuzzyAssetSearch(keybase1.UserVersion caller, string searchString); + array listPopularAssets(keybase1.UserVersion caller); void changeTrustline(keybase1.UserVersion caller, string signedTransaction); diff --git a/protocol/json/stellar1/local.json b/protocol/json/stellar1/local.json index b4d5d27a6975..778533622606 100644 --- a/protocol/json/stellar1/local.json +++ b/protocol/json/stellar1/local.json @@ -2205,6 +2205,18 @@ "items": "Asset" } }, + "listPopularAssetsLocal": { + "request": [ + { + "name": "sessionID", + "type": "int" + } + ], + "response": { + "type": "array", + "items": "Asset" + } + }, "addTrustlineLocal": { "request": [ { diff --git a/protocol/json/stellar1/remote.json b/protocol/json/stellar1/remote.json index 826e0c7f2b9a..98e260bae7cf 100644 --- a/protocol/json/stellar1/remote.json +++ b/protocol/json/stellar1/remote.json @@ -1302,6 +1302,18 @@ "items": "Asset" } }, + "listPopularAssets": { + "request": [ + { + "name": "caller", + "type": "keybase1.UserVersion" + } + ], + "response": { + "type": "array", + "items": "Asset" + } + }, "changeTrustline": { "request": [ { diff --git a/shared/constants/types/rpc-stellar-gen.tsx b/shared/constants/types/rpc-stellar-gen.tsx index 8e47fca931fd..a0ce15d09ed6 100644 --- a/shared/constants/types/rpc-stellar-gen.tsx +++ b/shared/constants/types/rpc-stellar-gen.tsx @@ -471,6 +471,7 @@ export const localValidateSecretKeyLocalRpcPromise = (params: MessageTypes['stel // 'stellar.1.local.sendPathLocal' // 'stellar.1.local.getRequestDetailsLocal' // 'stellar.1.local.fuzzyAssetSearchLocal' +// 'stellar.1.local.listPopularAssetsLocal' // 'stellar.1.local.addTrustlineLocal' // 'stellar.1.local.deleteTrustlineLocal' // 'stellar.1.local.changeTrustlineLimitLocal' @@ -532,6 +533,7 @@ export const localValidateSecretKeyLocalRpcPromise = (params: MessageTypes['stel // 'stellar.1.remote.detailsPlusPayments' // 'stellar.1.remote.assetSearch' // 'stellar.1.remote.fuzzyAssetSearch' +// 'stellar.1.remote.listPopularAssets' // 'stellar.1.remote.changeTrustline' // 'stellar.1.remote.findPaymentPath' // 'stellar.1.remote.postAnyTransaction'