# Module Service - Voting
## Overview
The Voting Service implements a decentralized governance and community voting system within the Cellframe SDK. This service provides comprehensive functionality for creating proposals, managing voting processes, and collecting community decisions with configurable parameters, weighted voting, and time-limited proposals.
*Based on: `dap_chain_net_srv_voting.h`, `dap_chain_net_srv_voting.c`*
**Service UID:** `DAP_CHAIN_NET_SRV_VOTING_ID` (0x6)
## Document Structure
- [[#Overview|Overview]]
- [[#Voting Structures|Voting Structures]]
- [[#dap_chain_net_vote_info_t|dap_chain_net_vote_info_t - Main voting information]]
- [[#dap_chain_net_vote_info_option_t|dap_chain_net_vote_info_option_t - Vote option structure]]
- [[#Voting Functions|Voting Functions]]
- [[#Proposal Management|Proposal Management Functions]]
- [[#Voting Operations|Voting Operations Functions]]
- [[#Information Retrieval|Information Retrieval Functions]]
- [[#Error Codes|Error Codes]]
- [[#Typical Examples|Typical Examples]]
## Voting Structures
### dap_chain_net_vote_info_t
Main voting information structure containing all data for a voting proposal.
```c
typedef struct dap_chain_net_vote_info {
dap_hash_fast_t hash; // Unique vote hash identifier
dap_chain_net_id_t net_id; // Network ID where vote occurs
bool is_expired; // Expiration status flag
dap_time_t expired; // Expiration timestamp
bool is_max_count_votes; // Vote count limit enabled
uint64_t max_count_votes; // Maximum votes allowed
bool is_changing_allowed; // Vote changing permission
bool is_delegate_key_required; // Delegate key requirement
struct {
size_t question_size; // Question text size
char *question_str; // Question text content
} question;
struct {
uint64_t count_option; // Number of vote options
dap_chain_net_vote_info_option_t **options; // Array of vote options
} options;
} dap_chain_net_vote_info_t;
```
**Fields:**
- `hash` - Unique identifier for this voting proposal
- `net_id` - Network where the voting takes place
- `is_expired` - Flag indicating if voting period has ended
- `expired` - Unix timestamp when voting expires
- `is_max_count_votes` - Whether there's a maximum vote limit
- `max_count_votes` - Maximum number of votes allowed
- `is_changing_allowed` - Whether voters can change their votes
- `is_delegate_key_required` - Whether delegate key is required to vote
- `question.question_size` - Size of the question text in bytes
- `question.question_str` - The actual question being voted on
- `options.count_option` - Number of available voting options
- `options.options` - Array of voting options with details
### dap_chain_net_vote_info_option_t
Structure representing a single voting option with vote tracking.
```c
typedef struct dap_chain_net_vote_info_option {
uint64_t option_idx; // Option index number
uint64_t votes_count; // Number of votes received
uint256_t weight; // Total voting weight
uint64_t description_size; // Description text size
char *description; // Option description text
dap_list_t *hashes_tx_votes; // List of vote transaction hashes
} dap_chain_net_vote_info_option_t;
```
**Fields:**
- `option_idx` - Sequential index of this option (0, 1, 2, etc.)
- `votes_count` - Total number of individual votes for this option
- `weight` - Cumulative voting weight (token-based weighting)
- `description_size` - Size of the description text in bytes
- `description` - Human-readable description of this voting option
- `hashes_tx_votes` - List of transaction hashes for votes on this option
## Voting Functions
### Proposal Management
#### `dap_chain_net_vote_create()`
Creates a new voting proposal with specified parameters.
```c
int dap_chain_net_vote_create(
const char *a_question,
dap_list_t *a_options,
dap_time_t a_expire_vote,
uint64_t a_max_vote,
uint256_t a_fee,
bool a_delegated_key_required,
bool a_vote_changing_allowed,
dap_chain_wallet_t *a_wallet,
dap_chain_net_t *a_net,
const char *a_token_ticker,
const char *a_hash_out_type,
char **a_hash_output
);
```
**Parameters:**
- `a_question` (const char *) - Question text for the proposal
- `a_options` (dap_list_t *) - List of voting options (strings)
- `a_expire_vote` (dap_time_t) - Expiration timestamp
- `a_max_vote` (uint64_t) - Maximum number of votes (0 for unlimited)
- `a_fee` (uint256_t) - Creation fee amount
- `a_delegated_key_required` (bool) - Require delegate key to vote
- `a_vote_changing_allowed` (bool) - Allow voters to change their votes
- `a_wallet` (dap_chain_wallet_t *) - Creator's wallet
- `a_net` (dap_chain_net_t *) - Target network
- `a_token_ticker` (const char *) - Token used for fees
- `a_hash_out_type` (const char *) - Output hash format ("hex" or "base58")
- `a_hash_output` (char **) - Output voting hash
**Returns:**
- `DAP_CHAIN_NET_VOTE_CREATE_OK` - Proposal created successfully
- `DAP_CHAIN_NET_VOTE_CREATE_LENGTH_QUESTION_OVERSIZE_MAX` - Question too long
- `DAP_CHAIN_NET_VOTE_CREATE_COUNT_OPTION_OVERSIZE_MAX` - Too many options
- `DAP_CHAIN_NET_VOTE_CREATE_NOT_ENOUGH_FUNDS_TO_TRANSFER` - Insufficient funds
**Error Conditions:**
- Returns error if question text exceeds maximum length
- Returns error if number of options exceeds limit
- Returns error if wallet has insufficient balance for fee
- Returns error if expiration time is in the past
### Voting Operations
#### `dap_chain_net_vote_voting()`
Casts a vote for a specific proposal option.
```c
int dap_chain_net_vote_voting(
dap_cert_t *a_cert,
uint256_t a_fee,
dap_chain_wallet_t *a_wallet,
dap_hash_fast_t a_hash,
uint64_t a_option_idx,
dap_chain_net_t *a_net,
const char *a_hash_out_type,
char **a_hash_tx_out
);
```
**Parameters:**
- `a_cert` (dap_cert_t *) - Certificate for signing (if required)
- `a_fee` (uint256_t) - Voting transaction fee
- `a_wallet` (dap_chain_wallet_t *) - Voter's wallet
- `a_hash` (dap_hash_fast_t) - Hash of the voting proposal
- `a_option_idx` (uint64_t) - Index of chosen option
- `a_net` (dap_chain_net_t *) - Network for the vote
- `a_hash_out_type` (const char *) - Output hash format
- `a_hash_tx_out` (char **) - Output transaction hash
**Returns:**
- `DAP_CHAIN_NET_VOTE_VOTING_OK` - Vote cast successfully
- `DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_FIND_VOTE` - Proposal not found
- `DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED` - Voting period expired
- `DAP_CHAIN_NET_VOTE_VOTING_INVALID_OPTION_INDEX` - Invalid option selected
### Information Retrieval
#### `dap_chain_net_vote_list()`
Retrieves list of all voting proposals on a network.
```c
dap_list_t *dap_chain_net_vote_list(dap_chain_net_t *a_net);
```
**Parameters:**
- `a_net` (dap_chain_net_t *) - Target network
**Returns:**
- List of `dap_chain_net_vote_info_t` structures
- `NULL` if no votes available or error occurred
#### `dap_chain_net_vote_extract_info()`
Extracts detailed information about a specific vote.
```c
dap_chain_net_vote_info_t *dap_chain_net_vote_extract_info(
dap_chain_net_t *a_net,
dap_hash_fast_t *a_vote_hash
);
```
**Parameters:**
- `a_net` (dap_chain_net_t *) - Network containing the vote
- `a_vote_hash` (dap_hash_fast_t *) - Hash of the voting proposal
**Returns:**
- Pointer to `dap_chain_net_vote_info_t` structure
- `NULL` if vote not found or error occurred
#### `dap_chain_net_vote_info_free()`
Frees memory allocated for vote information structure.
```c
void dap_chain_net_vote_info_free(dap_chain_net_vote_info_t *a_info);
```
**Parameters:**
- `a_info` (dap_chain_net_vote_info_t *) - Vote info structure to free
## Error Codes
### Vote Creation Error Codes
```c
enum DAP_CHAIN_NET_VOTE_CREATE_ERROR {
DAP_CHAIN_NET_VOTE_CREATE_OK, // Success
DAP_CHAIN_NET_VOTE_CREATE_LENGTH_QUESTION_OVERSIZE_MAX, // Question too long
DAP_CHAIN_NET_VOTE_CREATE_COUNT_OPTION_OVERSIZE_MAX, // Too many options
DAP_CHAIN_NET_VOTE_CREATE_FEE_IS_ZERO, // Zero fee specified
DAP_CHAIN_NET_VOTE_CREATE_SOURCE_ADDRESS_IS_INVALID, // Invalid source address
DAP_CHAIN_NET_VOTE_CREATE_NOT_ENOUGH_FUNDS_TO_TRANSFER, // Insufficient funds
DAP_CHAIN_NET_VOTE_CREATE_MAX_COUNT_OPTION_EXCEEDED, // Option count exceeded
DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_OPTION_TSD_ITEM, // TSD item creation failed
DAP_CHAIN_NET_VOTE_CREATE_INPUT_TIME_MORE_CURRENT_TIME, // Invalid expiration time
DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_CREATE_TSD_EXPIRE_TIME, // Expiration TSD failed
DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_CREATE_TSD_DELEGATE_KEY, // Delegate key TSD failed
DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_ADD_NET_FEE_OUT, // Fee output failed
DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_ADD_OUT_WITH_VALUE_BACK, // Value output failed
DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_SIGNED_TX, // Transaction signing failed
DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_POOL_DATUM_IN_MEMPOOL, // Mempool addition failed
DAP_CHAIN_NET_VOTE_CREATE_QUESTION_PARAM_MISSING, // Question parameter missing
DAP_CHAIN_NET_VOTE_CREATE_QUESTION_CONTAIN_MAX_CHARACTERS, // Question too long
DAP_CHAIN_NET_VOTE_CREATE_OPTION_PARAM_MISSING, // Option parameter missing
DAP_CHAIN_NET_VOTE_CREATE_NUMBER_OPTIONS_ERROR, // Invalid option count
DAP_CHAIN_NET_VOTE_CREATE_CONTAIN_MAX_OPTIONS, // Too many options
DAP_CHAIN_NET_VOTE_CREATE_FEE_PARAM_NOT_VALID, // Invalid fee parameter
DAP_CHAIN_NET_VOTE_CREATE_WALLET_PARAM_NOT_VALID, // Invalid wallet parameter
DAP_CHAIN_NET_VOTE_CREATE_WALLET_DOES_NOT_EXIST, // Wallet not found
DAP_CHAIN_NET_VOTE_CREATE_WRONG_TIME_FORMAT, // Invalid time format
DAP_CHAIN_NET_VOTE_CREATE_WRONG_TOKEN, // Invalid token
DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_CREATE_TSD_TOKEN, // Token TSD creation failed
DAP_CHAIN_NET_VOTE_CREATE_UNKNOWN_ERR // Unknown error
};
```
### Vote Casting Error Codes
```c
enum DAP_CHAIN_NET_VOTE_VOTING_ERROR {
DAP_CHAIN_NET_VOTE_VOTING_OK, // Success
DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_FIND_VOTE, // Vote not found
DAP_CHAIN_NET_VOTE_VOTING_THIS_VOTING_HAVE_MAX_VALUE_VOTES, // Vote limit reached
DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED, // Voting expired
DAP_CHAIN_NET_VOTE_VOTING_NO_KEY_FOUND_IN_CERT, // No key in certificate
DAP_CHAIN_NET_VOTE_VOTING_CERT_REQUIRED, // Certificate required
DAP_CHAIN_NET_VOTE_VOTING_KEY_IS_NOT_DELEGATED, // Key not delegated
DAP_CHAIN_NET_VOTE_VOTING_DOES_NOT_ALLOW_CHANGE_YOUR_VOTE, // Vote changing not allowed
DAP_CHAIN_NET_VOTE_VOTING_SOURCE_ADDRESS_INVALID, // Invalid source address
DAP_CHAIN_NET_VOTE_VOTING_NOT_ENOUGH_FUNDS_TO_TRANSFER, // Insufficient funds
DAP_CHAIN_NET_VOTE_VOTING_UNSPENT_UTX0_FOR_PARTICIPATION_THIS_VOTING, // No UTXO for voting
DAP_CHAIN_NET_VOTE_VOTING_INVALID_OPTION_INDEX, // Invalid option index
DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_CREATE_VOTE_ITEM, // Vote item creation failed
DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_CREATE_TSD_TX_COND_ITEM, // TSD condition failed
DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_NET_FEE_OUT, // Fee output failed
DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_OUT_WITH_VALUE_BACK, // Value output failed
DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_SIGN_TX, // Transaction signing failed
DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_POOL_IN_MEMPOOL, // Mempool addition failed
DAP_CHAIN_NET_VOTE_VOTING_NET_PARAM_MISSING, // Network parameter missing
DAP_CHAIN_NET_VOTE_VOTING_NET_PARAM_NOT_VALID, // Invalid network parameter
DAP_CHAIN_NET_VOTE_VOTING_HASH_NOT_FOUND, // Hash not found
DAP_CHAIN_NET_VOTE_VOTING_HASH_INVALID, // Invalid hash
DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_FIND_CERT, // Certificate not found
DAP_CHAIN_NET_VOTE_VOTING_FEE_PARAM_NOT_VALID, // Invalid fee parameter
DAP_CHAIN_NET_VOTE_VOTING_FEE_PARAM_BAD_TYPE, // Bad fee type
DAP_CHAIN_NET_VOTE_VOTING_WALLET_PARAM_NOT_VALID, // Invalid wallet parameter
DAP_CHAIN_NET_VOTE_VOTING_OPTION_IDX_PARAM_NOT_VALID, // Invalid option index
DAP_CHAIN_NET_VOTE_VOTING_WALLET_DOES_NOT_EXIST, // Wallet not found
DAP_CHAIN_NET_VOTE_VOTING_UNKNOWN_ERR, // Unknown error
DAP_CHAIN_NET_VOTE_VOTING_INTEGER_OVERFLOW // Integer overflow
};
```
## Typical Examples
### Voting Proposal Creation Example
```c
#include <dap_chain_net_srv_voting.h>
void voting_proposal_creation_example() {
log_it_info("=== Voting Proposal Creation Example ===");
// Step 1: Setup network and wallet
dap_chain_net_t *net = dap_chain_net_by_name("backbone");
if (!net) {
log_it_error("✗ Network 'backbone' not found");
return;
}
dap_chain_wallet_t *wallet = dap_chain_wallet_open("governance_wallet", NULL, NULL);
if (!wallet) {
log_it_error("✗ Failed to open wallet 'governance_wallet'");
return;
}
// Step 2: Prepare voting question and options
const char *question = "Should the network implement a new fee structure for exchange services?";
dap_list_t *options = NULL;
options = dap_list_append(options, (void*)"Yes, implement new fee structure");
options = dap_list_append(options, (void*)"No, keep current fee structure");
options = dap_list_append(options, (void*)"Need more community discussion");
options = dap_list_append(options, (void*)"Abstain from voting");
log_it_info("Creating voting proposal:");
log_it_info(" Question: %s", question);
log_it_info(" Options: %d available", dap_list_length(options));
// Step 3: Set voting parameters
dap_time_t expire_time = dap_time_now() + (7 * 24 * 60 * 60); // 7 days from now
uint64_t max_votes = 1000; // Maximum 1000 votes
uint256_t fee = dap_chain_balance_scan("10.0"); // 10 CELL creation fee
bool delegate_key_required = true; // Require delegate key
bool vote_changing_allowed = false; // No vote changing
log_it_info(" Expiration: %s", dap_ctime_r(&expire_time));
log_it_info(" Max votes: %" PRIu64, max_votes);
log_it_info(" Creation fee: %s CELL", dap_chain_balance_to_coins(fee));
log_it_info(" Delegate key required: %s", delegate_key_required ? "Yes" : "No");
log_it_info(" Vote changing allowed: %s", vote_changing_allowed ? "Yes" : "No");
// Step 4: Create voting proposal
char *hash_output = NULL;
int result = dap_chain_net_vote_create(
question, options, expire_time, max_votes, fee,
delegate_key_required, vote_changing_allowed, wallet,
net, "CELL", "hex", &hash_output
);
// Step 5: Handle creation result
switch (result) {
case DAP_CHAIN_NET_VOTE_CREATE_OK:
log_it_info("✓ Voting proposal created successfully");
log_it_info(" Proposal hash: %s", hash_output ? hash_output : "N/A");
break;
case DAP_CHAIN_NET_VOTE_CREATE_LENGTH_QUESTION_OVERSIZE_MAX:
log_it_error("✗ Question text is too long");
break;
case DAP_CHAIN_NET_VOTE_CREATE_COUNT_OPTION_OVERSIZE_MAX:
log_it_error("✗ Too many voting options provided");
break;
case DAP_CHAIN_NET_VOTE_CREATE_NOT_ENOUGH_FUNDS_TO_TRANSFER:
log_it_error("✗ Insufficient funds for creation fee");
log_it_error(" Required: %s CELL", dap_chain_balance_to_coins(fee));
break;
case DAP_CHAIN_NET_VOTE_CREATE_INPUT_TIME_MORE_CURRENT_TIME:
log_it_error("✗ Expiration time is in the past");
break;
case DAP_CHAIN_NET_VOTE_CREATE_WALLET_DOES_NOT_EXIST:
log_it_error("✗ Wallet not found or inaccessible");
break;
default:
log_it_error("✗ Proposal creation failed with error: %d", result);
break;
}
// Step 6: Cleanup
if (hash_output) {
DAP_DELETE(hash_output);
}
dap_list_free(options);
dap_chain_wallet_close(wallet);
log_it_info("Voting proposal creation example completed");
}
```
### Vote Casting Example
```c
#include <dap_chain_net_srv_voting.h>
void vote_casting_example() {
log_it_info("=== Vote Casting Example ===");
// Step 1: Setup network and voter wallet
dap_chain_net_t *net = dap_chain_net_by_name("backbone");
if (!net) {
log_it_error("✗ Network not found");
return;
}
dap_chain_wallet_t *voter_wallet = dap_chain_wallet_open("voter_wallet", NULL, NULL);
if (!voter_wallet) {
log_it_error("✗ Failed to open voter wallet");
return;
}
// Step 2: Get available voting proposals
dap_list_t *votes = dap_chain_net_vote_list(net);
if (!votes) {
log_it_error("✗ No voting proposals available");
dap_chain_wallet_close(voter_wallet);
return;
}
log_it_info("✓ Found active voting proposals");
// Step 3: Select first available proposal (in real app, user would choose)
dap_chain_net_vote_info_t *selected_vote = (dap_chain_net_vote_info_t *)votes->data;
log_it_info("Selected proposal details:");
log_it_info(" Question: %s", selected_vote->question.question_str);
log_it_info(" Options available: %" PRIu64, selected_vote->options.count_option);
log_it_info(" Expires: %s", dap_ctime_r(&selected_vote->expired));
log_it_info(" Delegate key required: %s", selected_vote->is_delegate_key_required ? "Yes" : "No");
log_it_info(" Vote changing allowed: %s", selected_vote->is_changing_allowed ? "Yes" : "No");
// Display available options
for (uint64_t i = 0; i < selected_vote->options.count_option; i++) {
dap_chain_net_vote_info_option_t *option = selected_vote->options.options[i];
log_it_info(" [%" PRIu64 "] %s (%" PRIu64 " votes, weight: %s)",
option->option_idx,
option->description,
option->votes_count,
dap_chain_balance_to_coins(option->weight));
}
// Step 4: Cast vote for option 0 (first option)
uint64_t chosen_option = 0;
uint256_t voting_fee = dap_chain_balance_scan("1.0"); // 1 CELL voting fee
log_it_info("Casting vote for option %" PRIu64 ": %s",
chosen_option,
selected_vote->options.options[chosen_option]->description);
// Step 5: Get certificate if required
dap_cert_t *cert = NULL;
if (selected_vote->is_delegate_key_required) {
cert = dap_cert_find_by_name("validator_cert");
if (!cert) {
log_it_error("✗ Delegate certificate required but not found");
dap_list_free(votes);
dap_chain_wallet_close(voter_wallet);
return;
}
log_it_info("✓ Using delegate certificate: %s", cert->name);
}
// Step 6: Execute vote
char *vote_tx_hash = NULL;
int voting_result = dap_chain_net_vote_voting(
cert, voting_fee, voter_wallet, selected_vote->hash,
chosen_option, net, "hex", &vote_tx_hash
);
// Step 7: Handle voting result
switch (voting_result) {
case DAP_CHAIN_NET_VOTE_VOTING_OK:
log_it_info("✓ Vote cast successfully");
log_it_info(" Vote transaction hash: %s", vote_tx_hash ? vote_tx_hash : "N/A");
log_it_info(" Chosen option: %" PRIu64, chosen_option);
break;
case DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED:
log_it_error("✗ Voting period has expired");
break;
case DAP_CHAIN_NET_VOTE_VOTING_THIS_VOTING_HAVE_MAX_VALUE_VOTES:
log_it_error("✗ Maximum vote limit reached for this proposal");
break;
case DAP_CHAIN_NET_VOTE_VOTING_CERT_REQUIRED:
log_it_error("✗ Delegate certificate required for this vote");
break;
case DAP_CHAIN_NET_VOTE_VOTING_KEY_IS_NOT_DELEGATED:
log_it_error("✗ Certificate key is not properly delegated");
break;
case DAP_CHAIN_NET_VOTE_VOTING_INVALID_OPTION_INDEX:
log_it_error("✗ Invalid option index: %" PRIu64, chosen_option);
break;
case DAP_CHAIN_NET_VOTE_VOTING_NOT_ENOUGH_FUNDS_TO_TRANSFER:
log_it_error("✗ Insufficient funds for voting fee");
log_it_error(" Required: %s CELL", dap_chain_balance_to_coins(voting_fee));
break;
default:
log_it_error("✗ Vote casting failed with error: %d", voting_result);
break;
}
// Step 8: Cleanup
if (vote_tx_hash) {
DAP_DELETE(vote_tx_hash);
}
dap_list_free(votes);
dap_chain_wallet_close(voter_wallet);
log_it_info("Vote casting example completed");
}
```
### Voting Results Analysis Example
```c
#include <dap_chain_net_srv_voting.h>
void voting_results_analysis_example() {
log_it_info("=== Voting Results Analysis Example ===");
// Step 1: Setup network
dap_chain_net_t *net = dap_chain_net_by_name("backbone");
if (!net) {
log_it_error("✗ Network not found");
return;
}
// Step 2: Get all voting proposals
dap_list_t *votes = dap_chain_net_vote_list(net);
if (!votes) {
log_it_info("No voting proposals found");
return;
}
// Step 3: Analyze each voting proposal
log_it_info("Voting Proposals Analysis:");
log_it_info("╭─────────────────────────────────────────────────────────────────────────────╮");
log_it_info("│ Question │ Status │ Options │ Total Votes │");
log_it_info("├─────────────────────────────────────────────────────────────────────────────┤");
dap_list_t *current = votes;
int proposal_count = 0;
while (current) {
dap_chain_net_vote_info_t *vote_info = (dap_chain_net_vote_info_t *)current->data;
// Determine voting status
const char *status_str = "Unknown";
dap_time_t now = dap_time_now();
if (vote_info->is_expired || now > vote_info->expired) {
status_str = "Expired";
} else {
status_str = "Active";
}
// Calculate total votes across all options
uint64_t total_votes = 0;
uint256_t total_weight = {0};
for (uint64_t i = 0; i < vote_info->options.count_option; i++) {
total_votes += vote_info->options.options[i]->votes_count;
SUM_256_256(total_weight, vote_info->options.options[i]->weight, &total_weight);
}
// Truncate question for display
char short_question[35];
strncpy(short_question, vote_info->question.question_str, 34);
short_question[34] = '\0';
if (strlen(vote_info->question.question_str) > 34) {
strcpy(&short_question[31], "...");
}
log_it_info("│ %-34s │ %-9s │ %7" PRIu64 " │ %11" PRIu64 " │",
short_question,
status_str,
vote_info->options.count_option,
total_votes);
proposal_count++;
current = current->next;
}
log_it_info("╰─────────────────────────────────────────────────────────────────────────────╯");
log_it_info("Total proposals: %d", proposal_count);
// Step 4: Detailed analysis of first proposal
if (proposal_count > 0) {
dap_chain_net_vote_info_t *first_vote = (dap_chain_net_vote_info_t *)votes->data;
log_it_info("");
log_it_info("--- Detailed Analysis of First Proposal ---");
log_it_info("Question: %s", first_vote->question.question_str);
log_it_info("Proposal Hash: %s", dap_chain_hash_fast_to_str_new(&first_vote->hash));
dap_time_t time_remaining = first_vote->expired - dap_time_now();
if (time_remaining > 0) {
log_it_info("Time remaining: %ld seconds (%.1f hours)",
time_remaining, (double)time_remaining / 3600.0);
} else {
log_it_info("Status: Voting period ended");
}
log_it_info("Voting Options and Results:");
uint64_t total_votes = 0;
uint256_t total_weight = {0};
// Calculate totals first
for (uint64_t i = 0; i < first_vote->options.count_option; i++) {
total_votes += first_vote->options.options[i]->votes_count;
SUM_256_256(total_weight, first_vote->options.options[i]->weight, &total_weight);
}
// Display each option with percentages
for (uint64_t i = 0; i < first_vote->options.count_option; i++) {
dap_chain_net_vote_info_option_t *option = first_vote->options.options[i];
double vote_percentage = total_votes > 0 ?
(double)option->votes_count / total_votes * 100.0 : 0.0;
log_it_info(" [%" PRIu64 "] %s",
option->option_idx,
option->description);
log_it_info(" Votes: %" PRIu64 " (%.1f%%)",
option->votes_count,
vote_percentage);
log_it_info(" Weight: %s",
dap_chain_balance_to_coins(option->weight));
log_it_info(" Transactions: %d",
dap_list_length(option->hashes_tx_votes));
}
log_it_info("Summary:");
log_it_info(" Total votes cast: %" PRIu64, total_votes);
log_it_info(" Total voting weight: %s", dap_chain_balance_to_coins(total_weight));
if (first_vote->is_max_count_votes) {
log_it_info(" Vote limit: %" PRIu64 " (%.1f%% filled)",
first_vote->max_count_votes,
total_votes > 0 ? (double)total_votes / first_vote->max_count_votes * 100.0 : 0.0);
}
}
// Step 5: Cleanup
dap_list_free(votes);
log_it_info("Voting results analysis example completed");
}
```
---
*See also: [[Modules/Module Service|Module Service]], [[Modules/Module Service - Exchange|Module Service - Exchange]], [[ETC/Services Overview|Services Overview]]*