As applications continue to develop upon the currently Telos Decide functionality, it becomes necessary to extend the contract's functionality to improve the developer and user experience. Given the resources needed to modify the current smart contract, a simpler approach is needed that could be achieved with the code base as-is. This approach requires the work to be done on the application layer, and the creation of a standard to be adopted by application developers.
Specifically, this new specification proposes to add the following functionality through a JSON object in the existing content
field:
- Since this metadata will be residing within the
content
columns of the tables, this means that the hyperlinks to externally-hosted content files (typically PDFs, images, or Word documents) will be moved to a newcontentUrls
field. Critically, this means that any dapp reading thecontent
field will have to inspect its value to ascertain how the author of the Works proposal or regular ballot intends for it to be used (more on that later). - An
image
field for Works proposals or regular ballots that apps could display to give them context - A
displayText
field for Works proposals milestones and regular ballot options (excluding elections and leaderboards) that gives them a human-readable title, in lieu of the 12-character key, that can extend past 12 characters. For example, a poll could shown an option for a ballot on where to place an office location asJackson, Mississippi
instead ofjacksonmissi
. Additionally, the first milestone for a Works proposal looking for funding for a new park in Hong Kong could have its first milestone displayed asEnvironmental Impact Study
rather than a milestone ID of1
ormiss.option1
(which are not very informative) - An
imageUrls
field for each Works milestone and regular ballot option. These images will help give end-users context for milestones and ballot options, and help create a more visually-appealing dapp. For example, a poll on favorite ice cream flavors could display an image (or images) of each flavor, or the aforementioned Hong Kong park example could show an image of the proposed park location for its first milestone ("Environmental Impact Study"). - A
description
field for each Works milestone and regular ballot option. In addition to images and human-readable titles (displayText
), each milestone or option could have an associated long-form description that could give users a more comprehensive explanation of what they entail. While this field is designed to allow for more text than thedisplayText
field, the number of characters allowed by dapps should still be limited since this field is likely to be displayed next to each option in a list. An end-user should be able to quickly read through each milestone / option's descriptions to get an overview of how each item compares to the others in the list. More thorough descriptions should be placed within the proposal / ballot'scontentUrls
field. - A
version
field to identify the specification version (currentlyv2
) to help dapps properly parse the metadata.
Note: since JSON objects are extensible, dapps can also enter additional metadata into the JSON object although other dapps may not use said information. An example could be a producedBy
field that includes the information about the dapp that was used to help author the proposal / ballot.
Since users are currently using the content
field to enter a URL, and dapps are attempting to display the value as a hyperlink, this means that dapps will need to implement code that conditionally displays the information based on the value type. The code would look something like this:
let contentUrls, imageUrls, optionData
try {
const parsedContent = JSON.parse(content)
contentUrls = parsedContent.contentUrls
imageUrls = parsedContent.imageUrls
optionData = parsedContent.optionData
} catch (err) {
try {
contentUrl = new URL(content)
} catch (err) {
// do something else, likely `Qm...` hash for IPFS / dStor
}
}
Or, more succinctly (using destructuring)...
let contentUrls, imageUrls, optionData
try {
({ contentUrls, imageUrls, optionData } = JSON.parse(content))
} catch (err) {
try {
contentUrl = new URL(content)
} catch (err) {
// do something else, likely `Qm...` hash for IPFS / dStor
}
}
or
let content
try {
content = JSON.parse(content))
} catch (err) {
console.log('content not parsible')
}
console.log('first imageUrls item is: ', content?.imageUrls?[0])
Additionally, since each property is optional, the dapp will have to decide how to display the metadata conditionally based on whether or not each field exists (ie an option with an imageUrls
value but no displayText
value, etc)
The JSON object structure will look something like this for a Works proposal:
{
"version": "DCMSv2",
"imageUrls": array of strings, // URLs or hashes for images associated with Works proposal
"contentUrls": array of strings // URLs or hashes for documents associated with Works proposal
"milestonesData":[
{
"displayText": string, // relatively short human-readable title for first milestone
"description": string, // medium-length description for first milestone
"imageUrls": array of strings // URLs or hashes for imagees associated with first milestone
},{
"displayText": string, // relatively short human-readable title for second milestone
"description": string, // medium-length description for second milestone
"imageUrls": array of strings // URLs or hashes for image associated with second milestone
}
]
}
Likewise, the JSON object structure for a regular telos.decide
ballot would look something like this:
{
"version": "DCMSv2",
"imageUrls": array of strings, // URLs or hashes for images associated with Works proposal
"contentUrls": array of strings // URLs or hashes for documents associated with Works proposal
"optionData": {
"option1...": { // key (`option1...`) must be same as the actual option key in `options` field of the `ballots` table
"displayText": string, // relatively short human-readable title for first option
"description": string, // medium-length description for first option
"imageUrls": array of strings // URLs or hashes for images associated with first option
},
"option2...": { // key (`option2...`) must be same as the actual option key in `options` field of the `ballots`
"displayText": string, // relatively short human-readable title for second option
"description": string, // medium-length description for second option
"imageUrls": array of strings // URLs or hashes for images associated with second option
}
}
}
Since adding metadata to the content
field will take up memory, we recommend that dapps helping to author proposals and ballots consider omitting any fields that are not being used. For example, a milestone's imageUrls
field should be omitted if the user has not specified an image for that milestone.
Any questions or discussion regarding this specification can be had by contact the specification's author (Kylan Hurt, [email protected]) or using the Telos Governance Telegram Channel at the following URL:
https://t.me/telosgovernance