diff --git a/src/app/admin/admin.component.html b/src/app/admin/admin.component.html index 4d4d325da..76304a073 100644 --- a/src/app/admin/admin.component.html +++ b/src/app/admin/admin.component.html @@ -115,6 +115,310 @@ + +
+
+ Update the hot feed algorithm by updating the values below. +
+ + +
+ Update Interaction Cap - Global Hot Feed (max $DESO locked) +
+ + + +
+
+ + +
+ Update Interaction Cap - Tag Specific Feeds (max $DESO locked) +
+ + + +
+
+ + +
+ Update Time Decay Blocks For Global Feed +
+ + + +
+
+ + +
+ Update Time Decay Blocks For Tag Feed +
+ + + +
+
+ + +
+ Update Transaction Type Multipliers +
+ + +
+
+ + + + + + +
+ + +
+ + +
+ Update User Posts Multiplier (boost all of a user's posts) +
+ + + + +
+
+ + +
+ Update User Interaction Multiplier (boost all of a user's interactions) +
+ + + + +
+
+ + +
+   + Look Up User Interaction Multipliers +
+ + + +
+
+
+ {{ hotFeedUserSearchResults }} +
+ +
+ Select posts below to whitelist. +
+ + + +
+
+ + +
+
+
+ +
+
Load More
+
Loading...
+
+
+
{ + this.hotFeedInteractionCap = res.InteractionCap / 1e9; + this.hotFeedTagInteractionCap = res.InteractionCapTag / 1e9; + this.hotFeedTimeDecayBlocks = res.TimeDecayBlocks; + this.hotFeedTagTimeDecayBlocks = res.TimeDecayBlocksTag; + this.hotFeedTxnTypeMultiplierMap = res.TxnTypeMultiplierMap; + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error getting hot feed constants: " + this.backendApi.stringifyError(err)); + } + ); + } + + // Fetch the hot feed. + if (this.hotFeedPostHashes.length > 0) { + this.loadingMoreHotFeed = true; + } + this.backendApi + .AdminGetUnfilteredHotFeed( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + 50, + this.hotFeedPostHashes + ) + .subscribe( + (res) => { + this.hotFeedPosts = this.hotFeedPosts.concat(res.HotFeedPage); + for (let ii = 0; ii < res.HotFeedPage?.length; ii++) { + this.hotFeedPostHashes = this.hotFeedPostHashes.concat(res.HotFeedPage[ii].PostHashHex); + } + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error loading hot feed: " + this.backendApi.stringifyError(err)); + } + ) + .add(() => { + this.loadingHotFeed = false; + this.loadingMoreHotFeed = false; + }); + } + + updateHotFeedInteractionCap() { + this.updatingHotFeedInteractionCap = true; + this.backendApi + .AdminUpdateHotFeedAlgorithm( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + this.hotFeedInteractionCap * 1e9, + 0, + 0, + 0, + {} + ) + .subscribe( + (res) => { + this.globalVars._alertSuccess( + "Successfully updated InteractionCap. The hot feed will take ~10s to recompute." + ); + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error updating InteractionCap: " + this.backendApi.stringifyError(err)); + } + ) + .add(() => { + this.updatingHotFeedInteractionCap = false; + }); + } + + updateHotFeedTagInteractionCap() { + this.updatingHotFeedTagInteractionCap = true; + this.backendApi + .AdminUpdateHotFeedAlgorithm( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + 0, + this.hotFeedTagInteractionCap * 1e9, + 0, + 0, + {} + ) + .subscribe( + (res) => { + this.globalVars._alertSuccess( + "Successfully updated Tag InteractionCap. The hot feed will take ~10s to recompute." + ); + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error updating Tag InteractionCap: " + this.backendApi.stringifyError(err)); + } + ) + .add(() => { + this.updatingHotFeedTagInteractionCap = false; + }); + } + + updateHotFeedTimeDecayBlocks() { + this.updatingHotFeedTimeDecayBlocks = true; + this.backendApi + .AdminUpdateHotFeedAlgorithm( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + 0, + 0, + this.hotFeedTimeDecayBlocks, + 0, + {} + ) + .subscribe( + (res) => { + this.globalVars._alertSuccess( + "Successfully updated TimeDecayBlocks. The hot feed will take ~10s to recompute." + ); + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error updating hot TimeDecayBlocks: " + this.backendApi.stringifyError(err)); + } + ) + .add(() => { + this.updatingHotFeedTimeDecayBlocks = false; + }); + } + + updateHotFeedTagTimeDecayBlocks() { + this.updatingHotFeedTagTimeDecayBlocks = true; + this.backendApi + .AdminUpdateHotFeedAlgorithm( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + 0, + 0, + 0, + this.hotFeedTagTimeDecayBlocks, + {} + ) + .subscribe( + (res) => { + this.globalVars._alertSuccess( + "Successfully updated tag TimeDecayBlocks. The hot feed will take ~10s to recompute." + ); + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error updating tag hot TimeDecayBlocks: " + this.backendApi.stringifyError(err)); + } + ) + .add(() => { + this.updatingHotFeedTagTimeDecayBlocks = false; + }); + } + + addMultiplierToTxnTypeMultiplier() { + this.hotFeedTxnTypeMultiplierMap[this.hotFeedTxnTypeMultiplierNewKey] = this.hotFeedTxnTypeMultiplierNewValue; + this.hotFeedTxnTypeMultiplierNewKey = null; + this.hotFeedTxnTypeMultiplierNewValue = null; + } + + updateHotFeedTxnTypeMultiplierMap() { + this.updatingHotFeedTxnTypeMultiplierMap = true; + this.backendApi + .AdminUpdateHotFeedAlgorithm( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + 0, + 0, + 0, + 0, + this.hotFeedTxnTypeMultiplierMap + ) + .subscribe( + (res) => { + this.globalVars._alertSuccess( + "Successfully updated txn type multiplier map. The hot feed will take ~10s to recompute." + ); + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error updating txn type multiplier map: " + this.backendApi.stringifyError(err)); + } + ) + .add(() => { + this.updatingHotFeedTxnTypeMultiplierMap = false; + }); + } + + updateHotFeedUserPostsMultiplier() { + this.updatingHotFeedUserPostsMultiplier = true; + this.backendApi + .AdminUpdateHotFeedUserMultiplier( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + this.hotFeedUserForPostsMultiplier, + -1 /*InteractionMultiplier -- negative values are ignored*/, + this.hotFeedUserPostsMultiplier + ) + .subscribe( + (res) => { + this.globalVars._alertSuccess("Successfully updated posts multiplier."); + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error updating posts multiplier: " + this.backendApi.stringifyError(err)); + } + ) + .add(() => { + this.updatingHotFeedUserPostsMultiplier = false; + }); + } + + updateHotFeedUserInteractionMultiplier() { + this.updatingHotFeedUserInteractionMultiplier = true; + this.backendApi + .AdminUpdateHotFeedUserMultiplier( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + this.hotFeedUserForInteractionMultiplier, + this.hotFeedUserInteractionMultiplier, + -1 /*PostsMultiplier -- negative values are ignored*/ + ) + .subscribe( + (res) => { + this.globalVars._alertSuccess("Successfully updated interaction multiplier."); + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error updating interaction multiplier: " + this.backendApi.stringifyError(err)); + } + ) + .add(() => { + this.updatingHotFeedUserInteractionMultiplier = false; + }); + } + + searchForHotFeedUserMultipliers() { + this.searchingHotFeedUserMultipliers = true; + this.backendApi + .AdminGetHotFeedUserMultiplier( + this.globalVars.localNode, + this.globalVars.loggedInUser.PublicKeyBase58Check, + this.hotFeedUserForSearch + ) + .subscribe( + (res) => { + this.hotFeedUserSearchResults = JSON.stringify( + { + InteractionMultiplier: res.InteractionMultiplier, + PostsMultiplier: res.PostsMultiplier, + }, + null, + 4 + ); + }, + (err) => { + console.error(err); + this.globalVars._alertError("Error fetching user's multipliers: " + this.backendApi.stringifyError(err)); + } + ) + .add(() => { + this.searchingHotFeedUserMultipliers = false; + }); + } + _loadPosts() { this.loadingMorePosts = true; diff --git a/src/app/backend-api.service.ts b/src/app/backend-api.service.ts index b30672c44..0b2a7d219 100644 --- a/src/app/backend-api.service.ts +++ b/src/app/backend-api.service.ts @@ -139,6 +139,12 @@ export class BackendRoutes { static RoutePathAdminUpdateJumioCountrySignUpBonus = "/api/v0/admin/update-jumio-country-sign-up-bonus"; static RoutePathAdminUpdateJumioUSDCents = "/api/v0/admin/update-jumio-usd-cents"; static RoutePathAdminUpdateJumioKickbackUSDCents = "/api/v0/admin/update-jumio-kickback-usd-cents"; + static RoutePathAdminGetUnfilteredHotFeed = "/api/v0/admin/get-unfiltered-hot-feed"; + static RoutePathAdminGetHotFeedAlgorithm = "/api/v0/admin/get-hot-feed-algorithm"; + static RoutePathAdminUpdateHotFeedAlgorithm = "/api/v0/admin/update-hot-feed-algorithm"; + static RoutePathAdminUpdateHotFeedPostMultiplier = "/api/v0/admin/update-hot-feed-post-multiplier"; + static RoutePathAdminUpdateHotFeedUserMultiplier = "/api/v0/admin/update-hot-feed-user-multiplier"; + static RoutePathAdminGetHotFeedUserMultiplier = "/api/v0/admin/get-hot-feed-user-multiplier"; // Referral program admin routes. static RoutePathAdminCreateReferralHash = "/api/v0/admin/create-referral-hash"; @@ -2104,6 +2110,79 @@ export class BackendApiService { }); } + AdminGetUnfilteredHotFeed( + endpoint: string, + AdminPublicKey: string, + ResponseLimit: number, + SeenPosts: Array + ): Observable { + return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetUnfilteredHotFeed, AdminPublicKey, { + AdminPublicKey, + ResponseLimit, + SeenPosts, + }); + } + + AdminGetHotFeedAlgorithm(endpoint: string, AdminPublicKey: string): Observable { + return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetHotFeedAlgorithm, AdminPublicKey, { + AdminPublicKey, + }); + } + + AdminUpdateHotFeedAlgorithm( + endpoint: string, + AdminPublicKey: string, + InteractionCap: number, + InteractionCapTag: number, + TimeDecayBlocks: number, + TimeDecayBlocksTag: number, + TxnTypeMultiplierMap: { [txnType: number]: number } + ): Observable { + return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateHotFeedAlgorithm, AdminPublicKey, { + AdminPublicKey, + InteractionCap, + InteractionCapTag, + TimeDecayBlocks, + TimeDecayBlocksTag, + TxnTypeMultiplierMap, + }); + } + + AdminUpdateHotFeedPostMultiplier( + endpoint: string, + AdminPublicKey: string, + PostHashHex: string, + Multiplier: number + ): Observable { + return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateHotFeedPostMultiplier, AdminPublicKey, { + AdminPublicKey, + PostHashHex, + Multiplier, + }); + } + + AdminUpdateHotFeedUserMultiplier( + endpoint: string, + AdminPublicKey: string, + Username: string, + InteractionMultiplier: number, + PostsMultiplier: number + ): Observable { + return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminUpdateHotFeedUserMultiplier, AdminPublicKey, { + AdminPublicKey, + Username, + InteractionMultiplier, + PostsMultiplier, + }); + } + + AdminGetHotFeedUserMultiplier(endpoint: string, AdminPublicKey: string, Username: string): Observable { + return this.jwtPost(endpoint, BackendRoutes.RoutePathAdminGetHotFeedUserMultiplier, AdminPublicKey, { + AdminPublicKey, + Username, + }); + } + SwapIdentity( endpoint: string, UpdaterPublicKeyBase58Check: string,