Building a Decentralized Voting Application on Soroban with Node.js
Introduction
Blockchain technology is revolutionizing how we think about security, transparency, and decentralization. One exciting application of blockchain is in voting systems. Stellar's Soroban provides an excellent platform for building decentralized applications, including voting systems, by utilizing smart contracts. In this tutorial, we will build a simple decentralized voting application using Soroban and Node.js.
Why Use Soroban and Node.js?
Soroban: Soroban is Stellar's smart contract platform that integrates seamlessly with the Stellar network, providing scalability and low transaction costs.
Node.js: A popular JavaScript runtime, Node.js allows developers to use JavaScript for server-side programming. It is widely used for building scalable network applications and provides a plethora of libraries and tools for interacting with blockchain.
Prerequisites
Before we start, ensure you have the following installed on your machine:
Node.js (v14 or later)
npm (comes with Node.js)
Rust (for Soroban development)
Soroban CLI: Install using Cargo (Rust's package manager)
bashCopy codecargo install --locked soroban-cli
Step 1: Setting Up the Project
Create a New Directory: Start by creating a new directory for your project.
bashCopy codemkdir soroban-voting-app cd soroban-voting-app
Initialize Node.js Project: Initialize a new Node.js project with npm.
bashCopy codenpm init -y
Install Dependencies: We'll use the
stellar-sdk
to interact with the Stellar network.bashCopy codenpm install stellar-sdk
Step 2: Writing the Soroban Smart Contract
Our voting application will use a smart contract to manage proposals and votes.
Create the Soroban Project:
bashCopy codesoroban contract new voting_contract cd voting_contract
Write the Voting Contract: In
src/lib.rs
, add the following code:rustCopy codeuse soroban_sdk::{contractimpl, Env, Symbol}; pub struct VotingContract; #[contractimpl] impl VotingContract { pub fn create_proposal(env: Env, proposal_name: String) { env.storage().set(Symbol::new(env, "proposal"), &proposal_name); env.storage().set(Symbol::new(env, "yes_votes"), &0u32); env.storage().set(Symbol::new(env, "no_votes"), &0u32); } pub fn vote_yes(env: Env) { let mut yes_votes: u32 = env.storage().get(Symbol::new(env, "yes_votes")).unwrap(); yes_votes += 1; env.storage().set(Symbol::new(env, "yes_votes"), &yes_votes); } pub fn vote_no(env: Env) { let mut no_votes: u32 = env.storage().get(Symbol::new(env, "no_votes")).unwrap(); no_votes += 1; env.storage().set(Symbol::new(env, "no_votes"), &no_votes); } pub fn get_results(env: Env) -> (u32, u32) { let yes_votes: u32 = env.storage().get(Symbol::new(env, "yes_votes")).unwrap(); let no_votes: u32 = env.storage().get(Symbol::new(env, "no_votes")).unwrap(); (yes_votes, no_votes) } }
Compile the Contract:
bashCopy codesoroban build
Step 3: Deploying the Contract
Deploy the Contract:
bashCopy codesoroban contract deploy --wasm target/wasm32-unknown-unknown/release/voting_contract.wasm
This command will return a contract ID that we will use to interact with the contract.
Step 4: Interacting with the Smart Contract using Node.js
Set Up Interaction Script: In the root directory of your Node.js project, create a file named
index.js
.Write the Interaction Code:
javascriptCopy codeconst StellarSdk = require('stellar-sdk'); const { Server, Keypair, Networks, TransactionBuilder, Operation, Asset, BASE_FEE } = StellarSdk; // Replace with your Horizon server const server = new Server('https://horizon-testnet.stellar.org'); const sorobanServer = new StellarSdk.SorobanServer(server); // Replace with your secret key const secretKey = 'your-secret-key-here'; const keypair = Keypair.fromSecret(secretKey); const publicKey = keypair.publicKey(); // Replace with your contract ID const contractId = 'your-contract-id-here'; async function createProposal(proposalName) { try { const account = await server.loadAccount(publicKey); const transaction = new TransactionBuilder(account, { fee: BASE_FEE, networkPassphrase: Networks.TESTNET }) .addOperation(Operation.invokeHostFunction({ function: 'create_proposal', parameters: [proposalName], contractId })) .setTimeout(30) .build(); transaction.sign(keypair); const response = await server.submitTransaction(transaction); console.log('Proposal created:', response); } catch (err) { console.error('Error creating proposal:', err); } } async function voteYes() { try { const account = await server.loadAccount(publicKey); const transaction = new TransactionBuilder(account, { fee: BASE_FEE, networkPassphrase: Networks.TESTNET }) .addOperation(Operation.invokeHostFunction({ function: 'vote_yes', contractId })) .setTimeout(30) .build(); transaction.sign(keypair); const response = await server.submitTransaction(transaction); console.log('Voted yes:', response); } catch (err) { console.error('Error voting yes:', err); } } async function getResults() { try { const results = await sorobanServer.callContract(contractId, 'get_results', []); console.log('Current results:', results); } catch (err) { console.error('Error getting results:', err); } } // Example usage (async () => { await createProposal('Implement Soroban in our Project'); await voteYes(); await getResults(); })();
Run the Script:
Execute the script using Node.js to create a proposal, vote yes, and retrieve results:
bashCopy codenode index.js
Enhancements and Next Steps
This guide demonstrates the fundamental steps to create, deploy, and interact with a decentralized voting contract using Soroban and Node.js. Here are a few enhancements you could consider:
UI Integration: Build a front-end interface using React or Angular to allow users to interact with the voting system easily.
User Authentication: Integrate Stellar's federated authentication to ensure only authorized users can vote.
Multiple Proposals: Modify the smart contract to handle multiple proposals simultaneously.
Analytics: Integrate with data analytics tools to visualize voting patterns and trends.
Conclusion
Soroban's integration with the Stellar network, combined with the ease of Node.js, provides a powerful platform for building decentralized applications. The decentralized voting system you have just built can serve as a foundation for more complex applications that leverage blockchain for transparency and security.
With Soroban, developers can explore a wide range of applications, from voting systems to decentralized finance (DeFi) projects. Get started today and be a part of the future of decentralized technology!
Read stellar docs here - https://developers.stellar.org/docs