From 9acbeb3da36b80aa831a6f147924a42b609b83ad Mon Sep 17 00:00:00 2001 From: superzordon Date: Fri, 1 Jul 2022 14:52:55 -0500 Subject: [PATCH 1/2] Create get-hodlers-for-public-key --- routes/user.go | 129 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 108 insertions(+), 21 deletions(-) diff --git a/routes/user.go b/routes/user.go index 6ebab6ba..f3571f8d 100644 --- a/routes/user.go +++ b/routes/user.go @@ -1305,11 +1305,36 @@ type GetHodlersForPublicKeyRequest struct { FetchAll bool } + type GetHodlersForPublicKeyResponse struct { Hodlers []*BalanceEntryResponse LastPublicKeyBase58Check string } +type GetHodlersForPublicKeysRequest struct { + // Array of Public Keys to retrieve hodlers for. + PublicKeysBase58Check []string `safeForLogging:"true"` + + // If true, fetch DAO coin balance entries instead of creator coin balance entries. + IsDAOCoin bool `safeForLogging:"true"` + + // If true, fetch balance entries for your hodlings instead of balance entries for hodler's of your coin. + FetchHodlings bool + + // The sorting method to use when returning profiles. Defaults to + // "coin_balance" when unset. + SortType TopHodlerSortType +} + +type GetHodlersForPublicKeysSingleResponse struct { + Hodlers []*BalanceEntryResponse + PublicKeyBase58Check string +} + +type GetHodlersForPublicKeysResponse struct { + HodlersForPublicKeys []*GetHodlersForPublicKeysSingleResponse +} + // Helper function to get the creator public key or the hodler public key depending upon fetchHodlings. func getHodlerOrHodlingPublicKey(balanceEntryResponse *BalanceEntryResponse, fetchHodlings bool) (_publicKeyBase58Check string) { if fetchHodlings { @@ -1336,7 +1361,7 @@ func (fes *APIServer) ComputeWealth( } // GetHodlersForPublicKey... Get BalanceEntryResponses for hodlings. -func (fes *APIServer) GetHodlersForPublicKey(ww http.ResponseWriter, req *http.Request) { +func (fes *APIServer) GetHodlersForPublicKeyEndpoint(ww http.ResponseWriter, req *http.Request) { decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) requestData := GetHodlersForPublicKeyRequest{} if err := decoder.Decode(&requestData); err != nil { @@ -1352,13 +1377,88 @@ func (fes *APIServer) GetHodlersForPublicKey(ww http.ResponseWriter, req *http.R return } + res, err := fes.GetHodlersForPublicKey(&requestData, utxoView) + + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetHodlersForPublicKeyEndpoint: Problem getting hodlers for public key: %v", err)) + return + } + + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetHodlersForPublicKeyEndpoint: Problem encoding response as JSON: %v", err)) + return + } + +} + +func (fes *APIServer) GetHodlersForPublicKeysEndpoint(ww http.ResponseWriter, req *http.Request) { + decoder := json.NewDecoder(io.LimitReader(req.Body, MaxRequestBodySizeBytes)) + requestData := GetHodlersForPublicKeysRequest{} + if err := decoder.Decode(&requestData); err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetHodlersForPublicKey: Problem parsing request body: %v", err)) + return + } + + // Get a view + utxoView, err := fes.backendServer.GetMempool().GetAugmentedUniversalView() + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf("GetHodlersForPublicKey: Error getting utxoView: %v", err)) + return + } + + if len(requestData.PublicKeysBase58Check) == 0 { + _AddBadRequestError(ww, fmt.Sprintf( + "GetHodlersForPublicKeysEndpoint: Must provide at least one public key.")) + return + } + + var hodlersForPublicKeys []*GetHodlersForPublicKeysSingleResponse + + for _, publicKey := range(requestData.PublicKeysBase58Check) { + publicKeyRequestData := &GetHodlersForPublicKeyRequest{ + PublicKeyBase58Check: publicKey, + IsDAOCoin: requestData.IsDAOCoin, + FetchHodlings: requestData.FetchHodlings, + SortType: requestData.SortType, + FetchAll: true, + } + res, err := fes.GetHodlersForPublicKey(publicKeyRequestData, utxoView) + if err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetHodlersForPublicKeyEndpoint: Problem getting hodlers for public key: %v", err)) + return + } + hodlersForPublicKey := &GetHodlersForPublicKeysSingleResponse{ + Hodlers: res.Hodlers, + PublicKeyBase58Check: publicKey, + } + hodlersForPublicKeys = append(hodlersForPublicKeys, hodlersForPublicKey) + } + + res := &GetHodlersForPublicKeysResponse{ + HodlersForPublicKeys: hodlersForPublicKeys, + } + + if err = json.NewEncoder(ww).Encode(res); err != nil { + _AddBadRequestError(ww, fmt.Sprintf( + "GetHodlersForPublicKeyEndpoint: Problem encoding response as JSON: %v", err)) + return + } + +} + +// GetHodlersForPublicKey... Get BalanceEntryResponses for hodlings. +func (fes *APIServer) GetHodlersForPublicKey(requestData *GetHodlersForPublicKeyRequest, utxoView *lib.UtxoView) (*GetHodlersForPublicKeyResponse, error) { // Decode the public key for which we are fetching hodlers / hodlings. If public key is not provided, use username var publicKeyBytes []byte + var err error if requestData.PublicKeyBase58Check != "" { publicKeyBytes, _, err = lib.Base58CheckDecode(requestData.PublicKeyBase58Check) if err != nil { - _AddBadRequestError(ww, fmt.Sprintf("GetHodlersForPublicKey: Problem decoding user public key: %v", err)) - return + return nil, fmt.Errorf("GetHodlersForPublicKey: Problem decoding user public key: %v", err) } } else { username := requestData.Username @@ -1366,8 +1466,7 @@ func (fes *APIServer) GetHodlersForPublicKey(ww http.ResponseWriter, req *http.R // Return an error if we failed to find a profile entry if profileEntry == nil { - _AddNotFoundError(ww, fmt.Sprintf("GetHodlersForPublicKey: could not find profile for username: %v", username)) - return + return nil, fmt.Errorf("GetHodlersForPublicKey: could not find profile for username: %v", username) } publicKeyBytes = profileEntry.PublicKey } @@ -1379,16 +1478,14 @@ func (fes *APIServer) GetHodlersForPublicKey(ww http.ResponseWriter, req *http.R hodlMap, err = fes.GetYouHodlMap( utxoView.GetPKIDForPublicKey(publicKeyBytes), false, requestData.IsDAOCoin, utxoView) if err != nil { - _AddBadRequestError(ww, fmt.Sprintf("GetHodlersForPublicKey: error getting youHodlMap: %v", err)) - return + return nil, fmt.Errorf("GetHodlersForPublicKey: error getting youHodlMap: %v", err) } } else { hodlMap, err = fes.GetHodlYouMap( utxoView.GetPKIDForPublicKey(publicKeyBytes), false, requestData.IsDAOCoin, utxoView) if err != nil { - _AddBadRequestError(ww, fmt.Sprintf("GetHodlersForPublicKey: error getting youHodlMap: %v", err)) - return + return nil, fmt.Errorf("GetHodlersForPublicKey: error getting youHodlMap: %v", err) } } for _, balanceEntryResponse := range hodlMap { @@ -1399,10 +1496,7 @@ func (fes *APIServer) GetHodlersForPublicKey(ww http.ResponseWriter, req *http.R if requestData.SortType != TopHodlerSortTypeNone && requestData.SortType != TopHodlerSortTypeCoinBalance && requestData.SortType != TopHodlerSortTypeWealth { - - _AddBadRequestError(ww, fmt.Sprintf("GetHodlersForPublicKey: Unrecognized "+ - "sort type: %v", requestData.SortType)) - return + return nil, fmt.Errorf("GetHodlersForPublicKey: Unrecognized sort type: %v", requestData.SortType) } sort.Slice(hodlList, func(ii, jj int) bool { if hodlList[ii].CreatorPublicKeyBase58Check == hodlList[ii].HODLerPublicKeyBase58Check { @@ -1426,9 +1520,6 @@ func (fes *APIServer) GetHodlersForPublicKey(ww http.ResponseWriter, req *http.R jjWealth := fes.ComputeWealth(hodlList[jj], utxoView) return iiWealth > jjWealth } else { - _AddBadRequestError(ww, fmt.Sprintf("GetHodlersForPublicKey: Unrecognized "+ - "sort type: %v", requestData.SortType)) - // TODO: We can't break the execution here but we should return false } }) @@ -1470,11 +1561,7 @@ func (fes *APIServer) GetHodlersForPublicKey(ww http.ResponseWriter, req *http.R Hodlers: hodlList, LastPublicKeyBase58Check: resLastPublicKey, } - if err = json.NewEncoder(ww).Encode(res); err != nil { - _AddBadRequestError(ww, fmt.Sprintf( - "GetHodlersForPublicKey: Problem encoding response as JSON: %v", err)) - return - } + return res, nil } type GetHolderCountForPublicKeysRequest struct { From 1695d6f0173dd7d16cff1214cb811bf510c672a4 Mon Sep 17 00:00:00 2001 From: superzordon Date: Fri, 1 Jul 2022 14:58:05 -0500 Subject: [PATCH 2/2] Add endpoints --- routes/server.go | 10 +++++++++- routes/user.go | 17 ++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/routes/server.go b/routes/server.go index ee64758f..d85e9ffd 100644 --- a/routes/server.go +++ b/routes/server.go @@ -72,6 +72,7 @@ const ( RoutePathGetSingleProfile = "/api/v0/get-single-profile" RoutePathGetSingleProfilePicture = "/api/v0/get-single-profile-picture" RoutePathGetHodlersForPublicKey = "/api/v0/get-hodlers-for-public-key" + RoutePathGetHodlersForPublicKeys = "/api/v0/get-hodlers-for-public-keys" RoutePathGetHodlersCountForPublicKeys = "/api/v0/get-hodlers-count-for-public-keys" RoutePathGetDiamondsForPublicKey = "/api/v0/get-diamonds-for-public-key" RoutePathGetFollowsStateless = "/api/v0/get-follows-stateless" @@ -824,7 +825,14 @@ func (fes *APIServer) NewRouter() *muxtrace.Router { "GetHodlersForPublicKey", []string{"POST", "OPTIONS"}, RoutePathGetHodlersForPublicKey, - fes.GetHodlersForPublicKey, + fes.GetHodlersForPublicKeyEndpoint, + PublicAccess, + }, + { + "GetHodlersForPublicKeys", + []string{"POST", "OPTIONS"}, + RoutePathGetHodlersForPublicKeys, + fes.GetHodlersForPublicKeysEndpoint, PublicAccess, }, { diff --git a/routes/user.go b/routes/user.go index f3571f8d..b3cdce6a 100644 --- a/routes/user.go +++ b/routes/user.go @@ -1305,7 +1305,6 @@ type GetHodlersForPublicKeyRequest struct { FetchAll bool } - type GetHodlersForPublicKeyResponse struct { Hodlers []*BalanceEntryResponse LastPublicKeyBase58Check string @@ -1327,12 +1326,12 @@ type GetHodlersForPublicKeysRequest struct { } type GetHodlersForPublicKeysSingleResponse struct { - Hodlers []*BalanceEntryResponse + Hodlers []*BalanceEntryResponse PublicKeyBase58Check string } type GetHodlersForPublicKeysResponse struct { - HodlersForPublicKeys []*GetHodlersForPublicKeysSingleResponse + HodlersForPublicKeys []*GetHodlersForPublicKeysSingleResponse } // Helper function to get the creator public key or the hodler public key depending upon fetchHodlings. @@ -1417,13 +1416,13 @@ func (fes *APIServer) GetHodlersForPublicKeysEndpoint(ww http.ResponseWriter, re var hodlersForPublicKeys []*GetHodlersForPublicKeysSingleResponse - for _, publicKey := range(requestData.PublicKeysBase58Check) { + for _, publicKey := range requestData.PublicKeysBase58Check { publicKeyRequestData := &GetHodlersForPublicKeyRequest{ - PublicKeyBase58Check: publicKey, - IsDAOCoin: requestData.IsDAOCoin, - FetchHodlings: requestData.FetchHodlings, - SortType: requestData.SortType, - FetchAll: true, + PublicKeyBase58Check: publicKey, + IsDAOCoin: requestData.IsDAOCoin, + FetchHodlings: requestData.FetchHodlings, + SortType: requestData.SortType, + FetchAll: true, } res, err := fes.GetHodlersForPublicKey(publicKeyRequestData, utxoView) if err != nil {