From 2f824e1be21bd624b266befb5ac42d58a29a29b8 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Mon, 21 Jun 2021 15:25:52 +0200 Subject: [PATCH] Governance Stacking Program Implemented --- .../Governance/Plugins/Pools/Superalgos.json | 4 +- .../Plugins/User-Profiles/Julian-Molina.json | 2 +- .../User-Profiles/Luis-Fernando-Molina.json | 31 ++- .../Schemas/App-Schema/staking-program.json | 2 +- .../App-Schema/token-power-switch.json | 4 +- .../Function-Libraries/DistributionProcess.js | 5 + .../UI/Function-Libraries/StackingProgram.js | 176 ++++++++++++++++++ .../UI/Utilities/MandatoryProgram.js | 22 +-- Projects/ProjectsSchema.json | 5 + 9 files changed, 231 insertions(+), 20 deletions(-) create mode 100644 Projects/Governance/UI/Function-Libraries/StackingProgram.js diff --git a/Projects/Governance/Plugins/Pools/Superalgos.json b/Projects/Governance/Plugins/Pools/Superalgos.json index c8d3c89c6..4fd2ffee9 100644 --- a/Projects/Governance/Plugins/Pools/Superalgos.json +++ b/Projects/Governance/Plugins/Pools/Superalgos.json @@ -575,8 +575,8 @@ "pools": [ { "type": "Pool", - "name": "Stacking", - "config": "{\n \"description\": \"\"\n}", + "name": "Stacking-Program", + "config": "{\n \"codeName\": \"Staking-Program\"\n}", "project": "Governance", "poolClasses": [], "pools": [], diff --git a/Projects/Governance/Plugins/User-Profiles/Julian-Molina.json b/Projects/Governance/Plugins/User-Profiles/Julian-Molina.json index 21e5006f4..8d7e9f971 100644 --- a/Projects/Governance/Plugins/User-Profiles/Julian-Molina.json +++ b/Projects/Governance/Plugins/User-Profiles/Julian-Molina.json @@ -269,7 +269,7 @@ } } }, - "stakingProgram": { + "stackingProgram": { "type": "Staking Program", "name": "New Staking Program", "config": "{}", diff --git a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json index 4520f925d..548a3f54e 100644 --- a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json +++ b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json @@ -990,7 +990,7 @@ "poolWeightVotes": [ { "type": "Pool Weight Vote", - "name": "Stacking Pool", + "name": "Stacking-Program Pool", "config": "{}", "project": "Governance", "id": "40d246e2-1cd8-4e8e-a9d9-33a3256f1f75", @@ -1014,7 +1014,7 @@ "uiObject": {}, "referenceParent": { "type": "Pool", - "name": "Stacking", + "name": "Stacking-Program", "id": "ea79efd3-c3d9-4c80-a1d0-1cab106e0242" } } @@ -2002,11 +2002,36 @@ } } }, - "stakingProgram": { + "stackingProgram": { "type": "Staking Program", "name": "New Staking Program", "config": "{}", "project": "Governance", + "tokensAwarded": { + "type": "Tokens Awarded", + "name": "New Tokens Awarded", + "project": "Governance", + "id": "928e9ccb-1e90-48a9-af77-b3089225fc4f", + "savedPayload": { + "position": { + "x": 29846.901110519182, + "y": 23025.90611888476 + }, + "targetPosition": { + "x": 30081.45055525959, + "y": 23212.953059442378 + }, + "floatingObject": { + "isPinned": false, + "isFrozen": false, + "isCollapsed": false, + "angleToParent": 1, + "distanceToParent": 3, + "arrangementStyle": 0 + }, + "uiObject": {} + } + }, "id": "b046f4e4-40b1-4e47-8fed-75a6a5c6029d", "savedPayload": { "position": { diff --git a/Projects/Governance/Schemas/App-Schema/staking-program.json b/Projects/Governance/Schemas/App-Schema/staking-program.json index 86dab37b1..0e54acf98 100644 --- a/Projects/Governance/Schemas/App-Schema/staking-program.json +++ b/Projects/Governance/Schemas/App-Schema/staking-program.json @@ -39,7 +39,7 @@ }, "addLeftIcons": true, "level": 1, - "propertyNameAtParent": "stakingProgram", + "propertyNameAtParent": "stackingProgram", "childrenNodesProperties": [ { "name": "tokensAwarded", diff --git a/Projects/Governance/Schemas/App-Schema/token-power-switch.json b/Projects/Governance/Schemas/App-Schema/token-power-switch.json index 6e150876b..323b15701 100644 --- a/Projects/Governance/Schemas/App-Schema/token-power-switch.json +++ b/Projects/Governance/Schemas/App-Schema/token-power-switch.json @@ -58,7 +58,7 @@ "actionProject": "Foundations", "actionFunction": "payload.executeAction", "disableIfPropertyIsDefined": true, - "propertyToCheckFor": "stakingProgram", + "propertyToCheckFor": "stackingProgram", "label": "Add Staking Program", "relatedUiObject": "Staking Program" }, @@ -117,7 +117,7 @@ "autoAdd": true }, { - "name": "stakingProgram", + "name": "stackingProgram", "type": "node", "childType": "Staking Program", "autoAdd": true diff --git a/Projects/Governance/UI/Function-Libraries/DistributionProcess.js b/Projects/Governance/UI/Function-Libraries/DistributionProcess.js index bd22a80a8..8a2200641 100644 --- a/Projects/Governance/UI/Function-Libraries/DistributionProcess.js +++ b/Projects/Governance/UI/Function-Libraries/DistributionProcess.js @@ -50,6 +50,11 @@ function newGovernanceFunctionLibraryDistributionProcess() { pools, userProfiles ) + + UI.projects.governance.functionLibraries.stackingProgram.calculate( + pools, + userProfiles + ) UI.projects.governance.functionLibraries.claims.calculate( features, diff --git a/Projects/Governance/UI/Function-Libraries/StackingProgram.js b/Projects/Governance/UI/Function-Libraries/StackingProgram.js new file mode 100644 index 000000000..e86764f80 --- /dev/null +++ b/Projects/Governance/UI/Function-Libraries/StackingProgram.js @@ -0,0 +1,176 @@ +function newGovernanceFunctionLibraryStackingProgram() { + let thisObject = { + calculate: calculate + } + + return thisObject + + function calculate( + pools, + userProfiles + ) { + let programPoolTokenReward + /* + In order to be able to calculate the share of the Program Pool for each User Profile, + we need to accumulate all the Stacking Power that each User Profile at their Program + node has, because with that Power is that each Program node gets a share of the pool. + */ + let accumulatedProgramPower = 0 + + /* Scan Pools Until finding the Mentoship-Program Pool */ + for (let i = 0; i < pools.length; i++) { + let poolsNode = pools[i] + programPoolTokenReward = UI.projects.governance.utilities.pools.findPool(poolsNode, "Staking-Program") + } + if (programPoolTokenReward === undefined || programPoolTokenReward === 0) { return } + + for (let i = 0; i < userProfiles.length; i++) { + let userProfile = userProfiles[i] + + if (userProfile.tokenPowerSwitch === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram.payload === undefined) { continue } + + resetProgram(userProfile.tokenPowerSwitch.stackingProgram) + } + for (let i = 0; i < userProfiles.length; i++) { + let userProfile = userProfiles[i] + + if (userProfile.tokenPowerSwitch === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram.payload === undefined) { continue } + + validateProgram(userProfile.tokenPowerSwitch.stackingProgram) + } + for (let i = 0; i < userProfiles.length; i++) { + let userProfile = userProfiles[i] + + if (userProfile.tokenPowerSwitch === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram.payload === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram.payload.stackingProgram.isActive === false) { continue } + + distributeProgram(userProfile.tokenPowerSwitch.stackingProgram) + } + for (let i = 0; i < userProfiles.length; i++) { + let userProfile = userProfiles[i] + + if (userProfile.tokenPowerSwitch === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram.payload === undefined) { continue } + if (userProfile.tokenPowerSwitch.stackingProgram.payload.stackingProgram.isActive === false) { continue } + + calculateProgram(userProfile.tokenPowerSwitch.stackingProgram) + } + + function resetProgram(node) { + if (node === undefined) { return } + if (node.payload === undefined) { return } + node.payload.stackingProgram = { + count: 0, + percentage: 0, + outgoingPower: 0, + ownPower: 0, + incomingPower: 0, + awarded: { + tokens: 0, + percentage: 0 + } + } + } + + function validateProgram(node) { + /* + This program is not going to run unless the Profile has Tokens, and for + that users needs to execute the setup procedure of signing their Github + username with their private key. + */ + if ( + node.payload.parentNode.payload.parentNode.payload.blockchainTokens === undefined + ) { + node.payload.stackingProgram.isActive = false + node.payload.parentNode.payload.parentNode.payload.uiObject.setErrorMessage("You need to setup this profile with the Profile Constructor, to access the Token Power of your account at the Blockchain.") + return + } + /* + The Staking Program is activated, only when then Mandatory Programs are active. + */ + if ( + node.payload.parentNode.payload.parentNode.tokenPowerSwitch !== undefined && + node.payload.parentNode.payload.parentNode.tokenPowerSwitch.referralProgram !== undefined && + node.payload.parentNode.payload.parentNode.tokenPowerSwitch.mentorshipProgram !== undefined && + node.payload.parentNode.payload.parentNode.tokenPowerSwitch.supportProgram !== undefined && + node.payload.parentNode.payload.parentNode.tokenPowerSwitch.referralProgram.payload.referralProgram !== undefined && + node.payload.parentNode.payload.parentNode.tokenPowerSwitch.mentorshipProgram.payload.mentorshipProgram !== undefined && + node.payload.parentNode.payload.parentNode.tokenPowerSwitch.supportProgram.payload.supportProgram !== undefined && + node.payload.parentNode.payload.parentNode.tokenPowerSwitch.referralProgram.payload.referralProgram.isActive === true && + node.payload.parentNode.payload.parentNode.tokenPowerSwitch.mentorshipProgram.payload.mentorshipProgram.isActive === true && + node.payload.parentNode.payload.parentNode.tokenPowerSwitch.supportProgram.payload.supportProgram.isActive === true + ) { + node.payload.stackingProgram.isActive = true + } else { + node.payload.stackingProgram.isActive = false + node.payload.uiObject.setErrorMessage("This Program will be activated once you activate the Referral, Support and Mentorship Programs.") + } + } + + function distributeProgram(programNode) { + if (programNode === undefined || programNode.payload === undefined) { return } + /* + Here we will convert Token Power into Stacking Power. + As per system rules Stacking Powar = tokensPower + */ + let programPower = programNode.payload.tokenPower + programNode.payload.stackingProgram.ownPower = programPower + + accumulatedProgramPower = accumulatedProgramPower + programPower + } + + function calculateProgram(programNode) { + /* + Here we will calculate which share of the Program Pool this user will get in tokens. + To do that, we use the ownPower, to see which proportion of the accumulatedProgramPower + represents. + */ + if (programNode.payload === undefined) { return } + /* + If the accumulatedProgramPower is not grater the amount of tokens at the Program Pool, then + this user will get the exact amount of tokens from the pool as incomingPower he has. + + If the accumulatedProgramPower is grater the amount of tokens at the Program Pool, then + the amount ot tokens to be received is a proportional to the share of incomingPower in accumulatedProgramPower. + */ + let totalPowerRewardRatio = accumulatedProgramPower / programPoolTokenReward + if (totalPowerRewardRatio < 1) { totalPowerRewardRatio = 1 } + + if (programNode.tokensAwarded === undefined || programNode.tokensAwarded.payload === undefined) { + programNode.payload.uiObject.setErrorMessage("Tokens Awarded Node is needed in order for this Program to get Tokens from the Program Pool.") + return + } + programNode.payload.stackingProgram.awarded.tokens = programNode.payload.stackingProgram.ownPower * totalPowerRewardRatio + + drawProgram(programNode) + } + + function drawProgram(node) { + if (node.payload !== undefined) { + + const ownPowerText = new Intl.NumberFormat().format(node.payload.stackingProgram.ownPower) + + node.payload.uiObject.statusAngleOffset = 0 + node.payload.uiObject.statusAtAngle = false + + node.payload.uiObject.setStatus(ownPowerText + ' Staking Power') + } + if (node.tokensAwarded !== undefined && node.tokensAwarded.payload !== undefined) { + + const tokensAwardedText = new Intl.NumberFormat().format(node.payload.stackingProgram.awarded.tokens) + + node.tokensAwarded.payload.uiObject.valueAngleOffset = 0 + node.tokensAwarded.payload.uiObject.valueAtAngle = false + + node.tokensAwarded.payload.uiObject.setValue(tokensAwardedText + ' SA Tokens') + } + } + } +} \ No newline at end of file diff --git a/Projects/Governance/UI/Utilities/MandatoryProgram.js b/Projects/Governance/UI/Utilities/MandatoryProgram.js index 976b567a9..5e4e9ab3f 100644 --- a/Projects/Governance/UI/Utilities/MandatoryProgram.js +++ b/Projects/Governance/UI/Utilities/MandatoryProgram.js @@ -165,9 +165,9 @@ function newFoundationsUtilitiesMandatoryProgram() { if (programNode === undefined || programNode.payload === undefined) { return } /* Here we will convert Token Power into programPowerName. - As per system rules mentoshipPower = tokensPower + As per system rules programPowerName = tokensPower */ - let mentoshipPower = programNode.payload.tokenPower + let programPower = programNode.payload.tokenPower /* We will also reseet the count of descendents from here. */ @@ -175,14 +175,14 @@ function newFoundationsUtilitiesMandatoryProgram() { /* The Own Power is the power generated by the same User Profile tokens, not inherited from others. */ - programNode.payload[programPropertyName].ownPower = mentoshipPower + programNode.payload[programPropertyName].ownPower = programPower - distributeProgramPower(programNode, mentoshipPower, count) + distributeProgramPower(programNode, programPower, count) } function distributeProgramPower( node, - mentoshipPower, + programPower, count, percentage ) { @@ -199,10 +199,10 @@ function newFoundationsUtilitiesMandatoryProgram() { */ node.payload[programPropertyName].count = node.payload[programPropertyName].count + count /* - The outgoingPower of this node will be accumulating all the mentoshipPower flowing + The outgoingPower of this node will be accumulating all the programPower flowing through it, no matter from where it comes. */ - node.payload[programPropertyName].outgoingPower = node.payload[programPropertyName].outgoingPower + mentoshipPower + node.payload[programPropertyName].outgoingPower = node.payload[programPropertyName].outgoingPower + programPower /* We need to adjust the balance that holds the accumulationt of all incomingPower of all Program nodes. To do this we will substratct the current incomingPower, bacause it is going to be recalculated @@ -258,7 +258,7 @@ function newFoundationsUtilitiesMandatoryProgram() { if (percentage === undefined || isNaN(percentage) === true) { percentage = defaultPercentage } - distributeProgramPower(childNode, mentoshipPower * percentage / 100, 0, percentage) + distributeProgramPower(childNode, programPower * percentage / 100, 0, percentage) } } break @@ -268,19 +268,19 @@ function newFoundationsUtilitiesMandatoryProgram() { drawUserNode(node, percentage) if (node.payload.referenceParent !== undefined) { - distributeProgramPower(node.payload.referenceParent, mentoshipPower / 10, 0) + distributeProgramPower(node.payload.referenceParent, programPower / 10, 0) } break } case 'User Profile': { if (node.tokenPowerSwitch !== undefined) { - distributeProgramPower(node.tokenPowerSwitch, mentoshipPower, 0) + distributeProgramPower(node.tokenPowerSwitch, programPower, 0) } break } case 'Token Power Switch': { if (node[programPropertyName] !== undefined) { - distributeProgramPower(node[programPropertyName], mentoshipPower, 1) + distributeProgramPower(node[programPropertyName], programPower, 1) } break } diff --git a/Projects/ProjectsSchema.json b/Projects/ProjectsSchema.json index 9318f6869..b0edf218d 100644 --- a/Projects/ProjectsSchema.json +++ b/Projects/ProjectsSchema.json @@ -1013,6 +1013,11 @@ "propertyName": "mentorshipProgram", "functionName": "newGovernanceFunctionLibraryMentorshipProgram" }, + { + "name": "Stacking Program", + "propertyName": "stackingProgram", + "functionName": "newGovernanceFunctionLibraryStackingProgram" + }, { "name": "Profile Constructor", "propertyName": "profileConstructor",