diff --git a/docs/swagger.yaml b/docs/swagger.yaml index fd055b3..05ca3d5 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -759,6 +759,8 @@ components: - lifeTimeUsdDeposit - lifeTimeUsdWithdrawal - lifeTimeUsdVolume + - activeWallets + - uniqueDepositors properties: usdTvl: type: string @@ -772,6 +774,12 @@ components: lifeTimeUsdVolume: type: string description: A float 64 string for life time volume (normalized to the current usd price of assets). + activeWallets: + type: number + description: Number of wallets with active postions. + uniqueDepositors: + type: number + description: Total number of unique depositors. # DATA MODELS diff --git a/pkg/api/apispec/generated.go b/pkg/api/apispec/generated.go index 235e045..9c4c4fa 100644 --- a/pkg/api/apispec/generated.go +++ b/pkg/api/apispec/generated.go @@ -30,6 +30,9 @@ type ActiveWallet struct { // AnalyticsOverviewResponse defines model for analyticsOverviewResponse. type AnalyticsOverviewResponse struct { + // Number of wallets with active postions. + ActiveWallets float32 `json:"activeWallets"` + // A float 64 string for life time deposits (normalized to the current usd price of assets). LifeTimeUsdDeposit string `json:"lifeTimeUsdDeposit"` @@ -39,6 +42,9 @@ type AnalyticsOverviewResponse struct { // A float 64 string for life time withdrawals (normalized to the current usd price of assets). LifeTimeUsdWithdrawal string `json:"lifeTimeUsdWithdrawal"` + // Total number of unique depositors. + UniqueDepositors float32 `json:"uniqueDepositors"` + // A float 64 string for the current tvl in USD. UsdTvl string `json:"usdTvl"` } @@ -4026,73 +4032,74 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "H4sIAAAAAAAC/+x8aXPiOLf/V1H5/6+amSqeJKyBfnUhgdBhabaQhHm6bglbBoE3JJltKt/9luUF28hg", - "upN+5s7Nm5kOls45OvqdTTr2X5Js6pZpIINR6ctfkgUJ1BFDhP+FDDjVkNK3Edn1nCfOj9iQvkgr5ycp", - "IxlQR9IXf6CUkag8Rzp0xrGd5TyamqaGoCG9vWUktLWgoVQVHRs9k2KGTYOmIM5nRWhjhnRPQluXvvwp", - "QU2TMtIa2hqTMpJFTGbemYaKZ1JGYuYSGVX/HzXpe8aXjTKCjZn0FvwACYG7uKhjh+q7yhmSbww1GwVC", - "drDBIr/Ujn6pVmXZtOPD4j8SBKlNdqPjh6lWPzPNmYb47K9KE0EFkejS5/y3w9q5FP/CzuoJWtmYIEX6", - "woiNBIjw+b5lJEzvNJOmQZg/8hzENKxjdp4cHyaihQ2GZohwWqaqUpSCmDvuLLWNgUgKYs4w6bTaQviJ", - "ElQQlQm2HMOSvkgcuIAPBjIfDSx7qmEZLNHuSsoI+Udt56QU9nSJdj3I5tEFWZDNQ/SCURdiwx/LV3Fe", - "b77t/wiLZ6hpaTZ6w8ddyMS12vPEAzd1llgtJbHaGWJcZT1EsKmk1K87OBXZJIgm004NvPVliEgm9eY/", - "5D4aygyvkYsFHguJaSHCMOJPXbs8JpKRLC+U3TlONsH4D4D5M7Dw6LyDXzanCyQzhzI0oLZjWKbf1ois", - "MdoMELVMg6Jj8TSsohHW0RNV7hGnfOwPqkDVTMhAqQBc6YFqEuDMBAzrCCjuRAp+N0yiQw3vkQKYCdgc", - "AdkmBBkM2FQBFsEyAqYKIKWI0T8cV3KklZBAY1OzdXS5PGs+772lecZsrhC4gdrlEm2Cue+jJJsqo3Vq", - "OcIs2FoD2ABPw3sB4RjgPC4ZEUiSVCPawO9vGUkh2Lozdd0RM47BQw7DU54t1C3NEas2mnTzc/KYG5Zp", - "oVrE1br6VK8jODA6Ty/lOrUfssZ6BOe5uf4i0tIhE4rSLZJc3mx1dvLWMBbVx4Jcry/n2en0ztzIk82+", - "XWq+6vP2agD3fSii6zqICMncMm/stt1+p2JPXleLWaXfmbyUprMdVV7y+VU118oO87mHBtlVi4kkw54s", - "Qr2yapLbzas5aC2rjX79cXNbu68V7lZlOircPahV2czL3ebtktR6z4nUR+EsMEr/oT55qJLGWll1do3C", - "HG9Nu6KXSL3eZy11aN9uWzNcwS206BdfT9OvCelXshtGtzhbIfdDe54b2f3WdrJ+3uHscHTfr1uvWK82", - "zM6uWJ7uzqLSd88C5y9Yp1C4cNocyZiF3hQRYpJkD8ofn84THLHdYd+DEgFF6xkeSDTtmyp9+fMv6f8T", - "pEpfpP93faiyrr2Ic+27f+ktExfFigLoJJXQ0CDZODeJjzpYVurhgcGcGu0Oens72oHvmZiXe0AM+Hrj", - "rhXUPZWCe8igFNfx2GefTsGeIKe065ZEP6LiSE2VRn8+Zt+Oa73LduunOdd+gHNyPXmRBClA8dVgiBhQ", - "A3z7gEvnyo3hlFVDORqNVNinhIhkdkf1rkc5ciqRmrTYCSTwqB+h+QcZjT1oC7l8IzJ8nmOiWaapubhN", - "z8Y8npzE53JlWWf0E4oCFxCNmaeA7tDSOHKHG2hdSp4ezU3iwoelJ3wwLgGt8aHaSk8xXKKdonshRREt", - "HRtsgFY2ooJSCeqxSuiQYeg44cEmKLtOh1/dDfVBJe7x+h7IlBTe2bYJ6fw8A2+cQ1BkC6mjTyhRPg5B", - "JoGyhqLJVZO9LCvy+rWIKURjuMFw1HginVK1mc/Oci9Tsqqsxv3B+nGstBOzZL6/1SjhRq83H/Q65aK5", - "3uStp+ay3F/1lrnyaHGbK8jdFzW/3aPF3XjaaBqnCddiyfKm0x/V2/VZXW7djvOzzaTWLJaf1w/yYEJ3", - "8Llroelq17BnDy0kIrzxdRslW9pkK6/F23FWX+buSsV6cdXI35Ze9jV7nMWL9bYwz7Um3W5ztRrPz2aZ", - "Bx5RDUWXlfF35LsoQB1lkhY2ZslI0xGlcIZSYNkb+D10iCCwJpvNTYLZLqolfSA/5m73bHTXMNj0ab2+", - "Hed6w+2qXVEf1Vm21Syo+8nwddwrCNGiyND1FF+VGlJNgkKnBgcm2RvhXHeoUxxSBnUrNqdUzN0Wbivl", - "U3OR4qX3+nGVkb25uRHODc6ABUe/Gcmw9Ski31THUdNYoVjIi+hZXAFYvifYEglSEErhHmi+62YICtGf", - "pOgfVBhexpZezTGMeqs93K0c4Ji0mUncBcA5gcP4hgq3K4QJoZ1G66iYXTmJ1LsqfUagYWvwyFZLN78G", - "Rm6u7ahnRPBshsjQIggqER7FgyzB+aRfFwyQigiB2oXTDqdGKScmQczdkagek1eVyD5hOSKACJK79wnw", - "dANjbnFZaXeNLZ3tmQzJetTfNV5K7X3x7qFsdcaVysBCk33FXtTZviDaW4dgVRwJfjZxcEg3EBKe+DxO", - "++O20e/Ky+zyYUqeHhuL+mg7baiD+zm17Up9hdVGR3ka7ppJpE+cV5VbrFF+eK7puV5lo1S33clcx5PV", - "IFsctYzauFavvFD1sbzB24l1krz4uCpfXJWe1vl53hyWHmy51O+Xm9v+/WS/n45f2badZYPn59t5I4uL", - "7ZPkj48ey4OKXms0SCmXHbTuJ124zLbacNqm7KleqKLFtNyuqffzbo/C/FkfG+Uj0ppoqUcbFweJ+3fK", - "lMatRo6cpGxi4wHJS/Nr1KylDYGWhZR/UVODBhRHehnrUIuG4qzQj2DZNJ6IJr5deX8/SXf6NJ50Dr+1", - "08fCYGmJmgzhMak2SpHw6Ee4+8mVB5dY70bxI7aHQRarjbCBGXbvWtLvklcq+tdt0E8ZXPqJW9dBDCqQ", - "QZExaBqSxVm6CnWs7YQIdq8jzxUDfFTGpyOSLnJOJuCDtu7J2X/bCaaEdXFZkihi2FRSSe8Nj8rqM45J", - "mAnrU7TeICuOalqRIT8FhM7ESA0SPUi0Dbzlt3Z+qpm6REkoB7I5YRXh9z4JixINUnbvp7ipyOlwO9Sw", - "ZcEZqrl1zLG/tJIumD7AmPN4XzIm4wV+mDClrqrVp3synheqxZqx6ZYmZnORN3q9CWs9quPkpFQYn0s9", - "XVba+2m93d7CnpxvrEqNBR4ubjdsUS106iz7dDepGc15iW2SSQvuG9VVdfQ67U0eG0pdeX1e1qeNQc2Y", - "r7PtWmnD2kauUmkuOnq9YK+S7xuFIhdXt832TF1v9eWq2ir1Yb3xSrr6urXe9yeL58f9YjOwC8zEleHm", - "kqvM6tBebbbru0LjZfv4MKq8rCadl+ld675fg4NR1arPuzmzmx+389WykK7ogD7K4o6MlVVHf72b1mh5", - "/5Aj+kZ5nul0WCWt0bTztM6v1qN9+bH0+nyX3smKWu2Or+PiMIjrOGkBcQOKGGcmyRVkQv2IMXNK9DMH", - "C415G0hSma3lFbHpBhMso9q3NSKxo7rsVfEXBVl2VKAkyCo4m/g5l3DugCHQpCdkhu/B8cbx/kFDNd3I", - "bDAou2LqEGuOfkx5Dv9LkaF6Rc1DU1DH+fkomkpOeQmmUF4iQwEUkTWW0dW/jaqmgWrv628UzOEaAQi+", - "9gCBDAHePwhMFWRvAHHPwSmwEAEUyaahXP2bn6RixvXFiddc4s5CEaEu1+zVzdUNz8ssZEALO7rlP2V4", - "Ex0H4LXznxkStPP0sDED0MJXEidAuBU4CJQevCY194SSk8nd3PiKQq5ngJalYZlPul5QN6c4tEqdvHEJ", - "H3/yfYgK9q3Fd5naug7JzqlQEdTYHNzNkbzkj679zNYyqWBlzlPAEGWAuwkKmAkgUBB1QAMgpaaMIeN9", - "N0tkAOh6iwwwCbAgpUgB2Ig+O1JRz6TMc03e/tVMZfduKgrfjwg01EOMr0kJWocoMwk66ix8+8BdjFyX", - "JOxiRiq8I8doA4aAZQ0qINBaRir+St7BvfMQkTUioM77PKI47nBcupD8/b4+7tZH4Fu3/fqHC2q6gbMZ", - "Ile+ZJ7VHtnm0B33SHly/FMbLPCJZ2zRYw6ohWRX7HX2mp+8BdezNNHlPCAGoKaBYKTbtmHBGTa4iEJf", - "NM7GLtczkfcMEs7ZDkOuE9vR3zJn55555yANhaO3IFJMEnS2p5h11HGeYk684/3t+wc6DUGnxKfrSOM6", - "HMtxsomwETA4o/ylEH7u/T1qjN5Ur3dlc+h4OWmY7jgnsBBEKfLs00kvDjZ7ykaHLtdqhOmvNNd4b/fH", - "mVrsdYyPN5tI69Kn1VxiNa7ugKs8UPXRfc6GOJiu/zq8gvLmOXOeetoCO6rzx9cKps7/3czMQjJWMVKA", - "X6HEMknbNx63aSdg5tK62Hrir9WkwHKywX0kqP1Gz78hkAs32V/H+8nw7sT3SPlbWtHInM08MP/mJTO/", - "AVWDM2AaAAawPm9K5+OPO8yNOirWHHQCaCjA714Eh9OVU2HIa1P7D+WJRy98po1b4peePibqHb1WlnZO", - "7Rdkv/8r8lhRN+5nWL4kLAdmmuQ6/PfXrk3vBbaTDmQ0bgMoE5NS7kv4sZnLIslXxN+P+8hTr+SX8T5B", - "kxY0/ttrsZ1ee5vs40Yh2OKd6EH3pnzo2k6ETzDYf9lZNQlwSEUa4hOgdO+NO+J4aQw6cuUf7caE7f6f", - "kEwLSUd9INAfGG6gBQ5aDOHRr5+j9YQe6hZIOu9z0eVX/ocCIeg0+OkS4SMxFm2K+ARWWmDx8BW83hZS", - "YAhT1NLc4+QNtNK4OPdOwxkd9nEOp2GvHXQynnBxQwHDv72HE72+84nDtDjkquN+jYodW8SfcXRc4NSC", - "qaPIxE+P9k9Fkq831/OgtYEY6GAjnL6lv0eyKSJnD6Z//N4o8fsu/7cvcD7vbi7H/pOD1LDiPKgTk5lp", - "IreDdmpblkmYewoWfJOJXgHwVfVCe3BmRhAfrmGkZACbI4Mf30XmcQsMH7ixuUmRfz+9wZoGpggQxGxi", - "IK8lRWRe4SVcamHvcwr14YAPv1f8ifm0mOdqO8oZ+PZFkoYUKSvv6MGGaoLpDrhTE7w9DzK98EfD/u6Z", - "xCeiUiMKujlEFEvnHac77BRgqPTBLsTj8rnVqbda09zNpuD3Kr8Dqv1xSBHdm9kU23+ImUFcO1wtXTmB", - "0zABN383aLr9fxnHzShI5Z8QiYZeN2JdEB/HwXeH/qnh8RPbP4DtYYCoQH0haFuHT3ckQtv9wI03Mt5I", - "xy3Gh/kJYPqMfrQ0Gl9+8yj+bOQ/pTiKfHnl0yTSmoT7rdmD3kK28ENdA6cw/5/yw+fniD/M+2sw+4nW", - "9Gg9OO+D6t7+JwAA//+AO9X7DF0AAA==", + "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", + "a3q07oz3TnRv/xMAAP//Nf6V3uFdAAA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/pkg/api/routes/get_v1_analytics_overview.go b/pkg/api/routes/get_v1_analytics_overview.go index e272f17..2628928 100644 --- a/pkg/api/routes/get_v1_analytics_overview.go +++ b/pkg/api/routes/get_v1_analytics_overview.go @@ -4,7 +4,9 @@ import ( "fmt" "net/http" + "github.com/AlekSi/pointer" "github.com/dcaf-labs/drip/pkg/api/apispec" + "github.com/dcaf-labs/drip/pkg/service/repository" "github.com/labstack/echo/v4" ) @@ -26,10 +28,22 @@ func (h Handler) GetV1AnalyticsOverview(c echo.Context) error { if err != nil { return c.JSON(http.StatusInternalServerError, apispec.ErrorResponse{Error: "internal server error"}) } + uniqueDepositorCount, err := h.analyticsRepo.GetUniqueDepositorCount(ctx) + if err != nil { + return c.JSON(http.StatusInternalServerError, apispec.ErrorResponse{Error: "internal server error"}) + } + activeWallets, err := h.repo.GetActiveWallets(ctx, repository.GetActiveWalletParams{ + PositionIsClosed: pointer.ToBool(false), + }) + if err != nil { + return c.JSON(http.StatusInternalServerError, apispec.ErrorResponse{Error: "internal server error"}) + } return c.JSON(http.StatusOK, apispec.AnalyticsOverviewResponse{ UsdTvl: fmt.Sprintf("%f", tvl.TotalUSDValue), LifeTimeUsdDeposit: fmt.Sprintf("%f", lifeTimeDeposit.TotalUSDDeposit), LifeTimeUsdVolume: fmt.Sprintf("%f", lifeTimeVolume.TotalUSDVolume), LifeTimeUsdWithdrawal: fmt.Sprintf("%f", lifeTimeWithdrawal.TotalUSDWithdrawal), + ActiveWallets: float32(len(activeWallets)), + UniqueDepositors: float32(uniqueDepositorCount), }) } diff --git a/pkg/service/processor/transaction_update.go b/pkg/service/processor/transaction_update.go index 1373dbe..aa71115 100644 --- a/pkg/service/processor/transaction_update.go +++ b/pkg/service/processor/transaction_update.go @@ -425,6 +425,7 @@ func (p impl) getDepositWithMetadataMetric( ) (*model.DepositMetric, error) { var ( vault string + depositor string referrer *string tokenADepositAmount uint64 ) @@ -434,6 +435,7 @@ func (p impl) getDepositWithMetadataMetric( vault = parsedAccounts.Common.Vault.String() referrer = pointer.ToString(parsedAccounts.Common.Referrer.String()) tokenADepositAmount = parsedIx.Params.TokenADepositAmount + depositor = parsedAccounts.Common.Depositor.String() } else if err != nil { return nil, err } @@ -443,6 +445,7 @@ func (p impl) getDepositWithMetadataMetric( vault = parsedAccounts.Vault.String() referrer = nil tokenADepositAmount = parsedIx.Params.TokenADepositAmount + depositor = parsedAccounts.Depositor.String() } else if err != nil { return nil, err } @@ -457,6 +460,7 @@ func (p impl) getDepositWithMetadataMetric( Vault: vault, Referrer: referrer, TokenADepositAmount: tokenADepositAmount, + Depositor: pointer.ToString(depositor), TokenAUsdPriceDay: nil, } return metric, nil @@ -468,6 +472,7 @@ func (p impl) getDepositMetric( ) (*model.DepositMetric, error) { var ( vault string + depositor string referrer *string tokenADepositAmount uint64 ) @@ -478,6 +483,7 @@ func (p impl) getDepositMetric( vault = parsedAccounts.Common.Vault.String() referrer = pointer.ToString(parsedAccounts.Common.Referrer.String()) tokenADepositAmount = parsedIx.Params.TokenADepositAmount + depositor = parsedAccounts.Common.Depositor.String() } else if err != nil { return nil, err } @@ -487,6 +493,7 @@ func (p impl) getDepositMetric( vault = parsedAccounts.Vault.String() referrer = nil tokenADepositAmount = parsedIx.Params.TokenADepositAmount + depositor = parsedAccounts.Depositor.String() } else if err != nil { return nil, err } @@ -501,6 +508,7 @@ func (p impl) getDepositMetric( Vault: vault, Referrer: referrer, TokenADepositAmount: tokenADepositAmount, + Depositor: pointer.ToString(depositor), TokenAUsdPriceDay: nil, } return metric, nil diff --git a/pkg/service/repository/admin.go b/pkg/service/repository/admin.go index bbddefd..272a613 100644 --- a/pkg/service/repository/admin.go +++ b/pkg/service/repository/admin.go @@ -34,6 +34,44 @@ func (d repositoryImpl) AdminGetVaultsByTokenPairID(ctx context.Context, tokenPa Find() } +func (d repositoryImpl) GetAdminPositions( + ctx context.Context, isVaultEnabled *bool, + positionFilterParams PositionFilterParams, + params PaginationParams, +) ([]*model.Position, error) { + stmt := d.repo.Position.WithContext(ctx) + + // Apply Joins + if isVaultEnabled != nil { + stmt = stmt.Join(d.repo.Vault, d.repo.Vault.Pubkey.EqCol(d.repo.Position.Vault)) + } + if positionFilterParams.Wallet != nil { + stmt = stmt. + Join(d.repo.TokenAccount, d.repo.TokenAccount.Mint.EqCol(d.repo.Position.Authority)) + } + + // Apply Filters + if isVaultEnabled != nil { + stmt = stmt.Where(d.repo.Vault.Enabled.Is(*isVaultEnabled)) + } + if positionFilterParams.Wallet != nil { + stmt = stmt. + Where( + d.repo.TokenAccount.Owner.Eq(*positionFilterParams.Wallet), + d.repo.TokenAccount.Amount.Gt(0)) + } + if positionFilterParams.IsClosed != nil { + stmt = stmt.Where(d.repo.Position.IsClosed.Is(*positionFilterParams.IsClosed)) + } + if params.Limit != nil { + stmt = stmt.Limit(*params.Limit) + } + if params.Offset != nil { + stmt = stmt.Offset(*params.Offset) + } + return stmt.Find() +} + func (d repositoryImpl) AdminSetVaultEnabled(ctx context.Context, vaultPubkey string, enabled bool) (*model.Vault, error) { var res model.Vault _, err := d.repo.Vault. diff --git a/pkg/service/repository/analytics/mock.go b/pkg/service/repository/analytics/mock.go index e8a1cab..49a22a8 100644 --- a/pkg/service/repository/analytics/mock.go +++ b/pkg/service/repository/analytics/mock.go @@ -125,6 +125,21 @@ func (mr *MockAnalyticsRepositoryMockRecorder) GetLifeTimeWithdrawalNormalizedTo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLifeTimeWithdrawalNormalizedToCurrentPrice", reflect.TypeOf((*MockAnalyticsRepository)(nil).GetLifeTimeWithdrawalNormalizedToCurrentPrice), ctx) } +// GetUniqueDepositorCount mocks base method. +func (m *MockAnalyticsRepository) GetUniqueDepositorCount(ctx context.Context) (int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetUniqueDepositorCount", ctx) + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetUniqueDepositorCount indicates an expected call of GetUniqueDepositorCount. +func (mr *MockAnalyticsRepositoryMockRecorder) GetUniqueDepositorCount(ctx interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUniqueDepositorCount", reflect.TypeOf((*MockAnalyticsRepository)(nil).GetUniqueDepositorCount), ctx) +} + // GetWithdrawalMetricBySignature mocks base method. func (m *MockAnalyticsRepository) GetWithdrawalMetricBySignature(ctx context.Context, signature string) (*model.WithdrawalMetric, error) { m.ctrl.T.Helper() diff --git a/pkg/service/repository/analytics/repository.go b/pkg/service/repository/analytics/repository.go index 8488f87..665335e 100644 --- a/pkg/service/repository/analytics/repository.go +++ b/pkg/service/repository/analytics/repository.go @@ -14,6 +14,7 @@ type AnalyticsRepository interface { GetWithdrawalMetricBySignature(ctx context.Context, signature string) (*model.WithdrawalMetric, error) GetCurrentTVL(ctx context.Context) (*model.CurrentTVL, error) + GetUniqueDepositorCount(ctx context.Context) (int64, error) GetLifeTimeDepositNormalizedToCurrentPrice(ctx context.Context) (*model.LifeTimeDeposit, error) GetLifeTimeVolumeNormalizedToCurrentPrice(ctx context.Context) (*model.LifeTimeVolume, error) GetLifeTimeWithdrawalNormalizedToCurrentPrice(ctx context.Context) (*model.LifeTimeWithdrawal, error) @@ -34,6 +35,15 @@ func NewAnalyticsRepository( } } +func (d analyticsRepositoryImpl) GetUniqueDepositorCount(ctx context.Context) (int64, error) { + return d.repo. + DepositMetric. + WithContext(ctx). + Distinct(d.repo.DepositMetric.Depositor). + Where(d.repo.DepositMetric.Depositor.IsNotNull()). + Count() +} + const tvlQuery = "select sum(token_usd_value) as total_usd_value from (select token.pubkey as token_mint, (sum(amount)*token.ui_market_price_usd)/power(10, token.decimals) as token_usd_value from vault join token_account on vault.token_a_account = token_account.pubkey join token on token_account.mint = token.pubkey where amount != 0 group by token.pubkey\nunion \nselect token.pubkey as token_mint, (sum(amount)*token.ui_market_price_usd)/power(10, token.decimals) as token_usd_value from vault join token_account on vault.token_b_account = token_account.pubkey join token on token_account.mint = token.pubkey where amount != 0 group by token.pubkey) as q1;" func (d analyticsRepositoryImpl) GetCurrentTVL(ctx context.Context) (*model.CurrentTVL, error) { diff --git a/pkg/service/repository/database/migrations/34_add_depositor_to_metrics.up.sql b/pkg/service/repository/database/migrations/34_add_depositor_to_metrics.up.sql new file mode 100644 index 0000000..8dd5341 --- /dev/null +++ b/pkg/service/repository/database/migrations/34_add_depositor_to_metrics.up.sql @@ -0,0 +1 @@ +ALTER TABLE deposit_metric ADD COLUMN depositor VARCHAR(255) NULL; \ No newline at end of file diff --git a/pkg/service/repository/get.go b/pkg/service/repository/get.go index efec5b5..37b477f 100644 --- a/pkg/service/repository/get.go +++ b/pkg/service/repository/get.go @@ -294,41 +294,3 @@ func (d repositoryImpl) GetVaultByAddress(ctx context.Context, address string) ( Where(d.repo.Vault.Enabled.Is(true)). First() } - -func (d repositoryImpl) GetAdminPositions( - ctx context.Context, isVaultEnabled *bool, - positionFilterParams PositionFilterParams, - params PaginationParams, -) ([]*model.Position, error) { - stmt := d.repo.Position.WithContext(ctx) - - // Apply Joins - if isVaultEnabled != nil { - stmt = stmt.Join(d.repo.Vault, d.repo.Vault.Pubkey.EqCol(d.repo.Position.Vault)) - } - if positionFilterParams.Wallet != nil { - stmt = stmt. - Join(d.repo.TokenAccount, d.repo.TokenAccount.Mint.EqCol(d.repo.Position.Authority)) - } - - // Apply Filters - if isVaultEnabled != nil { - stmt = stmt.Where(d.repo.Vault.Enabled.Is(*isVaultEnabled)) - } - if positionFilterParams.Wallet != nil { - stmt = stmt. - Where( - d.repo.TokenAccount.Owner.Eq(*positionFilterParams.Wallet), - d.repo.TokenAccount.Amount.Gt(0)) - } - if positionFilterParams.IsClosed != nil { - stmt = stmt.Where(d.repo.Position.IsClosed.Is(*positionFilterParams.IsClosed)) - } - if params.Limit != nil { - stmt = stmt.Limit(*params.Limit) - } - if params.Offset != nil { - stmt = stmt.Offset(*params.Offset) - } - return stmt.Find() -} diff --git a/pkg/service/repository/model/deposit_metric.gen.go b/pkg/service/repository/model/deposit_metric.gen.go index d369472..298c81a 100644 --- a/pkg/service/repository/model/deposit_metric.gen.go +++ b/pkg/service/repository/model/deposit_metric.gen.go @@ -22,6 +22,7 @@ type DepositMetric struct { Referrer *string `gorm:"column:referrer" json:"referrer" db:"referrer"` TokenADepositAmount uint64 `gorm:"column:token_a_deposit_amount;not null" json:"tokenADepositAmount" db:"token_a_deposit_amount"` TokenAUsdPriceDay *uint64 `gorm:"column:token_a_usd_price_day" json:"tokenAUsdPriceDay" db:"token_a_usd_price_day"` + Depositor *string `gorm:"column:depositor" json:"depositor" db:"depositor"` } // TableName DepositMetric's table name diff --git a/pkg/service/repository/query/deposit_metric.gen.go b/pkg/service/repository/query/deposit_metric.gen.go index f622145..1541792 100644 --- a/pkg/service/repository/query/deposit_metric.gen.go +++ b/pkg/service/repository/query/deposit_metric.gen.go @@ -37,6 +37,7 @@ func newDepositMetric(db *gorm.DB) depositMetric { _depositMetric.Referrer = field.NewString(tableName, "referrer") _depositMetric.TokenADepositAmount = field.NewUint64(tableName, "token_a_deposit_amount") _depositMetric.TokenAUsdPriceDay = field.NewUint64(tableName, "token_a_usd_price_day") + _depositMetric.Depositor = field.NewString(tableName, "depositor") _depositMetric.fillFieldMap() @@ -57,6 +58,7 @@ type depositMetric struct { Referrer field.String TokenADepositAmount field.Uint64 TokenAUsdPriceDay field.Uint64 + Depositor field.String fieldMap map[string]field.Expr } @@ -83,6 +85,7 @@ func (d *depositMetric) updateTableName(table string) *depositMetric { d.Referrer = field.NewString(table, "referrer") d.TokenADepositAmount = field.NewUint64(table, "token_a_deposit_amount") d.TokenAUsdPriceDay = field.NewUint64(table, "token_a_usd_price_day") + d.Depositor = field.NewString(table, "depositor") d.fillFieldMap() @@ -107,7 +110,7 @@ func (d *depositMetric) GetFieldByName(fieldName string) (field.OrderExpr, bool) } func (d *depositMetric) fillFieldMap() { - d.fieldMap = make(map[string]field.Expr, 10) + d.fieldMap = make(map[string]field.Expr, 11) d.fieldMap["signature"] = d.Signature d.fieldMap["ix_index"] = d.IxIndex d.fieldMap["ix_name"] = d.IxName @@ -118,6 +121,7 @@ func (d *depositMetric) fillFieldMap() { d.fieldMap["referrer"] = d.Referrer d.fieldMap["token_a_deposit_amount"] = d.TokenADepositAmount d.fieldMap["token_a_usd_price_day"] = d.TokenAUsdPriceDay + d.fieldMap["depositor"] = d.Depositor } func (d depositMetric) clone(db *gorm.DB) depositMetric {