From d795db61a871fb262991dbe3ee97b711b153797a Mon Sep 17 00:00:00 2001 From: Sunny Dasgupta Date: Mon, 24 Jul 2023 16:13:02 +0100 Subject: [PATCH 1/5] Pnl leaderboard of pubkeys --- leaderboard/sort_by_positions_pubkeys.go | 232 +++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 leaderboard/sort_by_positions_pubkeys.go diff --git a/leaderboard/sort_by_positions_pubkeys.go b/leaderboard/sort_by_positions_pubkeys.go new file mode 100644 index 0000000..a933458 --- /dev/null +++ b/leaderboard/sort_by_positions_pubkeys.go @@ -0,0 +1,232 @@ +package leaderboard + +import ( + "context" + "fmt" + "math" + "sort" + "strconv" + "time" + + log "github.com/sirupsen/logrus" + "github.com/vegaprotocol/topgun-service/verifier" +) + +var gqlQueryPartiesAccountsPositionsPubkeys string = `query ($pagination: Pagination!) { + partiesConnection(pagination: $pagination) { + edges { + node { + id + positionsConnection { + edges { + node { + market { + id + } + openVolume + realisedPNL + averageEntryPrice + unrealisedPNL + realisedPNL + } + } + } + transfersConnection(direction: To) { + edges { + node { + id + fromAccountType + toAccountType + from + amount + timestamp + asset { + id + name + } + } + } + } + depositsConnection { + edges { + node { + amount + createdTimestamp + creditedTimestamp + status + asset { + id + symbol + source { + __typename + } + } + } + } + } + } + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + }` + +func (s *Service) sortByPartyPositionsPubkeys(socials map[string]verifier.Social) ([]Participant, error) { + + // Grab the DP we're targeting (for the asset we're interested in for the market specified + decimalPlacesStr, err := s.getAlgorithmConfig("decimalPlaces") + if err != nil { + return nil, fmt.Errorf("failed to get algorithm config: %s", err) + } + decimalPlaces, err := strconv.ParseFloat(decimalPlacesStr, 64) + if err != nil { + return nil, fmt.Errorf("failed to get algorithm config: %s", err) + } + + pagination := Pagination{First: 50} + + ctx := context.Background() + partyEdges := []PartiesEdge{} + for { + connection, err := getPartiesConnection( + ctx, + s.cfg.VegaGraphQLURL.String(), + gqlQueryPartiesAccountsMakerReceived, + map[string]interface{}{"pagination": pagination}, + nil, + ) + if err != nil { + return nil, fmt.Errorf("failed to get list of parties in loop: %w", err) + } + + partyEdges = append(partyEdges, connection.Edges...) + + // fmt.Println("got ", len(partyEdges), "end?", connection.PageInfo.EndCursor) + + if !connection.PageInfo.NextPage { + // fmt.Println("done") + break + } else { + pagination.After = connection.PageInfo.EndCursor + } + + } + participants := []Participant{} + // if participant in JSON, PNL = json data, otherwise starting PnL 0 + for _, party := range partyEdges { + transfer := 1000.0 + deposit := 0.0 + if len(party.Party.TransfersConnection.Edges) != 0 { + for _, w := range party.Party.TransfersConnection.Edges { + if err != nil { + fmt.Errorf("failed to convert Transfer amount to string", err) + } + if w.Transfer.Asset.Id == s.cfg.VegaAssets[0] && + w.Transfer.Timestamp.After(s.cfg.StartTime) && + w.Transfer.Timestamp.Before(s.cfg.EndTime) { + transfer, err = strconv.ParseFloat(w.Transfer.Amount, 64) + } + } + } + + for _, d := range party.Party.DepositsConnection.Edges { + if err != nil { + fmt.Errorf("failed to convert Withdrawal amount to string", err) + } + + if d.Deposit.Asset.Id == s.cfg.VegaAssets[0] && + d.Deposit.Status == "STATUS_FINALIZED" && + d.Deposit.CreatedAt.After(s.cfg.StartTime) && + d.Deposit.CreatedAt.Before(s.cfg.EndTime) { + deposit, err = strconv.ParseFloat(d.Deposit.Amount, 64) + } + } + PnL := 0.0 + realisedPnL := 0.0 + unrealisedPnL := 0.0 + openVolume := 0.0 + dataFormatted := "" + if err == nil { + for _, acc := range party.Party.PositionsConnection.Edges { + for _, marketID := range s.cfg.MarketIDs { + if acc.Position.Market.ID == marketID { + if s, err := strconv.ParseFloat(acc.Position.RealisedPNL, 32); err == nil { + realisedPnL += s + } + if t, err := strconv.ParseFloat(acc.Position.UnrealisedPNL, 32); err == nil { + unrealisedPnL += t + } + if u, err := strconv.ParseFloat(acc.Position.OpenVolume, 32); err == nil { + openVolume += u + } + PnL = (realisedPnL + unrealisedPnL) - transfer - deposit + dataFormatted = strconv.FormatFloat(PnL, 'f', 10, 32) + } + } + + } + } + + if (realisedPnL != 0.0) || (unrealisedPnL != 0.0) || (openVolume != 0.0) { + if party.Party.blacklisted { + log.Infof("Blacklisted party added: %s", party.Party.ID) + } + + pubkeyBlacklist := []string{"93e8077e3c0a942bd5469b3b142ffe643f4d9c5d9962a862de419bfc5f8bfeb9", + "4af3e8fe168095cc20c9232f7b4723645a59c6717eb4e9d2121378c6002fb4bb", + "ad0549439a1c15ebffc2ff406451eec560facfabe762b3a5401e3d20d384d5b3", + "19e675aa6a7747ee504e31adc660aa9df4213a8ca9d1243e4a30d0974dac3705", + "45c231260e56ba839f8cc0a4ccec16a209965f6534887ff19c3bfc9242bfc844", + "fdab1c1c9db496f651d922e3b056a4736e3a3b0ee301cb20afa491f3656939d8", + "1d2247dff85b9396d46545cb959e3b5c5925dd77e193ba873f01f4079481f67b", + "937802822f779d3d14b280ffdabcd2935c8b7c708a6ca53b8c05230827c8a960", + "86ff2c3b45be7c43202d1dc370779d070faaba1029094c46174857f1b445673f", + "51351917f4400efe8ecdd1ecc726d174bbd87c991dc0795863cadd586b4e3865", + "2aaeeeec54b72fcf69d89b2f5960dea1b9bca2cc71a61f421502a80fff32c139", + "022a129df7f8360c9de598e8d0eeb06c62c9f63393b25024af89cd5bfb1c6207", + "09a576a282cbafe3b37673949f7d563118222d4fbfa3df7879727667d4970577", + "0b8519bb08e11dac3ab1073f4fc8cd0ff02e5b751d14c5e624c26bf65c7aaf92", + "feae764c6615a4e9c0170a500e1d51d312b4b8e50bd59fa825843025bff4fe02", + "4a9b97bd45af1a9d744462edcb67a249165065984667914db2d2167a0d45221d", + "82507ccb7b6380dc36eae68bdbc5495d2b9126ce00f49bce911f6ad6a0c1359d", + "c810aa6c86b3c367248cc41277970cf97ef95568451338d72972a41fddd079a2", + "edae7973f562cd232ff15094509655b4d31c6d7fd5f8a45db5965572e65c4d54"} + + for _, pubkey := range pubkeyBlacklist { + if pubkey == party.Party.ID { + party.Party.blacklisted = true + } + } + + t := time.Now().UTC() + if PnL != 0 { + dpMultiplier := math.Pow(10, decimalPlaces) + total := PnL / dpMultiplier + dataFormatted = strconv.FormatFloat(total, 'f', 10, 32) + } + + if party.Party.blacklisted == false { + participants = append(participants, Participant{ + PublicKey: party.Party.ID, + Data: []string{dataFormatted}, + sortNum: PnL, + CreatedAt: t, + UpdatedAt: t, + isBlacklisted: party.Party.blacklisted, + }) + } + + } + } + + sortFunc := func(i, j int) bool { + return participants[i].sortNum > participants[j].sortNum + } + sort.Slice(participants, sortFunc) + + return participants, nil +} From 3406282984f2faad1ab4990933e9ec0016fa67ab Mon Sep 17 00:00:00 2001 From: Sunny Dasgupta Date: Tue, 25 Jul 2023 11:17:29 +0100 Subject: [PATCH 2/5] New algo added to service.go --- leaderboard/service.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/leaderboard/service.go b/leaderboard/service.go index 0c6f9de..efd007a 100644 --- a/leaderboard/service.go +++ b/leaderboard/service.go @@ -207,6 +207,8 @@ func (s *Service) update() { p, err = s.sortByPartyRewardsMakerReceived(socials) case "ByPartyRewardsMakerReceivedPubkeys": p, err = s.sortByPartyRewardsMakerReceivedPubkeys(socials) + case "ByPartyPositionsPubkeys": + p, err = s.sortByPartyPositionsPubkeys(socials) default: err = fmt.Errorf("invalid algorithm: %s", s.cfg.Algorithm) } From 5d81a08b34401d5b8ab0ae429e92c36eab00a564 Mon Sep 17 00:00:00 2001 From: Sunny Dasgupta Date: Tue, 25 Jul 2023 11:18:21 +0100 Subject: [PATCH 3/5] Changing algo name in script --- leaderboard/sort_by_positions_pubkeys.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leaderboard/sort_by_positions_pubkeys.go b/leaderboard/sort_by_positions_pubkeys.go index a933458..2864ea5 100644 --- a/leaderboard/sort_by_positions_pubkeys.go +++ b/leaderboard/sort_by_positions_pubkeys.go @@ -12,7 +12,7 @@ import ( "github.com/vegaprotocol/topgun-service/verifier" ) -var gqlQueryPartiesAccountsPositionsPubkeys string = `query ($pagination: Pagination!) { +var gqlQueryPartiesPositionsPubkeys string = `query ($pagination: Pagination!) { partiesConnection(pagination: $pagination) { edges { node { @@ -95,7 +95,7 @@ func (s *Service) sortByPartyPositionsPubkeys(socials map[string]verifier.Social connection, err := getPartiesConnection( ctx, s.cfg.VegaGraphQLURL.String(), - gqlQueryPartiesAccountsMakerReceived, + gqlQueryPartiesPositionsPubkeys, map[string]interface{}{"pagination": pagination}, nil, ) From e5b6004d733d12c00ebbfee0ac672d5dbf474c1b Mon Sep 17 00:00:00 2001 From: Sunny Dasgupta Date: Tue, 25 Jul 2023 11:38:14 +0100 Subject: [PATCH 4/5] Deposit withdrawal algo --- .../sort_by_deposit_withdrawal_pubkeys.go | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 leaderboard/sort_by_deposit_withdrawal_pubkeys.go diff --git a/leaderboard/sort_by_deposit_withdrawal_pubkeys.go b/leaderboard/sort_by_deposit_withdrawal_pubkeys.go new file mode 100644 index 0000000..fba2404 --- /dev/null +++ b/leaderboard/sort_by_deposit_withdrawal_pubkeys.go @@ -0,0 +1,224 @@ +package leaderboard + +import ( + "context" + "fmt" + "sort" + "strconv" + "time" + + log "github.com/sirupsen/logrus" + "github.com/vegaprotocol/topgun-service/verifier" +) + +var gqlQueryPartiesDepositWithdrawalPubkeys string = `query ($pagination: Pagination!) { + partiesConnection(pagination: $pagination) { + edges { + node { + id + positionsConnection { + edges { + node { + market { + id + } + openVolume + realisedPNL + averageEntryPrice + unrealisedPNL + realisedPNL + } + } + } + withdrawalsConnection { + edges { + node { + amount + createdTimestamp + createdTimestamp + status + asset { + id + symbol + source { + __typename + } + } + } + } + } + depositsConnection { + edges { + node { + amount + createdTimestamp + creditedTimestamp + status + asset { + id + symbol + source { + __typename + } + } + } + } + } + } + } + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + } + }` + +func (s *Service) sortByPartyDepositWithdrawalPubkeys(socials map[string]verifier.Social) ([]Participant, error) { + + // Grab the DP we're targeting (for the asset we're interested in for the market specified + decimalPlacesStr, err := s.getAlgorithmConfig("decimalPlaces") + if err != nil { + return nil, fmt.Errorf("failed to get algorithm config: %s", err) + } + decimalPlaces, err := strconv.ParseFloat(decimalPlacesStr, 64) + if err != nil { + return nil, fmt.Errorf("failed to get algorithm config: %s", err) + } + + pagination := Pagination{First: 50} + + ctx := context.Background() + partyEdges := []PartiesEdge{} + for { + connection, err := getPartiesConnection( + ctx, + s.cfg.VegaGraphQLURL.String(), + gqlQueryPartiesDepositWithdrawalPubkeys, + map[string]interface{}{"pagination": pagination}, + nil, + ) + if err != nil { + return nil, fmt.Errorf("failed to get list of parties in loop: %w", err) + } + + partyEdges = append(partyEdges, connection.Edges...) + + // fmt.Println("got ", len(partyEdges), "end?", connection.PageInfo.EndCursor) + + if !connection.PageInfo.NextPage { + // fmt.Println("done") + break + } else { + pagination.After = connection.PageInfo.EndCursor + } + + } + participants := []Participant{} + // if participant in JSON, PNL = json data, otherwise starting PnL 0 + for _, party := range partyEdges { + withdrawal := 0.0 + deposit := 0.0 + if len(party.Party.WithdrawalsConnection.Edges) != 0 { + for _, w := range party.Party.WithdrawalsConnection.Edges { + if err != nil { + fmt.Errorf("failed to convert Transfer amount to string", err) + } + if w.Withdrawal.Asset.Id == s.cfg.VegaAssets[0] && + w.Withdrawal.CreatedAt.After(s.cfg.StartTime) && + w.Withdrawal.CreatedAt.Before(s.cfg.EndTime) { + withdrawal, err = strconv.ParseFloat(w.Withdrawal.Amount, 64) + } + } + } + + for _, d := range party.Party.DepositsConnection.Edges { + if err != nil { + fmt.Errorf("failed to convert Withdrawal amount to string", err) + } + + if d.Deposit.Asset.Id == s.cfg.VegaAssets[0] && + d.Deposit.Status == "STATUS_FINALIZED" && + d.Deposit.CreatedAt.After(s.cfg.StartTime) && + d.Deposit.CreatedAt.Before(s.cfg.EndTime) { + deposit, err = strconv.ParseFloat(d.Deposit.Amount, 64) + } + } + PnL := 0.0 + realisedPnL := 0.0 + unrealisedPnL := 0.0 + openVolume := 0.0 + if err == nil { + for _, acc := range party.Party.PositionsConnection.Edges { + for _, marketID := range s.cfg.MarketIDs { + if acc.Position.Market.ID == marketID { + if s, err := strconv.ParseFloat(acc.Position.RealisedPNL, 32); err == nil { + realisedPnL += s + } + if t, err := strconv.ParseFloat(acc.Position.UnrealisedPNL, 32); err == nil { + unrealisedPnL += t + } + if u, err := strconv.ParseFloat(acc.Position.OpenVolume, 32); err == nil { + openVolume += u + } + PnL = (realisedPnL + unrealisedPnL) / decimalPlaces + } + } + + } + } + + if (withdrawal != 0.0) && (deposit != 0.0) && (PnL != 0.0) { + if party.Party.blacklisted { + log.Infof("Blacklisted party added: %s", party.Party.ID) + } + + pubkeyBlacklist := []string{"93e8077e3c0a942bd5469b3b142ffe643f4d9c5d9962a862de419bfc5f8bfeb9", + "4af3e8fe168095cc20c9232f7b4723645a59c6717eb4e9d2121378c6002fb4bb", + "ad0549439a1c15ebffc2ff406451eec560facfabe762b3a5401e3d20d384d5b3", + "19e675aa6a7747ee504e31adc660aa9df4213a8ca9d1243e4a30d0974dac3705", + "45c231260e56ba839f8cc0a4ccec16a209965f6534887ff19c3bfc9242bfc844", + "fdab1c1c9db496f651d922e3b056a4736e3a3b0ee301cb20afa491f3656939d8", + "1d2247dff85b9396d46545cb959e3b5c5925dd77e193ba873f01f4079481f67b", + "937802822f779d3d14b280ffdabcd2935c8b7c708a6ca53b8c05230827c8a960", + "86ff2c3b45be7c43202d1dc370779d070faaba1029094c46174857f1b445673f", + "51351917f4400efe8ecdd1ecc726d174bbd87c991dc0795863cadd586b4e3865", + "2aaeeeec54b72fcf69d89b2f5960dea1b9bca2cc71a61f421502a80fff32c139", + "022a129df7f8360c9de598e8d0eeb06c62c9f63393b25024af89cd5bfb1c6207", + "09a576a282cbafe3b37673949f7d563118222d4fbfa3df7879727667d4970577", + "0b8519bb08e11dac3ab1073f4fc8cd0ff02e5b751d14c5e624c26bf65c7aaf92", + "feae764c6615a4e9c0170a500e1d51d312b4b8e50bd59fa825843025bff4fe02", + "4a9b97bd45af1a9d744462edcb67a249165065984667914db2d2167a0d45221d", + "82507ccb7b6380dc36eae68bdbc5495d2b9126ce00f49bce911f6ad6a0c1359d", + "c810aa6c86b3c367248cc41277970cf97ef95568451338d72972a41fddd079a2", + "edae7973f562cd232ff15094509655b4d31c6d7fd5f8a45db5965572e65c4d54"} + + for _, pubkey := range pubkeyBlacklist { + if pubkey == party.Party.ID { + party.Party.blacklisted = true + } + } + + t := time.Now().UTC() + if party.Party.blacklisted == false { + participants = append(participants, Participant{ + PublicKey: party.Party.ID, + Data: []string{"Completed"}, + sortNum: PnL, + CreatedAt: t, + UpdatedAt: t, + isBlacklisted: party.Party.blacklisted, + }) + } + + } + } + + sortFunc := func(i, j int) bool { + return participants[i].sortNum > participants[j].sortNum + } + sort.Slice(participants, sortFunc) + + return participants, nil +} From 70e9b2999e0805bcbc33d6c6900e87e7d929cb5f Mon Sep 17 00:00:00 2001 From: Sunny Dasgupta Date: Tue, 25 Jul 2023 11:50:24 +0100 Subject: [PATCH 5/5] added to service.go --- leaderboard/service.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/leaderboard/service.go b/leaderboard/service.go index efd007a..00f11d6 100644 --- a/leaderboard/service.go +++ b/leaderboard/service.go @@ -209,6 +209,8 @@ func (s *Service) update() { p, err = s.sortByPartyRewardsMakerReceivedPubkeys(socials) case "ByPartyPositionsPubkeys": p, err = s.sortByPartyPositionsPubkeys(socials) + case "ByPartyDepositWithdrawalPubkeys": + p, err = s.sortByPartyDepositWithdrawalPubkeys(socials) default: err = fmt.Errorf("invalid algorithm: %s", s.cfg.Algorithm) }