# 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]]*