Governance: Signing of Profiles implemented
This commit is contained in:
1 parent
f0acdf1303
commit
12faa5b099
18 files changed
+256
-42
No files matched your search
@@ -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
@@ -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.
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
File renamed without changes.
@@ -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",
|
||||
|
||||
+13
-2
@@ -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--
|
||||
});
|
||||
}
|
||||
|
||||
@@ -997,6 +997,11 @@
|
||||
"name": "User Referrals",
|
||||
"propertyName": "userrReferrals",
|
||||
"functionName": "newGovernanceFunctionLibraryUserReferrals"
|
||||
},
|
||||
{
|
||||
"name": "Profile Constructor",
|
||||
"propertyName": "profileConstructor",
|
||||
"functionName": "newGovernanceFunctionLibraryProfileConstructor"
|
||||
}
|
||||
],
|
||||
"utilities": [],
|
||||
|
||||
Reference in new issue
Block a user