Governance: Signing of Profiles implemented

This commit is contained in:
Luis Fernando Molina committed 2021-06-15 17:32:37 +02:00
1 parent f0acdf1303
commit 12faa5b099
18 files changed
+256 -42

No files matched your search

+19
View File
@@ -132,6 +132,25 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
case 'signData': {
let serverResponse = await WEB3_SERVER.signData(
params.privateKey,
params.data
)
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
case 'recoverAddress': {
let serverResponse = await WEB3_SERVER.recoverAddress(
params.signature
)
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
default: {
respondWithContent(JSON.stringify({ error: 'Method ' + params.method + ' is invalid.' }), httpResponse)
}
+48 -11
View File
@@ -6,6 +6,8 @@ exports.newWeb3Server = function newWeb3Server() {
getNetworkClientStatus: getNetworkClientStatus,
createWalletAccount: createWalletAccount,
getWalletBalances: getWalletBalances,
signData: signData,
recoverAddress: recoverAddress,
initialize: initialize,
finalize: finalize,
run: run
@@ -56,7 +58,7 @@ exports.newWeb3Server = function newWeb3Server() {
return status
}
} catch (err) {
return { error: 'Could not connect to ' + key + '. ' + err.message + '.' }
return { error: 'Could not connect to ' + key + '. ' + err.stack + '.' }
}
}
@@ -73,7 +75,7 @@ exports.newWeb3Server = function newWeb3Server() {
}
} catch (err) {
return { error: 'Could not create the account. ' + err.message }
return { error: 'Could not create the account. ' + err.stack }
}
}
@@ -116,22 +118,22 @@ exports.newWeb3Server = function newWeb3Server() {
for (let j = 0; j < walletAccount.tokenBalances.length; j++) {
let tokenBalance = walletAccount.tokenBalances[j]
if (tokenBalance.referenceParent === undefined) { continue }
if (tokenBalance.referenceParent.parentNode === undefined) { continue }
if (tokenBalance.referenceParent.smartContracts === undefined) { continue }
if (tokenBalance.referenceParent === undefined) { continue }
if (tokenBalance.referenceParent.parentNode === undefined) { continue }
if (tokenBalance.referenceParent.smartContracts === undefined) { continue }
if (tokenBalance.referenceParent.config.codeName === undefined) {
tokenBalance.error = 'Reference Parent without config.codeName defined.'
continue
}
}
if (tokenBalance.referenceParent.smartContracts.config.address === undefined) {
tokenBalance.error = 'Reference Parent Smart Contract without config.address defined.'
continue
}
}
let tokenContractAddress = tokenBalance.referenceParent.smartContracts.config.address
// The minimum ABI to get ERC20 Token balance
// The minimum ABI to get ERC20 Token balance
let minABI = [
// balanceOf
{
@@ -152,8 +154,8 @@ exports.newWeb3Server = function newWeb3Server() {
];
let contract = new web3.eth.Contract(minABI, tokenContractAddress);
try {
try {
tokenBalance.value = await contract.methods.balanceOf(walletAccount.config.address).call()
} catch (err) {
if (err.message.indexOf('Provided address') >= 0) {
@@ -170,7 +172,7 @@ exports.newWeb3Server = function newWeb3Server() {
return responseData
}
} catch (err) {
return { error: 'Could not connect to ' + key + '. ' + err.message + '.' }
return { error: 'Could not connect to ' + key + '. ' + err.stack + '.' }
}
}
@@ -202,4 +204,39 @@ exports.newWeb3Server = function newWeb3Server() {
}
}
}
async function signData(privateKey, data) {
try {
let web3 = new Web3()
let signature = web3.eth.accounts.sign(data, privateKey)
return {
signature: signature,
result: 'Ok'
}
} catch (err) {
return { error: 'Could not sign the data. ' + err.stack }
}
}
async function recoverAddress(signature) {
try {
console.log("STRING:", signature)
let signatureObject = JSON.parse(signature)
console.log("OBJECT:", signatureObject)
let web3 = new Web3()
let address = web3.eth.accounts.recover(signatureObject)
return {
address: address,
result: 'Ok'
}
} catch (err) {
return { error: 'Could not recover address. ' + err.stack }
}
}
}
@@ -11,7 +11,7 @@ function newEthereumFunctionLibraryAccounts() {
let params = {
method: 'createWalletAccount',
entropy: walletAccountNode.id
entropy: walletAccountNode.id + (new Date()).valueOf()
}
let url = 'WEB3' // we don't need to ask this to any specific superalgos node.
@@ -52,7 +52,7 @@
},
{
"style": "Javascript",
"text": "UI.projects.foundations.utilities.nodeConfig.savePropertyAtNodeConfig(node.payload,'showPanels', true)"
"text": "UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload,'showPanels', true)"
},
{
"style": "Text",
@@ -511,7 +511,7 @@ function newLayer() {
}
}
} else {
UI.projects.foundations.utilities.nodeConfig.savePropertyAtNodeConfig(thisObject.payload, 'showPanels', panelsVisibleButton.showPanels)
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(thisObject.payload, 'showPanels', panelsVisibleButton.showPanels)
}
}
}
@@ -560,7 +560,7 @@ function newLayer() {
}
}
UI.projects.foundations.utilities.nodeConfig.savePropertyAtNodeConfig(thisObject.payload, 'status', thisObject.status)
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(thisObject.payload, 'status', thisObject.status)
let eventData = thisObject
thisObject.container.eventHandler.raiseEvent('Status Changed', eventData)
}
@@ -114,7 +114,7 @@ function newLayersPanel() {
}
function saveObjectStateVisibleLayers() {
UI.projects.foundations.utilities.nodeConfig.savePropertyAtNodeConfig(thisObject.payload, 'visibleLayers', desiredVisibleLayers)
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(thisObject.payload, 'visibleLayers', desiredVisibleLayers)
}
function saveObjectStatePanelLocation() {
@@ -122,7 +122,7 @@ function newLayersPanel() {
upOrDown: thisObject.upDownButton.status,
leftOrRight: thisObject.leftRightButton.status
}
UI.projects.foundations.utilities.nodeConfig.savePropertyAtNodeConfig(thisObject.payload, 'panelLocation', panelLocation)
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(thisObject.payload, 'panelLocation', panelLocation)
}
function readObjectState() {
@@ -1,12 +1,12 @@
function newFoundationsUtilitiesNodeConfig() {
let thisObject = {
savePropertyAtNodeConfig: savePropertyAtNodeConfig,
saveConfigProperty: saveConfigProperty,
loadConfigProperty: loadConfigProperty
}
return thisObject
function savePropertyAtNodeConfig(payload, propertyName, value) {
function saveConfigProperty(payload, propertyName, value) {
try {
let config = JSON.parse(payload.node.config)
config[propertyName] = value
@@ -1,7 +1,7 @@
{
"type": "User Profile",
"name": "Luis-Fernando-Molina",
"config": "{\n \"tokens\": 10000000,\n\"blockchainAccount\": \"0x9546eAA9380A224a56d7067D712296E9D40d40e1\"\n}",
"config": "{\n \"tokens\": 10000000,\n \"signature\": {\n \"message\": \"Luis-Fernando-Molina\",\n \"messageHash\": \"0x443abf3389e332a62d21b84dd12e271cb428d334195d3aeb986ca85ee53cccb9\",\n \"v\": \"0x1b\",\n \"r\": \"0x90293b042c180aa21b05f0356f31688c597be4ff2df136f63a2b8a899c658eb0\",\n \"s\": \"0x42abf909024d34217430e42ebadc96b7834218cc86a4c295a2ae419ff2fca6e3\",\n \"signature\": \"0x90293b042c180aa21b05f0356f31688c597be4ff2df136f63a2b8a899c658eb042abf909024d34217430e42ebadc96b7834218cc86a4c295a2ae419ff2fca6e31b\"\n }\n}",
"project": "Governance",
"contributionClaims": {
"type": "Contribution Claims",
@@ -3932,7 +3932,7 @@
"floatingObject": {
"isPinned": false,
"isFrozen": false,
"isCollapsed": true,
"isCollapsed": false,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
@@ -36,6 +36,13 @@
"relatedUiObject": "User Profile",
"actionFunction": "payload.executeAction"
},
{
"action": "Add UI Object",
"actionProject": "Foundations",
"actionFunction": "payload.executeAction",
"label": "Add Profile Constructor",
"relatedUiObject": "Profile Constructor"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
@@ -1,5 +1,5 @@
{
"type": "Signature",
"type": "Profile Constructor",
"menuItems": [
{
"action": "Configure",
@@ -8,6 +8,16 @@
"iconPathOn": "configuration",
"iconPathOff": "configuration"
},
{
"action": "Build Profile",
"actionProject": "Governance",
"label": "Build Profile",
"askConfirmation": true,
"confirmationLabel": "Confirm to Proceed",
"workDoneLabel": "Done",
"relatedUiObject": "Profile Constructor",
"actionFunction": "payload.executeAction"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
@@ -19,11 +29,12 @@
"actionFunction": "payload.executeAction"
}
],
"isHierarchyHead": true,
"editors": {
"config": true
},
"initialValues": {
"config": "{ \"privateKey\": \"\"}"
"config": "{ \"githubUsername\": \"\"}"
},
"addLeftIcons": true,
"level": 2,
@@ -35,13 +35,6 @@
"label": "Add User Referrer",
"relatedUiObject": "User Referrer"
},
{
"action": "Add UI Object",
"actionProject": "Signature",
"actionFunction": "payload.executeAction",
"label": "Add Signature",
"relatedUiObject": "Add Signature"
},
{
"action": "Delete UI Object",
"actionProject": "Foundations",
@@ -28,6 +28,11 @@ function newGovernanceActionSwitch() {
UI.projects.governance.functionLibraries.votes.installVotes(action.node, action.rootNodes)
break
}
case 'Build Profile':
{
UI.projects.governance.functionLibraries.profileConstructor.buildProfile(action.node, action.rootNodes)
break
}
case 'Add Missing Plugin User Profiles':
{
UI.projects.governance.functionLibraries.pluginsFunctions.addMissingPluginUserProfiles(action.node, action.rootNodes)
@@ -0,0 +1,97 @@
function newGovernanceFunctionLibraryProfileConstructor() {
let thisObject = {
buildProfile: buildProfile
}
return thisObject
function buildProfile(
node,
rootNodes
) {
/*
Some validations first...
*/
if (node.payload.referenceParent === undefined) {
node.payload.uiObject.setErrorMessage("You need to reference the node that contains the data to be signed.")
return
}
let data = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(node.payload, 'githubUsername')
if (data === undefined || data === "") {
node.payload.referenceParent.payload.uiObject.setErrorMessage("githubUsername config property missing.")
return
}
createNewAccount()
signUserProfileData()
function createNewAccount() {
let params = {
method: 'createWalletAccount',
entropy: node.id + (new Date()).valueOf()
}
let url = 'WEB3' // we don't need to ask this to any specific superalgos node.
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.')
walletAccountNode.payload.uiObject.menu.internalClick('Delete UI Object')
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)
return
}
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'address', response.address)
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload, 'privateKey', response.privateKey)
}
}
function signUserProfileData() {
let privateKey = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(node.payload, 'privateKey')
if (privateKey === undefined || privateKey === "") { return }
let request = {
url: 'WEB3',
params: {
method: "signData",
privateKey: privateKey,
data: data
}
}
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.')
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)
console.log('Call to WEB3 Server failed. ' + response.error)
return
}
UI.projects.foundations.utilities.nodeConfig.saveConfigProperty(node.payload.referenceParent.payload, 'signature', response.signature)
node.payload.uiObject.setInfoMessage("Profile Account has been successfully created.")
}
}
}
}
@@ -117,9 +117,9 @@ function newGovernanceFunctionLibraryUserReferrals() {
function distributeForProfile(userProfile) {
if (userProfile === undefined || userProfile.payload === undefined) { return }
let referringPower
let referringPower
if (userProfile.payload.blockchainTokens === undefined) {
referringPower = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(userProfile.payload, 'tokens')
return
} else {
referringPower = userProfile.payload.blockchainTokens
}
@@ -118,7 +118,7 @@ function newGovernanceFunctionLibraryVotes() {
if (userProfile.payload === undefined) { return }
let votes
if (userProfile.payload.blockchainTokens === undefined) {
votes = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(userProfile.payload, 'tokens')
return
} else {
votes = userProfile.payload.blockchainTokens
}
@@ -53,18 +53,58 @@ function newGovernanceUserProfileSpace() {
if (userProfile.payload === undefined) { continue }
if (userProfile.payload.blockchainTokens === undefined) {
let blockchainAccount = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(userProfile.payload, 'blockchainAccount')
if (blockchainAccount !== undefined && blockchainAccount !== "") {
setTimeout(getBlockchainTokens, timer, userProfile)
//userProfile.payload.blockchainTokens = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(userProfile.payload, 'tokens')
getBlockchainAccount(userProfile)
}
}
function getBlockchainAccount(userProfile) {
let signature = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(userProfile.payload, 'signature')
if (signature === undefined || signature === "") { return }
let request = {
url: 'WEB3',
params: {
method: "recoverAddress",
signature: JSON.stringify(signature)
}
}
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) {
userProfile.payload.uiObject.setErrorMessage('Call via HTTP Interface failed.')
return
}
let response = JSON.parse(data)
/* Lets check the result of the method call */
if (response.result !== GLOBAL.DEFAULT_OK_RESPONSE.result) {
userProfile.payload.uiObject.setErrorMessage('Call to WEB3 Server failed. ' + response.error)
console.log('Call to WEB3 Server failed. ' + response.error)
return
}
let blockchainAccount = response.address
if (
blockchainAccount !== undefined &&
blockchainAccount !== "" &&
userProfile.payload.blockchainTokens === undefined
) {
waitingForResponses++
userProfile.payload.blockchainTokens = 0 // We need to set this value here so that the next call to BSCSCAN is not done more than once.
setTimeout(getBlockchainTokens, timer, userProfile, blockchainAccount)
timer = timer + 5000
}
}
}
function getBlockchainTokens(userProfile) {
let blockchainAccount = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(userProfile.payload, 'blockchainAccount')
function getBlockchainTokens(userProfile, blockchainAccount) {
console.log('blockchainAccount ', blockchainAccount)
const url = "https://api.bscscan.com/api?module=account&action=tokenbalance&contractaddress=0xfb981ed9a92377ca4d75d924b9ca06df163924fd&address=" + blockchainAccount + "&tag=latest&apikey=YourApiKeyToken"
waitingForResponses++
fetch(url).then(function (response) {
return response.json();
@@ -74,9 +114,9 @@ function newGovernanceUserProfileSpace() {
userProfile.payload.blockchainTokens = Number(data.result) / 1000000000000000000
waitingForResponses--
}).catch(function (err) {
userProfile.payload.blockchainTokens = 0
console.log(err)
userProfile.payload.uiObject.setErrorMessage(err.message)
const message = err.message + ' - ' + 'Can not access BSC SCAN servers. Using tokens Config Property instead of blockchain data.'
console.log(message)
userProfile.payload.uiObject.setErrorMessage(message, 1000)
waitingForResponses--
});
}
+5
View File
@@ -997,6 +997,11 @@
"name": "User Referrals",
"propertyName": "userrReferrals",
"functionName": "newGovernanceFunctionLibraryUserReferrals"
},
{
"name": "Profile Constructor",
"propertyName": "profileConstructor",
"functionName": "newGovernanceFunctionLibraryProfileConstructor"
}
],
"utilities": [],