feat: Add initial code drop

This commit is contained in:
Nathan Woodburn 2024-07-19 12:33:57 +10:00
parent d968c9460c
commit 1ae919599b
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
4 changed files with 785 additions and 1 deletions

View File

@ -1 +1,9 @@
# australian_capital_dao
# Australian Capital DAO
This is a repo to hold the code for the ACD bot.
The bot uses N8N to automate the process of sending messages on any DAO transaction.
## Files
[n8n.json](/n8n.json) - The n8n workflow file (import this into n8n and add the necessary credentials)
[parser.js](/parser.js) - The script that parses the transaction data to be used to create the message
[message.js](/message.js) - The script that creates the message to send to the telegram and discord bots

75
message.js Normal file
View File

@ -0,0 +1,75 @@
function cleanJsonString(jsonString) {
// Remove invisible and non-printable characters (excluding newlines, carriage returns, and tabs)
const cleanedString = jsonString.replace(/[^\x20-\x7E\r\n\t]+/g, '');
// Remove leading or trailing whitespace
const trimmedString = cleanedString.trim();
// Ensure the string is enclosed within curly braces if its a JSON object
if (!trimmedString.startsWith('{') || !trimmedString.endsWith('}')) {
throw new Error('Invalid JSON format: Missing opening or closing brace.');
}
return trimmedString;
}
const addressNames = {
"0x6cb4b39bec23a921c9a20d061bf17d4640b0d39e":"woodburn.au"
};
function addressName(address) {
if (addressNames.hasOwnProperty(address)){
return addressNames[address];
}
return address;
}
var message = "New DAO transaction: ";
const parsed = $('Parser').first().json;
message += parsed.method;
if (parsed.method == "Submit Vote"){
message += "\n"+ addressName(parsed.member) + " voted ";
if (parsed.vote == 1){
message += "for";
} else {
message += "against";
}
message += " proposal #"+parsed.proposal;
message += " using " + parsed.votes + " votes";
}
else if (parsed.method == "Sponsor Proposal"){
message += "\n"+ addressName(parsed.member) + " sponsored ";
message += "proposal #"+parsed.proposal;
}
else if (parsed.method == "Submit Proposal"){
message += "\n"+ addressName($('HTTP Request').first().json.result.from);
message += " created proposal #" + parsed.proposal;
try {
const cleanedJsonString = cleanJsonString(parsed.data.details);
const details = JSON.parse(cleanedJsonString);
message += "\nProposal: " + details.title;
message += "\nDescription: " + details.description;
if (details.contentURI != ""){
message += "\nURL: " + details.contentURI;
}
}
catch (error){
message += "\nProposal details failed to parse";
message += error;
}
}
else if (parsed.method == "Process Proposal"){
message += "\n"+ addressName($('HTTP Request').first().json.result.from);
message += " executed proposal #" + parsed.proposal;
}
return {
"message":message,
"explorer":"https://optimistic.etherscan.io/tx/"+$('HTTP Request').first().json.result.transactionHash,
"proposalURL":"https://admin.daohaus.club/#/molochV3/0xa/0xf4604948ad5365840803297bf81cd9a46c36fce7/proposal/"+parsed.proposal
};

570
n8n.json Normal file
View File

@ -0,0 +1,570 @@
{
"name": "DAOHaus Alerts",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "530c914a-c732-4cb6-aaf1-2b722f9e7398",
"options": {}
},
"id": "def14e6f-a3fc-4844-8a94-b2d3a0a9bdb5",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1.1,
"position": [
660,
540
],
"webhookId": "530c914a-c732-4cb6-aaf1-2b722f9e7398"
},
{
"parameters": {
"method": "POST",
"url": "https://opt-mainnet.g.alchemy.com/v2/{alchemy_api_key}",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"id\": 1,\n \"jsonrpc\": \"2.0\",\n \"method\": \"eth_getTransactionReceipt\",\n \"params\": [\n\"{{ $json[\"body\"][\"event\"][\"activity\"][0][\"hash\"] }}\"\n ]\n}",
"options": {}
},
"id": "b97eaff4-26f2-4230-b3e2-3eb14b5cbbba",
"name": "HTTP Request",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
1160,
540
]
},
{
"parameters": {
"authentication": "webhook",
"options": {},
"embeds": {
"values": [
{
"description": "={{ $json[\"message\"] }}\n\n{{ $json[\"proposalURL\"] }}",
"author": "Australian Capital DAO",
"color": "#FF00D9",
"timestamp": "={{ ($now.minus({hours:10})).toFormat('yyyy-LL-dd HH:mm:ss') }}\n",
"title": "New DAO TX",
"url": "={{ $json[\"explorer\"] }}"
}
]
}
},
"id": "8e49fb62-06a1-4e51-898c-c17e1eb5dae0",
"name": "Discord2",
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1960,
420
],
"credentials": {
"discordWebhookApi": {
"id": "XzOnTbxymIRJMNFK",
"name": "N8N Channel"
}
}
},
{
"parameters": {
"chatId": "-4260162868",
"text": "={{ $json[\"message\"] }}",
"replyMarkup": "inlineKeyboard",
"inlineKeyboard": {
"rows": [
{
"row": {
"buttons": [
{
"text": "View tx on Etherscan",
"additionalFields": {
"url": "={{ $json[\"explorer\"] }}"
}
},
{
"text": "View Proposal",
"additionalFields": {
"url": "={{ $json[\"proposalURL\"] }}"
}
}
]
}
}
]
},
"additionalFields": {
"appendAttribution": false
}
},
"id": "2577c299-f86e-46d2-8799-e4e10875e3c7",
"name": "Telegram",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
1960,
640
],
"credentials": {
"telegramApi": {
"id": "VWQskb1y7DoFEnMh",
"name": "Telegram account"
}
}
},
{
"parameters": {
"updates": [
"message"
],
"additionalFields": {}
},
"id": "245d297b-8838-441e-b206-1f9cfdff8591",
"name": "Telegram Trigger",
"type": "n8n-nodes-base.telegramTrigger",
"typeVersion": 1.1,
"position": [
480,
940
],
"webhookId": "47a00ca7-1eb5-408d-8846-4af7f8b1e36b",
"credentials": {
"telegramApi": {
"id": "VWQskb1y7DoFEnMh",
"name": "Telegram account"
}
}
},
{
"parameters": {
"authentication": "webhook",
"content": "=New message from: {{ $json[\"message\"][\"from\"][\"first_name\"] }} (username: {{ $json[\"message\"][\"from\"][\"username\"] }}) (ID: {{ $json[\"message\"][\"from\"][\"id\"] }})\nChat Title: {{ $json[\"message\"][\"chat\"][\"title\"] }}\nChat ID: {{ $json[\"message\"][\"chat\"][\"id\"] }}\nChat Type: {{ $json[\"message\"][\"chat\"][\"type\"] }}\nMessage text: {{ $json[\"message\"][\"text\"] }}",
"options": {}
},
"id": "ce165915-be3e-49f2-b9e8-308f98e37ffd",
"name": "Discord3",
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1560,
900
],
"credentials": {
"discordWebhookApi": {
"id": "XzOnTbxymIRJMNFK",
"name": "N8N Channel"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "ca511fdf-180b-4236-b474-3bfe439ded0c",
"leftValue": "={{ $json[\"body\"][\"event\"][\"activity\"].length }}",
"rightValue": 1,
"operator": {
"type": "number",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "9536c45d-ae2a-472d-87f5-2b4535150128",
"name": "If1",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
880,
540
]
},
{
"parameters": {
"jsCode": "function hexToDecimal(hex) {\n return parseInt(hex, 16);\n}\nfunction stripExtraZeros(hexString) {\n // Remove leading zeros while keeping at least \"0x\" if present\n hexString = hexString.replace(/^0x0+/, '');\n return \"0x\"+hexString;\n}\n\n\n\nconst topics = {\n \"0xb9956173924f9c1204bae41dd3737d7ed1161846d13183879cdc03c4b9f8d019\":\"Submit Proposal\",\n \"0x786755545a7e27c12c90cc7f0934514d03fdacfe3684a340b8c4100531e7ecd5\":\"Submit Vote\",\n \"0xb4571f7e4e2c2b6e6185e47ab5caa5fe34087299bd49fbae945a4583101ee3f0\":\"Process Proposal\",\n \"0xd45ad122361f16d6f50d7c4a73638f20ee48eff6186af15224e2a4a1f6d50171\":\"Sponsor Proposal\"\n};\n\nvar Logs = $('HTTP Request').first().json.result.logs;\nvar topicsFromLogs = [];\n\nfor (var i = 0; i < Logs.length; i++) {\n var log = Logs[i];\n topicsFromLogs.push(...log.topics); // Using spread operator to append topics array\n}\n\nvar data = {\n \"method\":\"Unknown method\"\n};\n\nconst opts = {\n \"Submit Vote\":{\n 1:\"member\",\n 2:\"proposal\",\n 3:\"vote\"\n },\n \"Submit Proposal\":{\n 1:\"proposal\",\n 2:\"dataHash\"\n },\n \"Process Proposal\":{\n 1:\"member\",\n 2:\"proposal\",\n 3:\"vote\"\n },\n \"Sponsor Proposal\":{\n 1:\"member\",\n 2:\"proposal\",\n 3:\"votingStarts\"\n }\n}\n\n\n// Check each topic in the logs against the topics object\nfor (let i = 0; i < topicsFromLogs.length; i++) {\n const topic = topicsFromLogs[i];\n if (topics.hasOwnProperty(topic)) {\n data[\"method\"] = topics[topic];\n console.log('Matched Option:', data[\"method\"]);\n } else {\n if (opts.hasOwnProperty(data[\"method\"])){\n var keys = opts[data[\"method\"]];\n if (keys[i] != \"member\"){\n data[keys[i]] = hexToDecimal(topic); \n } else {\n data[keys[i]] = stripExtraZeros(topic);\n }\n }\n }\n}\nfunction hexToUtf8(hexStr) {\n return Buffer.from(hexStr, 'hex').toString('utf8');\n}\n\nif (data[\"method\"]== \"Submit Proposal\"){\n const hexData = $('HTTP Request').first().json.result.logs[0].data;\n // Extracting segments from hexData (assuming it's already defined)\n const votingPeriodHex = hexData.slice(2, 66); // 64 characters (32 bytes) for votingPeriod\n const proposalDataHex = hexData.slice(66, 130); // 64 characters (32 bytes) for proposalData\n const expirationHex = hexData.slice(130, 194); // 64 characters (32 bytes) for expiration\n const baalGasHex = hexData.slice(194, 258); // 64 characters (32 bytes) for baalGas\n const selfSponsorHex = hexData.slice(258, 322); // 64 characters (32 bytes) for selfSponsor\n const timestampHex = hexData.slice(322, 386); // 64 characters (32 bytes) for timestamp\n const detailsHex = hexData.slice(386); // Remaining part for details\n \n // Decode hex segments into decimal or string format\n const votingPeriod = hexToDecimal(votingPeriodHex);\n const proposalData = proposalDataHex;\n const expiration = hexToDecimal(expirationHex);\n const baalGas = hexToDecimal(baalGasHex);\n const selfSponsor = hexToDecimal(selfSponsorHex);\n const timestamp = hexToDecimal(timestampHex);\n \n let detailsObj;\n detailsObj = hexToUtf8(detailsHex);\n const jsonStringStart = detailsObj.indexOf('{\"');\n if (jsonStringStart !== -1) {\n detailsObj = detailsObj.slice(jsonStringStart);\n }\n\n \n // Construct the JSON object\n const jsonObject = {\n votingPeriod: votingPeriod,\n proposalData: proposalData,\n expiration: expiration,\n baalGas: baalGas,\n selfSponsor: selfSponsor,\n timestamp: timestamp,\n details: detailsObj\n };\n\n data['data'] = jsonObject;\n} else if (data[\"method\"]== \"Submit Vote\"){\n const hexData = $('HTTP Request').first().json.result.logs[0].data;\n data[\"votes\"]= hexToDecimal(hexData)/1000000000000000000;\n} else if (data[\"method\"]== \"Process Proposal\"){\n var logData = []\n for (var i = 0; i < Logs.length; i++) {\n if (Logs[i].topics[0]==\"0xb4571f7e4e2c2b6e6185e47ab5caa5fe34087299bd49fbae945a4583101ee3f0\"){\n data[\"proposal\"] = hexToDecimal(Logs[i].topics[1]);\n }\n}\n\n\n}\n\nconsole.log(data);\nreturn data;\n"
},
"id": "eb7edb1c-a29d-4a55-9e69-3526edb2194a",
"name": "Parser",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1360,
540
]
},
{
"parameters": {
"jsCode": "function cleanJsonString(jsonString) {\n // Remove invisible and non-printable characters (excluding newlines, carriage returns, and tabs)\n const cleanedString = jsonString.replace(/[^\\x20-\\x7E\\r\\n\\t]+/g, '');\n \n // Remove leading or trailing whitespace\n const trimmedString = cleanedString.trim();\n \n // Ensure the string is enclosed within curly braces if its a JSON object\n if (!trimmedString.startsWith('{') || !trimmedString.endsWith('}')) {\n throw new Error('Invalid JSON format: Missing opening or closing brace.');\n }\n\n return trimmedString;\n}\n\nconst addressNames = {\n \"0x6cb4b39bec23a921c9a20d061bf17d4640b0d39e\":\"woodburn.au\" \n};\nfunction addressName(address) {\n if (addressNames.hasOwnProperty(address)){\n return addressNames[address];\n }\n return address;\n}\n\n\n\nvar message = \"New DAO transaction: \";\nconst parsed = $('Parser').first().json;\nmessage += parsed.method;\n\nif (parsed.method == \"Submit Vote\"){\n message += \"\\n\"+ addressName(parsed.member) + \" voted \";\n if (parsed.vote == 1){\n message += \"for\";\n } else {\n message += \"against\";\n }\n message += \" proposal #\"+parsed.proposal;\n message += \" using \" + parsed.votes + \" votes\";\n}\nelse if (parsed.method == \"Sponsor Proposal\"){\n message += \"\\n\"+ addressName(parsed.member) + \" sponsored \";\n message += \"proposal #\"+parsed.proposal;\n}\nelse if (parsed.method == \"Submit Proposal\"){\n message += \"\\n\"+ addressName($('HTTP Request').first().json.result.from);\n message += \" created proposal #\" + parsed.proposal;\n try {\n const cleanedJsonString = cleanJsonString(parsed.data.details);\n const details = JSON.parse(cleanedJsonString);\n message += \"\\nProposal: \" + details.title;\n message += \"\\nDescription: \" + details.description;\n\n if (details.contentURI != \"\"){\n message += \"\\nURL: \" + details.contentURI;\n }\n }\n catch (error){\n message += \"\\nProposal details failed to parse\";\n message += error;\n }\n}\nelse if (parsed.method == \"Process Proposal\"){\n message += \"\\n\"+ addressName($('HTTP Request').first().json.result.from);\n message += \" executed proposal #\" + parsed.proposal;\n}\n\n\n// message += \"\\n\\nhttps://optimistic.etherscan.io/tx/\";\n// message += $('HTTP Request').first().json.result.transactionHash;\n// message += \"\\nhttps://admin.daohaus.club/#/molochV3/0xa/0xf4604948ad5365840803297bf81cd9a46c36fce7/proposal/\"\n// message += parsed.proposal;\n\nreturn {\n \"message\":message,\n \"explorer\":\"https://optimistic.etherscan.io/tx/\"+$('HTTP Request').first().json.result.transactionHash,\n\"proposalURL\":\"https://admin.daohaus.club/#/molochV3/0xa/0xf4604948ad5365840803297bf81cd9a46c36fce7/proposal/\"+parsed.proposal\n};\n\n"
},
"id": "22c0ce02-9388-4dca-ac32-3fda22a4f280",
"name": "Create message",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1580,
500
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "21456147-b1d5-4cb6-877d-ffe7c567eec6",
"leftValue": "={{ $json[\"message\"][\"entities\"].length }}",
"rightValue": 0,
"operator": {
"type": "number",
"operation": "notEquals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "cc10be80-8d35-43d0-84a7-78440d3b7801",
"name": "If",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
660,
1100
]
},
{
"parameters": {
"chatId": "={{ $json[\"message\"][\"chat\"][\"id\"] }}",
"text": "Pong",
"additionalFields": {
"appendAttribution": false,
"reply_to_message_id": "={{ $json[\"message\"][\"message_id\"] }}"
}
},
"id": "d6d67b9f-279f-4618-a2d4-14737449131f",
"name": "Ping Pong",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
1280,
1000
],
"credentials": {
"telegramApi": {
"id": "VWQskb1y7DoFEnMh",
"name": "Telegram account"
}
}
},
{
"parameters": {
"chatId": "={{ $json[\"message\"][\"chat\"][\"id\"] }}",
"text": "Sure here is the link to the Australian Capital DAO",
"replyMarkup": "inlineKeyboard",
"inlineKeyboard": {
"rows": [
{
"row": {
"buttons": [
{
"text": "Go to DAO Page",
"additionalFields": {
"url": "https://admin.daohaus.club/#/molochv3/0xa/0xf4604948ad5365840803297bf81cd9a46c36fce7"
}
}
]
}
}
]
},
"additionalFields": {
"appendAttribution": false,
"reply_to_message_id": "={{ $json[\"message\"][\"message_id\"] }}"
}
},
"id": "402477d9-701c-4d08-80d9-608c4b702881",
"name": "Dao Link",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [
1280,
1160
],
"credentials": {
"telegramApi": {
"id": "VWQskb1y7DoFEnMh",
"name": "Telegram account"
}
}
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json[\"message\"][\"text\"] }}",
"rightValue": "/ping",
"operator": {
"type": "string",
"operation": "startsWith"
}
}
],
"combinator": "and"
}
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "4c2f8464-cf52-467d-a219-e75793559353",
"leftValue": "={{ $json[\"message\"][\"text\"] }}",
"rightValue": "/dao",
"operator": {
"type": "string",
"operation": "startsWith"
}
}
],
"combinator": "and"
}
}
]
},
"options": {}
},
"id": "eb1090bf-5f39-4c8e-ac85-ed2e7b59e76e",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"typeVersion": 3,
"position": [
960,
1080
]
}
],
"pinData": {
"Webhook": [
{
"json": {
"headers": {
"host": "n8n.woodburn.au",
"x-forwarded-scheme": "https",
"x-forwarded-proto": "https",
"x-forwarded-for": "118.208.168.176",
"x-real-ip": "118.208.168.176",
"content-length": "845",
"content-type": "application/json",
"user-agent": "insomnia/9.3.1",
"accept": "*/*"
},
"params": {},
"query": {},
"body": {
"webhookId": "wh_mvrhnhyqysvf70qj",
"id": "whevt_rc0mq97pww9a7leo",
"createdAt": "2024-07-18T05:46:57.824Z",
"type": "ADDRESS_ACTIVITY",
"event": {
"network": "OPT_MAINNET",
"activity": [
{
"fromAddress": "0xf4604948ad5365840803297bf81cd9a46c36fce7",
"toAddress": "0x35d3efffa0e6c63ee5c7e8c7dd7e7d6e961a6689",
"blockNum": "0x752694c",
"hash": "0x02d3f83b6663df1edc04db532190a17ef7a3267ca3104d7c36435eb2aad12b3f",
"value": 0,
"typeTraceAddress": "STATICCALL_0_0",
"asset": "ETH",
"category": "internal",
"rawContract": {
"rawValue": "0x0",
"decimals": 18
}
}
]
}
}
}
}
],
"Telegram Trigger": [
{
"json": {
"update_id": 328606253,
"message": {
"message_id": 34,
"from": {
"id": 5166524939,
"is_bot": false,
"first_name": "Nathan.Woodburn/",
"username": "nathanwoodburn",
"language_code": "en"
},
"chat": {
"id": -4260162868,
"title": "Test Bot Group",
"type": "group",
"all_members_are_administrators": true
},
"date": 1721355038,
"text": "/dao@australian_capital_dao_bot",
"entities": [
{
"offset": 0,
"length": 31,
"type": "bot_command"
}
]
}
}
}
]
},
"connections": {
"Webhook": {
"main": [
[
{
"node": "If1",
"type": "main",
"index": 0
}
]
]
},
"HTTP Request": {
"main": [
[
{
"node": "Parser",
"type": "main",
"index": 0
}
]
]
},
"Telegram Trigger": {
"main": [
[
{
"node": "Discord3",
"type": "main",
"index": 0
},
{
"node": "If",
"type": "main",
"index": 0
}
]
]
},
"If1": {
"main": [
[
{
"node": "HTTP Request",
"type": "main",
"index": 0
}
]
]
},
"Parser": {
"main": [
[
{
"node": "Create message",
"type": "main",
"index": 0
}
]
]
},
"Create message": {
"main": [
[
{
"node": "Discord2",
"type": "main",
"index": 0
},
{
"node": "Telegram",
"type": "main",
"index": 0
}
]
]
},
"If": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "Ping Pong",
"type": "main",
"index": 0
}
],
[
{
"node": "Dao Link",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "4d31c171-d9e4-47a8-8a76-4a56b6fd3101",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "716fbd4310435337bb8df7c59b7984bfb867d59d9129682cbc4d8523a713d40e"
},
"id": "POAYZQJI8PYGlKWt",
"tags": []
}

131
parser.js Normal file
View File

@ -0,0 +1,131 @@
function hexToDecimal(hex) {
return parseInt(hex, 16);
}
function stripExtraZeros(hexString) {
// Remove leading zeros while keeping at least "0x" if present
hexString = hexString.replace(/^0x0+/, '');
return "0x"+hexString;
}
const topics = {
"0xb9956173924f9c1204bae41dd3737d7ed1161846d13183879cdc03c4b9f8d019":"Submit Proposal",
"0x786755545a7e27c12c90cc7f0934514d03fdacfe3684a340b8c4100531e7ecd5":"Submit Vote",
"0xb4571f7e4e2c2b6e6185e47ab5caa5fe34087299bd49fbae945a4583101ee3f0":"Process Proposal",
"0xd45ad122361f16d6f50d7c4a73638f20ee48eff6186af15224e2a4a1f6d50171":"Sponsor Proposal"
};
var Logs = $('HTTP Request').first().json.result.logs;
var topicsFromLogs = [];
for (var i = 0; i < Logs.length; i++) {
var log = Logs[i];
topicsFromLogs.push(...log.topics); // Using spread operator to append topics array
}
var data = {
"method":"Unknown method" // Default value
};
const opts = {
"Submit Vote":{
1:"member",
2:"proposal",
3:"vote"
},
"Submit Proposal":{
1:"proposal",
2:"dataHash"
},
"Process Proposal":{
1:"member",
2:"proposal",
3:"vote"
},
"Sponsor Proposal":{
1:"member",
2:"proposal",
3:"votingStarts"
}
}
// Check each topic in the logs against the topics object
for (let i = 0; i < topicsFromLogs.length; i++) {
const topic = topicsFromLogs[i];
if (topics.hasOwnProperty(topic)) {
data["method"] = topics[topic];
console.log('Matched Option:', data["method"]);
} else {
if (opts.hasOwnProperty(data["method"])){
var keys = opts[data["method"]];
if (keys[i] != "member"){
data[keys[i]] = hexToDecimal(topic);
} else {
data[keys[i]] = stripExtraZeros(topic);
}
}
}
}
function hexToUtf8(hexStr) {
return Buffer.from(hexStr, 'hex').toString('utf8');
}
// Extracting data for specific methods
if (data["method"]== "Submit Proposal"){
const hexData = $('HTTP Request').first().json.result.logs[0].data;
// Extracting segments from hexData (assuming it's already defined)
const votingPeriodHex = hexData.slice(2, 66); // 64 characters (32 bytes) for votingPeriod
const proposalDataHex = hexData.slice(66, 130); // 64 characters (32 bytes) for proposalData
const expirationHex = hexData.slice(130, 194); // 64 characters (32 bytes) for expiration
const baalGasHex = hexData.slice(194, 258); // 64 characters (32 bytes) for baalGas
const selfSponsorHex = hexData.slice(258, 322); // 64 characters (32 bytes) for selfSponsor
const timestampHex = hexData.slice(322, 386); // 64 characters (32 bytes) for timestamp
const detailsHex = hexData.slice(386); // Remaining part for details
// Decode hex segments into decimal or string format
const votingPeriod = hexToDecimal(votingPeriodHex);
const proposalData = proposalDataHex;
const expiration = hexToDecimal(expirationHex);
const baalGas = hexToDecimal(baalGasHex);
const selfSponsor = hexToDecimal(selfSponsorHex);
const timestamp = hexToDecimal(timestampHex);
let detailsObj;
detailsObj = hexToUtf8(detailsHex);
const jsonStringStart = detailsObj.indexOf('{"');
if (jsonStringStart !== -1) {
detailsObj = detailsObj.slice(jsonStringStart);
}
// Construct the JSON object
const jsonObject = {
votingPeriod: votingPeriod,
proposalData: proposalData,
expiration: expiration,
baalGas: baalGas,
selfSponsor: selfSponsor,
timestamp: timestamp,
details: detailsObj
};
data['data'] = jsonObject;
} else if (data["method"]== "Submit Vote"){
const hexData = $('HTTP Request').first().json.result.logs[0].data;
data["votes"]= hexToDecimal(hexData)/1000000000000000000;
} else if (data["method"]== "Process Proposal"){
var logData = []
for (var i = 0; i < Logs.length; i++) {
if (Logs[i].topics[0]=="0xb4571f7e4e2c2b6e6185e47ab5caa5fe34087299bd49fbae945a4583101ee3f0"){
data["proposal"] = hexToDecimal(Logs[i].topics[1]);
}
}
}
console.log(data);
return data;