diff --git a/.gitignore b/.gitignore index 07cadad8b..9705d9e62 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ Log-Files My-Workspaces My-Social-Trading-Data My-Network-Nodes-Data +My-Secrets debug.log .DS_Store *.db diff --git a/Platform/Client/githubServer.js b/Platform/Client/githubServer.js index 4c0521a8b..b40fa153d 100644 --- a/Platform/Client/githubServer.js +++ b/Platform/Client/githubServer.js @@ -304,6 +304,7 @@ exports.newGithubServer = function newGithubServer() { if (await validateUserProfileNodeNameEqualsGithubUsername() === false) { continue } if (await validateUserProfileIdDoesNotBelongtoAnotherUserProfile() === false) { continue } if (await validateUserProfileBlockchainAccountDoesNotBelongtoAnotherUserProfile() === false) { continue } + if (await validateUserProfileSigningAccountsDoesNotBelongtoAnotherUserProfile() === false) { continue } if (await mergePullRequest() === false) { console.log('[WARN] Github Server -> mergeGithubPullRequests -> Merge Failed -> Pull Request "' + pullRequest.title + '" not merged because Github could not merge it. -> mergeResponse.message = ' + mergeResponse.data.message) @@ -578,6 +579,48 @@ exports.newGithubServer = function newGithubServer() { } } + async function validateUserProfileSigningAccountsDoesNotBelongtoAnotherUserProfile() { + try { + /* + Validation #8 Signing accounts of the User Profile + must have a signature of the same Github username of the User Profile. + */ + + if (userProfile.signingAccounts === undefined) { return true } + + for (let i = 0; i < userProfile.signingAccounts.length; i++) { + let signingAccount = userProfile.signingAccounts[i] + let config = JSON.parse(signingAccount.config) + let messageSigned = config.signature.message + + if (messageSigned !== githubUsername) { + console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #8 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Signing Account ' + signingAccount.name + ' has not signed the current Github User Account, but something else. -> messageSigned = ' + messageSigned + '-> githubUsername = ' + githubUsername) + + await PL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + await octokit.rest.issues.createComment({ + owner: owner, + repo: repo, + issue_number: pullRequest.number, + body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because the Signing Account ' + signingAccount.name + ' has not signed the current Github User Account, but something else. \n\n messageSigned = ' + messageSigned + '" \n\n githubUsername = ' + githubUsername + '"' + }); + + await PL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME) + await octokit.rest.pulls.update({ + owner: owner, + repo: repo, + pull_number: pullRequest.number, + state: 'closed' + }); + return false + } + } + + return true + } catch (err) { + console.log(err.stack) + } + } + async function mergePullRequest() { /* All validations passed, we will proceed an merge this Pull Request. diff --git a/Platform/UI/AppLoader.js b/Platform/UI/AppLoader.js index eb8f87864..2e010babf 100644 --- a/Platform/UI/AppLoader.js +++ b/Platform/UI/AppLoader.js @@ -138,7 +138,7 @@ function newAppLoader() { for (let i = 0; i < modulesArray.length; i++) { let path = modulesArray[i] - console.log(path) + REQUIREJS([path], onRequired) if (INFO_LOG === true) { logger.write('[INFO] loadModules -> Module Requested.') } diff --git a/Platform/UI/Utilities.js b/Platform/UI/Utilities.js index 0c2cbee7a..6216d3d59 100644 --- a/Platform/UI/Utilities.js +++ b/Platform/UI/Utilities.js @@ -98,6 +98,9 @@ function newUniqueId () { function splitTextIntoPhrases (text, wordsPerLine) { try { + if (text.split === undefined) { + return [] + } let splittedLabel = text.split(' ') let phrases = [] let phrase = '' diff --git a/Projects/Foundations/UI/Spaces/Design-Space/Workspace.js b/Projects/Foundations/UI/Spaces/Design-Space/Workspace.js index 5f1fcc8bc..61a2b1335 100644 --- a/Projects/Foundations/UI/Spaces/Design-Space/Workspace.js +++ b/Projects/Foundations/UI/Spaces/Design-Space/Workspace.js @@ -18,6 +18,7 @@ function newWorkspace() { share: shareWorkspace, getNodesByTypeAndHierarchyHeadsType: getNodesByTypeAndHierarchyHeadsType, getProjectsHeads: getProjectsHeads, + getProjectHeadByNodeType: getProjectHeadByNodeType, getHierarchyHeads: getHierarchyHeads, getHierarchyHeadsById: getHierarchyHeadsById, getHierarchyHeadsByCodeNameAndNodeType: getHierarchyHeadsByCodeNameAndNodeType, @@ -547,6 +548,17 @@ function newWorkspace() { return nodes } + function getProjectHeadByNodeType(nodeType) { + let projectHeads = getProjectsHeads() + if (projectHeads === undefined) { return } + for (let i = 0; i < projectHeads.length; i++) { + let hierarchyHead = projectHeads[i] + if (hierarchyHead.type === nodeType) { + return hierarchyHead + } + } + } + function getHierarchyHeadsById(nodeId) { let hierarchyHeads = getHierarchyHeads() if (hierarchyHeads === undefined) { return } diff --git a/Projects/Governance/Icons/signing-account.png b/Projects/Governance/Icons/signing-account.png new file mode 100644 index 000000000..a4ee2a209 Binary files /dev/null and b/Projects/Governance/Icons/signing-account.png differ diff --git a/Projects/Governance/Icons/signing-accounts.png b/Projects/Governance/Icons/signing-accounts.png new file mode 100644 index 000000000..a4ee2a209 Binary files /dev/null and b/Projects/Governance/Icons/signing-accounts.png differ diff --git a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json index d20244250..98c9a8ce9 100644 --- a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json +++ b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json @@ -127,12 +127,12 @@ "id": "f4d39b02-4324-438d-9f74-2bea2b7272ef", "savedPayload": { "position": { - "x": 10242.705098312485, - "y": 21727.335575687743 + "x": 10476.335575687743, + "y": 24007.294901687517 }, "targetPosition": { - "x": 10000, - "y": 21551 + "x": 10300, + "y": 24250 }, "floatingObject": { "isPinned": false, @@ -516,12 +516,12 @@ "id": "b6e3c87d-a11b-4b2a-b6a6-edc96375f5da", "savedPayload": { "position": { - "x": 10092.705098312485, - "y": 21836.316954888545 + "x": 10585.316954888545, + "y": 24157.294901687517 }, "targetPosition": { - "x": 10000, - "y": 21551 + "x": 10300, + "y": 24250 }, "floatingObject": { "isPinned": false, @@ -12448,12 +12448,12 @@ "id": "bb390957-b8a2-4a8a-9fbf-963ea20f6eaf", "savedPayload": { "position": { - "x": 9907.294901687515, - "y": 21836.316954888545 + "x": 10585.316954888545, + "y": 24342.705098312483 }, "targetPosition": { - "x": 10000, - "y": 21551 + "x": 10300, + "y": 24250 }, "floatingObject": { "isPinned": false, @@ -12508,12 +12508,12 @@ "id": "b046f4e4-40b1-4e47-8fed-75a6a5c6029d", "savedPayload": { "position": { - "x": 9635.273908764775, - "y": 22001.399212980523 + "x": 10750.399212980523, + "y": 24614.72609123522 }, "targetPosition": { - "x": 9757.294901687515, - "y": 21727.335575687743 + "x": 10476.335575687743, + "y": 24492.705098312483 }, "floatingObject": { "isPinned": false, @@ -12549,7 +12549,7 @@ "userDelegates": [ { "type": "User Delegate", - "name": "PLuv", + "name": "", "config": "{}", "project": "Governance", "id": "a2bbd553-e24c-44b8-a199-83114476ce24", @@ -12621,7 +12621,7 @@ "userDelegates": [ { "type": "User Delegate", - "name": "harrellbm", + "name": "", "config": "{}", "project": "Governance", "id": "2c79cd42-28a7-4a4b-ad3b-a8a29e993697", @@ -12693,7 +12693,7 @@ "userDelegates": [ { "type": "User Delegate", - "name": "Raplh2502", + "name": "", "config": "{}", "project": "Governance", "id": "94f99114-fc01-450e-9d9d-0b62c8ea393f", @@ -12765,7 +12765,7 @@ "userDelegates": [ { "type": "User Delegate", - "name": "cozed-gh", + "name": "", "config": "{}", "project": "Governance", "id": "ee1b374b-d4af-494c-93b8-3f83849d85f2", @@ -12837,7 +12837,7 @@ "userDelegates": [ { "type": "User Delegate", - "name": "Smidy13", + "name": "", "config": "{}", "project": "Governance", "id": "6a843bed-6392-4981-9e27-eff22f0f9fb1", @@ -12909,7 +12909,7 @@ "userDelegates": [ { "type": "User Delegate", - "name": "ssplatt", + "name": "", "config": "{}", "project": "Governance", "id": "b053ef35-1efe-46f4-81b2-d0c2e8ad0732", @@ -13007,12 +13007,12 @@ "id": "681ff42a-d5af-4fed-971e-935398dac2aa", "savedPayload": { "position": { - "x": 9270.142215762084, - "y": 21991.83790310513 + "x": 10740.83790310513, + "y": 24979.857784237916 }, "targetPosition": { - "x": 9458.938333077034, - "y": 21758.69411466804 + "x": 10507.694114668038, + "y": 24791.061666922964 }, "floatingObject": { "isPinned": false, @@ -13042,12 +13042,12 @@ "id": "ff3bc7ad-6051-4246-99fa-1210a3378a29", "savedPayload": { "position": { - "x": 8862.225195856072, - "y": 21821.411192628635 + "x": 10570.41119262863, + "y": 25387.774804143926 }, "targetPosition": { - "x": 9160.581764466553, - "y": 21790.052653648338 + "x": 10539.052653648334, + "y": 25089.418235533445 }, "floatingObject": { "isPinned": false, @@ -13066,12 +13066,12 @@ "id": "7f642170-d60b-41bc-85ae-dc64fbfc8b4c", "savedPayload": { "position": { - "x": 9160.581764466553, - "y": 21790.052653648338 + "x": 10539.052653648334, + "y": 25089.418235533445 }, "targetPosition": { - "x": 9458.938333077034, - "y": 21758.69411466804 + "x": 10507.694114668038, + "y": 24791.061666922964 }, "floatingObject": { "isPinned": false, @@ -13094,12 +13094,12 @@ "id": "e4be3ce4-3569-4d97-8d54-95bb4cfcb0c5", "savedPayload": { "position": { - "x": 9225.794544639943, - "y": 21569.897997353088 + "x": 10318.897997353088, + "y": 25024.205455360054 }, "targetPosition": { - "x": 9458.938333077034, - "y": 21758.69411466804 + "x": 10507.694114668038, + "y": 24791.061666922964 }, "floatingObject": { "isPinned": false, @@ -13117,12 +13117,12 @@ "id": "3ff7f410-911d-4cb8-9094-d816dee4dccb", "savedPayload": { "position": { - "x": 9458.938333077034, - "y": 21758.69411466804 + "x": 10507.694114668038, + "y": 24791.061666922964 }, "targetPosition": { - "x": 9757.294901687515, - "y": 21727.335575687743 + "x": 10476.335575687743, + "y": 24492.705098312483 }, "floatingObject": { "isPinned": false, @@ -13140,12 +13140,12 @@ "id": "4f35322c-3e7d-49f8-9706-10bf71f0d420", "savedPayload": { "position": { - "x": 9757.294901687515, - "y": 21727.335575687743 + "x": 10476.335575687743, + "y": 24492.705098312483 }, "targetPosition": { - "x": 10000, - "y": 21551 + "x": 10300, + "y": 24250 }, "floatingObject": { "isPinned": false, @@ -13163,18 +13163,18 @@ "id": "f8182a9c-f830-4ec1-a238-ac3a5efd69e6", "savedPayload": { "position": { - "x": 10000, - "y": 21551 + "x": 10300, + "y": 24250 }, "targetPosition": { "x": 10000, - "y": 21251 + "y": 24250 }, "floatingObject": { "isPinned": false, "isFrozen": false, "isCollapsed": false, - "angleToParent": 2, + "angleToParent": 1, "distanceToParent": 3, "arrangementStyle": 0 }, @@ -13190,12 +13190,181 @@ "id": "9870ca2a-cefc-484b-b7fc-206d62782ebc", "savedPayload": { "position": { - "x": 9700, - "y": 21251 + "x": 9850, + "y": 24509.807621135333 }, "targetPosition": { "x": 10000, - "y": 21251 + "y": 24250 + }, + "floatingObject": { + "isPinned": false, + "isFrozen": false, + "isCollapsed": false, + "angleToParent": 1, + "distanceToParent": 3, + "arrangementStyle": 0 + }, + "uiObject": { + "isRunning": false + } + } + }, + "signingAccounts": { + "type": "Signing Accounts", + "name": "New Signing Accounts", + "project": "Governance", + "signingAccounts": [ + { + "type": "Signing Account", + "name": "Social Trading Desktop", + "config": "{\n \"signature\": {\n \"message\": \"Luis-Fernando-Molina\",\n \"messageHash\": \"0x443abf3389e332a62d21b84dd12e271cb428d334195d3aeb986ca85ee53cccb9\",\n \"v\": \"0x1c\",\n \"r\": \"0x44cba4eeebb7f8bfb0d9fedb8b3c5c34ecd75b69969766435ae641547a8158c4\",\n \"s\": \"0x144b9076038085fa5fa51c381e76377cd2bcc87c835698eeb5195cceefb63ead\",\n \"signature\": \"0x44cba4eeebb7f8bfb0d9fedb8b3c5c34ecd75b69969766435ae641547a8158c4144b9076038085fa5fa51c381e76377cd2bcc87c835698eeb5195cceefb63ead1c\"\n }\n}", + "project": "Governance", + "id": "30858b11-5b8d-46c6-97f8-765e3676fc2f", + "savedPayload": { + "position": { + "x": 9550, + "y": 23990.192378864667 + }, + "targetPosition": { + "x": 9850, + "y": 23990.192378864667 + }, + "floatingObject": { + "isPinned": false, + "isFrozen": false, + "isCollapsed": false, + "angleToParent": 2, + "distanceToParent": 3, + "arrangementStyle": 0 + }, + "uiObject": { + "isRunning": false + } + } + }, + { + "type": "Signing Account", + "name": "Social Trading Server", + "config": "{\n \"signature\": {\n \"message\": \"Luis-Fernando-Molina\",\n \"messageHash\": \"0x443abf3389e332a62d21b84dd12e271cb428d334195d3aeb986ca85ee53cccb9\",\n \"v\": \"0x1b\",\n \"r\": \"0xc56bbcd7a99f47e20c5d83b1d4c102e1c7a223267b76f53200ff87fea7964e95\",\n \"s\": \"0x3e730a7d40a13199ef59f7a2a06a9d43da8f918e37afd6f706eceaea1fa8ed2d\",\n \"signature\": \"0xc56bbcd7a99f47e20c5d83b1d4c102e1c7a223267b76f53200ff87fea7964e953e730a7d40a13199ef59f7a2a06a9d43da8f918e37afd6f706eceaea1fa8ed2d1b\"\n }\n}", + "project": "Governance", + "id": "beff2691-f55f-401c-87a7-f6f7e59ebfb0", + "savedPayload": { + "position": { + "x": 9590.192378864669, + "y": 23840.192378864667 + }, + "targetPosition": { + "x": 9850, + "y": 23990.192378864667 + }, + "floatingObject": { + "isPinned": false, + "isFrozen": false, + "isCollapsed": false, + "angleToParent": 2, + "distanceToParent": 3, + "arrangementStyle": 0 + }, + "uiObject": { + "isRunning": false + } + } + }, + { + "type": "Signing Account", + "name": "Social Trading Mobile", + "config": "{\n \"signature\": {\n \"message\": \"Luis-Fernando-Molina\",\n \"messageHash\": \"0x443abf3389e332a62d21b84dd12e271cb428d334195d3aeb986ca85ee53cccb9\",\n \"v\": \"0x1c\",\n \"r\": \"0x502693fda93e9331e1eb1f5f6bd2896f6175d86816d11437ab8f4c51bdb95c5c\",\n \"s\": \"0x3c901bdb9f56f97cf558159c0f57c94dcade020a992be74a955a2cddf88047e1\",\n \"signature\": \"0x502693fda93e9331e1eb1f5f6bd2896f6175d86816d11437ab8f4c51bdb95c5c3c901bdb9f56f97cf558159c0f57c94dcade020a992be74a955a2cddf88047e11c\"\n }\n}", + "project": "Governance", + "id": "5828093e-65e1-4b18-9cbc-9ff33c98acc1", + "savedPayload": { + "position": { + "x": 9700, + "y": 23730.384757729335 + }, + "targetPosition": { + "x": 9850, + "y": 23990.192378864667 + }, + "floatingObject": { + "isPinned": false, + "isFrozen": false, + "isCollapsed": false, + "angleToParent": 2, + "distanceToParent": 3, + "arrangementStyle": 0 + }, + "uiObject": { + "isRunning": false + } + } + }, + { + "type": "Signing Account", + "name": "Social Trading Platform", + "config": "{\n \"signature\": {\n \"message\": \"Luis-Fernando-Molina\",\n \"messageHash\": \"0x443abf3389e332a62d21b84dd12e271cb428d334195d3aeb986ca85ee53cccb9\",\n \"v\": \"0x1c\",\n \"r\": \"0x363cd2c23617b65f0314a6b1b34c515e0fed9b2da62d53f2cf2609c1bc25e7fb\",\n \"s\": \"0x5e72414fcfe8a1308d7d82f275b3922cfe738374ed74e67086c59cfe7b6c0a24\",\n \"signature\": \"0x363cd2c23617b65f0314a6b1b34c515e0fed9b2da62d53f2cf2609c1bc25e7fb5e72414fcfe8a1308d7d82f275b3922cfe738374ed74e67086c59cfe7b6c0a241c\"\n }\n}", + "project": "Governance", + "id": "fa5647f8-42bc-4d7b-8137-401ac8b5433c", + "savedPayload": { + "position": { + "x": 9850, + "y": 23690.192378864667 + }, + "targetPosition": { + "x": 9850, + "y": 23990.192378864667 + }, + "floatingObject": { + "isPinned": false, + "isFrozen": false, + "isCollapsed": false, + "angleToParent": 2, + "distanceToParent": 3, + "arrangementStyle": 0 + }, + "uiObject": { + "isRunning": false + } + } + }, + { + "type": "Signing Account", + "name": "P2P Network Node", + "config": "{\n \"signature\": {\n \"message\": \"Luis-Fernando-Molina\",\n \"messageHash\": \"0x443abf3389e332a62d21b84dd12e271cb428d334195d3aeb986ca85ee53cccb9\",\n \"v\": \"0x1b\",\n \"r\": \"0x1df7b43b26e14a886b0702f3a43bfa7e078a3603a54d5befeb83ae451e423267\",\n \"s\": \"0x19cb2e7ba38cf49e5baa6ea20cbf895e86c9e010217a3f42e4df46b7b4e0bf36\",\n \"signature\": \"0x1df7b43b26e14a886b0702f3a43bfa7e078a3603a54d5befeb83ae451e42326719cb2e7ba38cf49e5baa6ea20cbf895e86c9e010217a3f42e4df46b7b4e0bf361b\"\n }\n}", + "project": "Governance", + "id": "e7066d66-9e36-4f38-963e-76b915b38c43", + "savedPayload": { + "position": { + "x": 10000, + "y": 23730.384757729335 + }, + "targetPosition": { + "x": 9850, + "y": 23990.192378864667 + }, + "floatingObject": { + "isPinned": false, + "isFrozen": false, + "isCollapsed": false, + "angleToParent": 2, + "distanceToParent": 3, + "arrangementStyle": 0 + }, + "uiObject": { + "isRunning": false + } + } + } + ], + "id": "1aae1fa4-e5cf-48de-a25e-20001523da70", + "savedPayload": { + "position": { + "x": 9850, + "y": 23990.192378864667 + }, + "targetPosition": { + "x": 10000, + "y": 24250 }, "floatingObject": { "isPinned": false, @@ -13213,17 +13382,17 @@ "id": "a8de78f0-c3e4-4a2a-b7e8-f659073969db", "savedPayload": { "position": { - "x": 39655.1724137931, - "y": 18250 + "x": 10000, + "y": 24250 }, "targetPosition": { - "x": 39655.1724137931, - "y": 18250 + "x": 10000, + "y": 24250 }, "floatingObject": { "isPinned": false, "isFrozen": false, - "isCollapsed": true, + "isCollapsed": false, "angleToParent": 1, "distanceToParent": 3, "arrangementStyle": 0 diff --git a/Projects/Governance/Plugins/User-Profiles/Test-Network-Client-Profile.json b/Projects/Governance/Plugins/User-Profiles/Test-Network-Client-Profile.json index c690c8490..bbd0152d0 100644 --- a/Projects/Governance/Plugins/User-Profiles/Test-Network-Client-Profile.json +++ b/Projects/Governance/Plugins/User-Profiles/Test-Network-Client-Profile.json @@ -62,12 +62,12 @@ "id": "baa2f02c-2920-4edb-a103-d452fc61d82f", "savedPayload": { "position": { - "x": 29310.344827586196, - "y": 24250 + "x": 30000, + "y": 18250 }, "targetPosition": { - "x": 29310.344827586196, - "y": 24250 + "x": 30000, + "y": 18250 }, "floatingObject": { "isPinned": false, diff --git a/Projects/Governance/Plugins/User-Profiles/Test-Network-Node-Profile.json b/Projects/Governance/Plugins/User-Profiles/Test-Network-Node-Profile.json index 8a2bcd5c7..03377a20e 100644 --- a/Projects/Governance/Plugins/User-Profiles/Test-Network-Node-Profile.json +++ b/Projects/Governance/Plugins/User-Profiles/Test-Network-Node-Profile.json @@ -62,11 +62,11 @@ "id": "36c2b050-631f-4291-987c-418adc94317d", "savedPayload": { "position": { - "x": 27586.206896551714, + "x": 40000, "y": 21250 }, "targetPosition": { - "x": 27586.206896551714, + "x": 40000, "y": 21250 }, "floatingObject": { diff --git a/Projects/Governance/Schemas/App-Schema/profile-constructor.json b/Projects/Governance/Schemas/App-Schema/profile-constructor.json index 5c4180bd3..b8cf9f043 100644 --- a/Projects/Governance/Schemas/App-Schema/profile-constructor.json +++ b/Projects/Governance/Schemas/App-Schema/profile-constructor.json @@ -18,6 +18,16 @@ "relatedUiObject": "Profile Constructor", "actionFunction": "payload.executeAction" }, + { + "action": "Add Signing Account", + "actionProject": "Governance", + "label": "Add Signing Account", + "askConfirmation": true, + "confirmationLabel": "Confirm to Proceed", + "workDoneLabel": "Done", + "relatedUiObject": "Profile Constructor", + "actionFunction": "payload.executeAction" + }, { "action": "Delete UI Object", "actionProject": "Foundations", diff --git a/Projects/Governance/Schemas/App-Schema/signing-account.json b/Projects/Governance/Schemas/App-Schema/signing-account.json new file mode 100644 index 000000000..3b73941f1 --- /dev/null +++ b/Projects/Governance/Schemas/App-Schema/signing-account.json @@ -0,0 +1,35 @@ +{ + "type": "Signing Account", + "menuItems": [ + { + "action": "Configure", + "actionFunction": "uiObject.configEditor.activate", + "actionProject": "Foundations", + "label": "Configure", + "iconPathOn": "configuration", + "iconPathOff": "configuration" + }, + { + "action": "Delete UI Object", + "actionProject": "Foundations", + "askConfirmation": true, + "confirmationLabel": "Confirm to Delete", + "label": "Delete", + "iconPathOn": "delete-entity", + "iconPathOff": "delete-entity", + "actionFunction": "payload.executeAction" + } + ], + "addLeftIcons": true, + "level": 2, + "attachingRules": { + "compatibleTypes": "->Signing Accounts->" + }, + "editors": { + "config": true + }, + "initialValues": { + "config": "{}" + }, + "propertyNameAtParent": "signingAccounts" +} \ No newline at end of file diff --git a/Projects/Governance/Schemas/App-Schema/signing-accounts.json b/Projects/Governance/Schemas/App-Schema/signing-accounts.json new file mode 100644 index 000000000..8a8b2dba4 --- /dev/null +++ b/Projects/Governance/Schemas/App-Schema/signing-accounts.json @@ -0,0 +1,29 @@ +{ + "type": "Signing Accounts", + "menuItems": [ + { + "action": "Delete UI Object", + "actionProject": "Foundations", + "askConfirmation": true, + "confirmationLabel": "Confirm to Delete", + "label": "Delete", + "iconPathOn": "delete-entity", + "iconPathOff": "delete-entity", + "actionFunction": "payload.executeAction" + } + ], + "addLeftIcons": true, + "level": 2, + "attachingRules": { + "compatibleTypes": "->User Profile->" + }, + "propertyNameAtParent": "signingAccounts", + "childrenNodesProperties": [ + { + "name": "signingAccounts", + "type": "array", + "childType": "Signing Account", + "autoAdd": false + } + ] +} \ No newline at end of file diff --git a/Projects/Governance/Schemas/App-Schema/user-profile.json b/Projects/Governance/Schemas/App-Schema/user-profile.json index a3e31924e..4fe356ae4 100644 --- a/Projects/Governance/Schemas/App-Schema/user-profile.json +++ b/Projects/Governance/Schemas/App-Schema/user-profile.json @@ -69,6 +69,12 @@ "type": "node", "childType": "Tokens Mined", "autoAdd": true + }, + { + "name": "signingAccounts", + "type": "node", + "childType": "Signing Accounts", + "autoAdd": false } ] } \ No newline at end of file diff --git a/Projects/Governance/UI/Function-Libraries/ActionSwitch.js b/Projects/Governance/UI/Function-Libraries/ActionSwitch.js index b9ac27c78..da9022ebe 100644 --- a/Projects/Governance/UI/Function-Libraries/ActionSwitch.js +++ b/Projects/Governance/UI/Function-Libraries/ActionSwitch.js @@ -38,6 +38,11 @@ function newGovernanceActionSwitch() { UI.projects.governance.functionLibraries.profileConstructor.buildProfile(action.node, action.rootNodes) break } + case 'Add Signing Account': + { + UI.projects.governance.functionLibraries.profileConstructor.addSigningAccount(action.node, action.rootNodes) + break + } case 'Add Missing Plugin User Profiles': { UI.projects.governance.functionLibraries.pluginsFunctions.addMissingPluginUserProfiles(action.node, action.rootNodes) diff --git a/Projects/Governance/UI/Function-Libraries/ProfileConstructor.js b/Projects/Governance/UI/Function-Libraries/ProfileConstructor.js index eb09d4f6f..b772610c8 100644 --- a/Projects/Governance/UI/Function-Libraries/ProfileConstructor.js +++ b/Projects/Governance/UI/Function-Libraries/ProfileConstructor.js @@ -1,6 +1,7 @@ function newGovernanceFunctionLibraryProfileConstructor() { let thisObject = { - buildProfile: buildProfile + buildProfile: buildProfile, + addSigningAccount: addSigningAccount } return thisObject @@ -18,7 +19,7 @@ function newGovernanceFunctionLibraryProfileConstructor() { if (githubUsername === undefined || githubUsername === "") { node.payload.uiObject.setErrorMessage( "githubUsername config property missing.", - UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR + UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR ) return } @@ -53,7 +54,7 @@ function newGovernanceFunctionLibraryProfileConstructor() { if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { node.payload.uiObject.setErrorMessage( 'Call via HTTP Interface failed.', - UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR + UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR ) return } @@ -67,14 +68,14 @@ function newGovernanceFunctionLibraryProfileConstructor() { node.payload.uiObject.setErrorMessage( 'Call to WEB3 Server failed. ' + response.error, UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR - ) + ) console.log('Call to WEB3 Server failed. ' + response.error) return } else { node.payload.uiObject.setErrorMessage( 'Call to WEB3 Server failed. Most likely the Mnemonic provided is not correct or you need to run node setup because a dependency is missing. ' + response.error, UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR - ) + ) console.log('Call to WEB3 Server failed. Most likely the Mnemonic provided is not correct or you need to run node setup because a dependency is missing. ' + response.error) return } @@ -103,7 +104,7 @@ function newGovernanceFunctionLibraryProfileConstructor() { node.payload.uiObject.setErrorMessage( 'Call via HTTP Interface failed.', UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR - ) + ) return } @@ -114,7 +115,7 @@ function newGovernanceFunctionLibraryProfileConstructor() { node.payload.uiObject.setErrorMessage( 'Call to WEB3 Server failed. ' + response.error, UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR - ) + ) console.log('Call to WEB3 Server failed. ' + response.error) return } @@ -145,12 +146,184 @@ function newGovernanceFunctionLibraryProfileConstructor() { node.payload.uiObject.setInfoMessage( "Profile Private Key has been successfully created. User Profile installed as a plugin and saved. Use the Private Key at a crypto wallet and delete this node once done.", UI.projects.governance.globals.designer.SET_INFO_COUNTER_FACTOR - ) + ) } else { node.payload.uiObject.setInfoMessage( "Mnemonic successfully imported. User Profile installed as a plugin and saved. Your external wallet was sucessfully linked to your profile.", UI.projects.governance.globals.designer.SET_INFO_COUNTER_FACTOR + ) + } + } + } + } + + function addSigningAccount( + node, + rootNodes + ) { + let githubUsername = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(node.payload, 'githubUsername') + let mnemonic = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(node.payload, 'mnemonic') + let signingAccounts + + if (githubUsername === undefined || githubUsername === "") { + node.payload.uiObject.setErrorMessage( + "githubUsername config property missing.", + UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR + ) + return + } + + /* + Some validations first... + */ + if (node.payload.referenceParent === undefined) { + node.payload.uiObject.setErrorMessage( + "The Profile Contstructor needs to reference your User Profile.", + UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR + ) + return + } + + if (node.payload.referenceParent.signingAccounts === undefined) { + signingAccounts = UI.projects.foundations.functionLibraries.uiObjectsFromNodes.addUIObject( + node.payload.referenceParent, + 'Signing Accounts', + UI.projects.foundations.spaces.designSpace.workspace.workspaceNode.rootNodes + ) + } else { + signingAccounts = node.payload.referenceParent.signingAccounts + } + + createWallet() + + function createWallet() { + let params + /* + If the user provides a mnemonic then we will get the private key and address from it, + otherwise, we will create a new private key and address. + */ + if (mnemonic === undefined || mnemonic === "") { + params = { + method: 'createWalletAccount', + entropy: node.id + (new Date()).valueOf() + } + } else { + params = { + method: 'mnemonicToPrivateKey', + mnemonic: mnemonic + } + } + + let url = 'WEB3' // We will access the default Client WEB3 endpoint. + + httpRequest(JSON.stringify(params), url, onResponse) + + function onResponse(err, data) { + /* Lets check the result of the call through the http interface */ + if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + node.payload.uiObject.setErrorMessage( + 'Call via HTTP Interface failed.', + UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR + ) + return + } + + let response = JSON.parse(data) + + /* Lets check the result of the method call */ + if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + + if (mnemonic === undefined || mnemonic === "") { + node.payload.uiObject.setErrorMessage( + 'Call to WEB3 Server failed. ' + response.error, + UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR ) + console.log('Call to WEB3 Server failed. ' + response.error) + return + } else { + node.payload.uiObject.setErrorMessage( + 'Call to WEB3 Server failed. Most likely the Mnemonic provided is not correct or you need to run node setup because a dependency is missing. ' + response.error, + UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR + ) + console.log('Call to WEB3 Server failed. Most likely the Mnemonic provided is not correct or you need to run node setup because a dependency is missing. ' + response.error) + return + } + } + + signUserProfileData(response.address, response.privateKey) + } + } + + function signUserProfileData(address, privateKey) { + + let request = { + url: 'WEB3', + params: { + method: "signData", + privateKey: privateKey, + data: githubUsername + } + } + + httpRequest(JSON.stringify(request.params), request.url, onResponse) + + function onResponse(err, data) { + /* Lets check the result of the call through the http interface */ + if (err.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + node.payload.uiObject.setErrorMessage( + 'Call via HTTP Interface failed.', + UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR + ) + return + } + + let response = JSON.parse(data) + + /* Lets check the result of the method call */ + if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) { + node.payload.uiObject.setErrorMessage( + 'Call to WEB3 Server failed. ' + response.error, + UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR + ) + console.log('Call to WEB3 Server failed. ' + response.error) + return + } + + createSigningAccount(response.signature) + } + + function createSigningAccount(signature) { + + let signingAccount = UI.projects.foundations.functionLibraries.uiObjectsFromNodes.addUIObject( + signingAccounts, + 'Signing Account', + UI.projects.foundations.spaces.designSpace.workspace.workspaceNode.rootNodes + ) + /* + We store at the User Profile the Signed githubUsername + */ + UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(signingAccount.payload, 'signature', signature) + + node.config = "{}" + UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'nodeName', signingAccount.name) + UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'nodeType', signingAccount.type) + UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'nodeId', signingAccount.id) + UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'address', address) + UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'privateKey', privateKey) + UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'githubUsername', githubUsername) + /* + Show nice message. + */ + if (mnemonic === undefined || mnemonic === "") { + node.payload.uiObject.setInfoMessage( + "Signing Account has been successfully created.", + UI.projects.governance.globals.designer.SET_INFO_COUNTER_FACTOR + ) + } else { + node.payload.uiObject.setInfoMessage( + "Mnemonic successfully imported. Signing Account has been successfully created.", + UI.projects.governance.globals.designer.SET_INFO_COUNTER_FACTOR + ) } } } diff --git a/Projects/Governance/UI/Function-Libraries/TokenMining.js b/Projects/Governance/UI/Function-Libraries/TokenMining.js index 68abe13c7..4ad90ec87 100644 --- a/Projects/Governance/UI/Function-Libraries/TokenMining.js +++ b/Projects/Governance/UI/Function-Libraries/TokenMining.js @@ -126,6 +126,7 @@ function newGovernanceFunctionLibraryTokenMining() { if (userProfile === undefined) { return } if (userProfile.payload === undefined) { return } if (userProfile.tokensMined === undefined) { return } + if (userProfile.tokensMined.payload === undefined) { return } if (userProfile.tokensMined.payload.tokensMined === undefined) { userProfile.tokensMined.payload.tokensMined = { awarded: 0, @@ -147,6 +148,8 @@ function newGovernanceFunctionLibraryTokenMining() { if (userProfile === undefined) { return } if (userProfile.payload === undefined) { return } if (userProfile.tokensMined === undefined) { return } + if (userProfile.tokensMined.payload === undefined) { return } + if (programNode.payload === undefined) { return } if (programNode.payload[programPropertyName] === undefined) { return } @@ -165,6 +168,7 @@ function newGovernanceFunctionLibraryTokenMining() { if (userProfile === undefined) { return } if (userProfile.payload === undefined) { return } if (userProfile.tokensMined === undefined) { return } + if (userProfile.tokensMined.payload === undefined) { return } const awarded = parseFloat(userProfile.tokensMined.payload.tokensMined.awarded.toFixed(0)).toLocaleString('en') const bonus = parseFloat(userProfile.tokensMined.payload.tokensMined.bonus.toFixed(0)).toLocaleString('en') diff --git a/Projects/Governance/UI/Function-Libraries/TokenPower.js b/Projects/Governance/UI/Function-Libraries/TokenPower.js index d588bc777..e2217ceab 100644 --- a/Projects/Governance/UI/Function-Libraries/TokenPower.js +++ b/Projects/Governance/UI/Function-Libraries/TokenPower.js @@ -187,6 +187,7 @@ function newGovernanceFunctionLibraryTokenPower() { if (childNode === undefined) { continue } if (childNode.type === "Delegation Program" && excludeDelegationProgram === true) { continue } if (childNode.type === "Tokens Mined") { continue } + if (childNode.type === "Signing Accounts") { continue } let percentage = getPercentage(childNode) @@ -205,6 +206,7 @@ function newGovernanceFunctionLibraryTokenPower() { if (childNode === undefined) { continue } if (childNode.type === "Delegation Program" && excludeDelegationProgram === true) { continue } if (childNode.type === "Tokens Mined") { continue } + if (childNode.type === "Signing Accounts") { continue } let percentage = getPercentage(childNode) if (percentage !== undefined && isNaN(percentage) !== true) { @@ -241,6 +243,7 @@ function newGovernanceFunctionLibraryTokenPower() { if (childNode === undefined) { continue } if (childNode.type === "Delegation Program" && excludeDelegationProgram === true) { continue } if (childNode.type === "Tokens Mined") { continue } + if (childNode.type === "Signing Accounts") { continue } let percentage = getPercentage(childNode) if (percentage === undefined || isNaN(percentage) === true) { @@ -262,6 +265,7 @@ function newGovernanceFunctionLibraryTokenPower() { if (childNode === undefined) { continue } if (childNode.type === "Delegation Program" && excludeDelegationProgram === true) { continue } if (childNode.type === "Tokens Mined") { continue } + if (childNode.type === "Signing Accounts") { continue } let percentage = getPercentage(childNode) if (percentage === undefined || isNaN(percentage) === true) { diff --git a/Projects/Governance/UI/Spaces/User-Profile-Space/UserProfile.js b/Projects/Governance/UI/Spaces/User-Profile-Space/UserProfile.js index d37d0f684..d38898d0e 100644 --- a/Projects/Governance/UI/Spaces/User-Profile-Space/UserProfile.js +++ b/Projects/Governance/UI/Spaces/User-Profile-Space/UserProfile.js @@ -23,6 +23,11 @@ function newGovernanceUserProfileSpace() { return thisObject function initialize() { + /* + If the workspace is not related to governance, then we exit the Intialize Function + */ + let governanceProject = UI.projects.foundations.spaces.designSpace.workspace.getProjectHeadByNodeType('Governance Project') + if (governanceProject === undefined) { return } /* Here we will run the distribution process, that in turn will run all the programs. */ @@ -40,11 +45,8 @@ function newGovernanceUserProfileSpace() { thisObject.container = newContainer() thisObject.container.initialize(MODULE_NAME) thisObject.container.isDraggeable = false - /* - If the workspace is not related to governance, then we exit the Intialize Function - */ + let userProfiles = UI.projects.foundations.spaces.designSpace.workspace.getHierarchyHeadsByNodeType('User Profile') - if (userProfiles.length === 0) { return } /* We are going to collapse all User Profiles to save processing resources at the UI */ @@ -330,6 +332,11 @@ function newGovernanceUserProfileSpace() { function physics() { if (UI.projects.foundations.spaces.designSpace.workspace === undefined) { return } /* + If the workspace is not related to governance, then we exit the Intialize Function + */ + let governanceProject = UI.projects.foundations.spaces.designSpace.workspace.getProjectHeadByNodeType('Governance Project') + if (governanceProject === undefined) { return } + /* Load the user profiles with Token Power. */ let userProfiles = UI.projects.foundations.spaces.designSpace.workspace.getHierarchyHeadsByNodeType('User Profile') @@ -368,7 +375,7 @@ function newGovernanceUserProfileSpace() { userProfile.payload.uiObject.setErrorMessage( 'Call via HTTP Interface failed.', UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR - ) + ) return } @@ -379,7 +386,7 @@ function newGovernanceUserProfileSpace() { userProfile.payload.uiObject.setErrorMessage( 'Call to WEB3 Server failed. ' + response.error, UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR - ) + ) console.log('Call to WEB3 Server failed. ' + response.error) return } @@ -411,7 +418,7 @@ function newGovernanceUserProfileSpace() { } else { userProfile.payload.uiObject.setInfoMessage(data, UI.projects.governance.globals.designer.SET_INFO_COUNTER_FACTOR - ) + ) userProfile.payload.blockchainTokens = Number(data.result) / 1000000000000000000 userProfile.payload.reputation = Math.min(reputationByAddress.get(blockchainAccount.toLowerCase()) | 0, userProfile.payload.blockchainTokens) } @@ -422,7 +429,7 @@ function newGovernanceUserProfileSpace() { if (userProfile.payload !== undefined) { userProfile.payload.uiObject.setErrorMessage(message, UI.projects.governance.globals.designer.SET_ERROR_COUNTER_FACTOR - ) + ) } waitingForResponses-- });