برنامه نویسی

ساخت یک سیستم رای گیری غیرمتمرکز ساده در Stellar

این ارسالی برای ساخت بهتر در Stellar است: چالش قرارداد هوشمند: ایجاد یک آموزش

آموزش شما

Stellar یک پلت فرم بلاک چین قدرتمند است که توسعه دهندگان را قادر می سازد تا برنامه های غیرمتمرکز (dApps) را به راحتی ایجاد کنند. در این آموزش، فرآیند ساخت یک سیستم رای گیری غیرمتمرکز اولیه در Stellar را بررسی خواهیم کرد. این پروژه به شما کمک می‌کند مفاهیم کلیدی Stellar را درک کنید و تجربه عملی در زمینه توسعه قراردادهای هوشمند با استفاده از Soroban، پلتفرم قرارداد هوشمند Stellar به شما ارائه دهد.

فهرست مطالب

  1. مقدمه ای بر استلار و سوروبان
  2. راه اندازی محیط توسعه
  3. ایجاد قرارداد رای گیری
  4. استقرار قرارداد
  5. ساخت Frontend
  6. تست dApp

مقدمه ای بر استلار و سوروبان

Stellar یک پروتکل منبع باز و غیرمتمرکز برای ارز دیجیتال به انتقال پول فیات است. Soroban پلتفرم قرارداد هوشمند Stellar است که به توسعه دهندگان اجازه می دهد تا قراردادهای هوشمند را در شبکه Stellar بنویسند، مستقر کنند و اجرا کنند.

مفاهیم کلیدی که در این آموزش استفاده خواهیم کرد:

  • قراردادهای هوشمند: قراردادهای خود اجرائی با شرایطی که مستقیماً در کد نوشته شده است.
  • حساب ها: موجودیت هایی در شبکه Stellar که می توانند موجودی ها را نگه دارند و تراکنش ها را ارسال کنند.
  • معاملات: عملیاتی که وضعیت دفتر کل را تغییر می دهد.

راه اندازی محیط توسعه

قبل از شروع کدنویسی، اجازه دهید محیط توسعه خود را تنظیم کنیم. ما باید Stellar CLI، Rust را نصب کنیم و یک پروژه Soroban جدید ایجاد کنیم.

  1. Stellar CLI را نصب کنید:
curl -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
cargo install --locked --version 20.0.0-rc2 soroban-cli
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  1. ایجاد یک پروژه جدید Soroban:
soroban contract init voting-system
cd voting-system
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ایجاد قرارداد رای گیری

حالا بیایید قرارداد رای خود را بسازیم. ما ساختارهایی را برای نامزدها و رای دهندگان تعریف خواهیم کرد و عملکردهایی را برای ثبت نام کاندیداها، رای دادن و بازیابی نتایج اجرا خواهیم کرد.

را ویرایش کنید src/lib.rs فایل:

#![no_std]
use soroban_sdk::{contractimpl, symbol_short, vec, Env, Symbol, Vec};

#[derive(Clone)]
pub struct Candidate {
    name: Symbol,
    votes: u32,
}

#[derive(Clone)]
pub struct Voter {
    address: Symbol,
    has_voted: bool,
}

pub struct VotingContract;

#[contractimpl]
impl VotingContract {
    pub fn init(env: Env) -> VecCandidate> {
        let candidates = vec![&env];
        env.storage().set(&symbol_short!("candidates"), &candidates);
        candidates
    }

    pub fn add_candidate(env: Env, name: Symbol) -> VecCandidate> {
        let mut candidates: VecCandidate> = env.storage().get(&symbol_short!("candidates")).unwrap();
        candidates.push_back(Candidate { name, votes: 0 });
        env.storage().set(&symbol_short!("candidates"), &candidates);
        candidates
    }

    pub fn vote(env: Env, voter: Symbol, candidate_index: u32) -> VecCandidate> {
        let mut candidates: VecCandidate> = env.storage().get(&symbol_short!("candidates")).unwrap();
        let mut voters: VecVoter> = env.storage().get(&symbol_short!("voters")).unwrap_or(vec![&env]);

        // Check if voter has already voted
        if let Some(voter_index) = voters.iter().position(|v| v.address == voter) {
            if voters.get(voter_index).unwrap().has_voted {
                panic!("Voter has already cast a vote");
            }
            voters.set(voter_index, &Voter { address: voter, has_voted: true });
        } else {
            voters.push_back(Voter { address: voter, has_voted: true });
        }

        // Increment vote count for the chosen candidate
        let mut candidate = candidates.get(candidate_index).unwrap();
        candidate.votes += 1;
        candidates.set(candidate_index, &candidate);

        env.storage().set(&symbol_short!("candidates"), &candidates);
        env.storage().set(&symbol_short!("voters"), &voters);

        candidates
    }

    pub fn get_results(env: Env) -> VecCandidate> {
        env.storage().get(&symbol_short!("candidates")).unwrap()
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این قرارداد چهار کارکرد اصلی را تعریف می کند:

  • init: قرارداد را با یک لیست خالی از نامزدها اولیه می کند.
  • add_candidate: نامزد جدیدی را به انتخابات اضافه می کند.
  • vote: به رای دهنده اجازه می دهد به یک نامزد رای دهد.
  • get_results: نتایج رای گیری فعلی را بازیابی می کند.

استقرار قرارداد

اکنون که قرارداد خود را داریم، بیایید آن را در شبکه آزمایشی Stellar مستقر کنیم.

  1. ساخت قرارداد:
soroban contract build
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  1. یک حساب Stellar برای قرارداد ایجاد کنید:
soroban config identity generate contract-admin
soroban config network add testnet --rpc-url https://soroban-testnet.stellar.org:443 --network-passphrase "Test SDF Network ; September 2015"
soroban config identity fund contract-admin --network testnet
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  1. استقرار قرارداد:
soroban contract deploy \
    --wasm target/wasm32-unknown-unknown/release/voting_system.wasm \
    --source contract-admin \
    --network testnet
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

شناسه قراردادی که با این دستور بازگردانده شده است را یادداشت کنید، زیرا برای تعامل با قرارداد به آن نیاز داریم.

ساخت Frontend

برای فرانت‌اند، از React با the استفاده می‌کنیم @stellar/freighter-api کتابخانه برای تعامل با شبکه استلار. ابتدا یک پروژه React جدید راه اندازی کنید:

npx create-react-app voting-dapp
cd voting-dapp
npm install @stellar/freighter-api
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اکنون، بیایید یک ظاهر ساده برای dApp رأی دهی خود ایجاد کنیم. محتوای آن را جایگزین کنید src/App.js:

import React, { useState, useEffect } from 'react';
import { isConnected, getPublicKey, signTransaction } from '@stellar/freighter-api';
import { SorobanRpc, Transaction, xdr } from 'stellar-sdk';

const server = new SorobanRpc.Server("https://soroban-testnet.stellar.org:443");
const contractId = 'YOUR_CONTRACT_ID'; // Replace with your deployed contract ID

function App() {
  const [candidates, setCandidates] = useState([]);
  const [newCandidate, setNewCandidate] = useState('');
  const [selectedCandidate, setSelectedCandidate] = useState('');
  const [walletConnected, setWalletConnected] = useState(false);

  useEffect(() => {
    checkWalletConnection();
    fetchCandidates();
  }, []);

  const checkWalletConnection = async () => {
    const connected = await isConnected();
    setWalletConnected(connected);
  };

  const fetchCandidates = async () => {
    try {
      const result = await server.invokeHostFunction({
        contractId: contractId,
        functionName: 'get_results',
        args: []
      });
      setCandidates(result);
    } catch (error) {
      console.error('Error fetching candidates:', error);
    }
  };

  const addCandidate = async () => {
    if (!newCandidate) return;
    try {
      await server.invokeHostFunction({
        contractId: contractId,
        functionName: 'add_candidate',
        args: [xdr.ScSymbol.fromString(newCandidate)]
      });
      setNewCandidate('');
      fetchCandidates();
    } catch (error) {
      console.error('Error adding candidate:', error);
    }
  };

  const vote = async () => {
    if (!selectedCandidate) return;
    try {
      const publicKey = await getPublicKey();
      const transaction = await server.invokeHostFunction({
        contractId: contractId,
        functionName: 'vote',
        args: [
          xdr.ScSymbol.fromString(publicKey),
          xdr.ScSymbol.fromString(selectedCandidate)
        ]
      });
      const signedTransaction = await signTransaction(transaction.toXDR());
      await server.sendTransaction(signedTransaction);
      fetchCandidates();
    } catch (error) {
      console.error('Error voting:', error);
    }
  };

  return (
    div className="App">
      h1>Stellar Voting dApph1>
      {walletConnected ? (
        
          h2>Add Candidateh2>
          input
            type="text"
            value={newCandidate}
            onChange={(e) => setNewCandidate(e.target.value)}
          />
          button onClick={addCandidate}>Add Candidatebutton>

          h2>Voteh2>
          select onChange={(e) => setSelectedCandidate(e.target.value)}>
            option value="">Select a candidateoption>
            {candidates.map((candidate, index) => (
              option key={index} value={candidate.name}>
                {candidate.name}
              option>
            ))}
          select>
          button onClick={vote}>Votebutton>

          h2>Resultsh2>
          ul>
            {candidates.map((candidate, index) => (
              li key={index}>
                {candidate.name}: {candidate.votes} votes
              li>
            ))}
          ul>
        >
      ) : (
        p>Please connect your Stellar wallet to use this dApp.p>
      )}
    div>
  );
}

export default App;
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این کامپوننت React یک رابط ساده برای اضافه کردن نامزدها، رای دادن و مشاهده نتایج ارائه می‌کند. از API Freighter برای تعامل با کیف پول Stellar کاربر استفاده می کند stellar-sdk برای ارتباط با سرور Soroban RPC.

تست dApp

برای تست dApp:

  1. سرور توسعه React را راه اندازی کنید:
npm start
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

  1. مرورگر خود را باز کرده و به آن بروید http://localhost:3000.

  2. کیف پول Stellar خود (به عنوان مثال، فریتر) را به شبکه آزمایشی وصل کنید.

  3. نامزدها را اضافه کنید، رای بدهید و نتایج را مشاهده کنید.

چند نکته کلیدی:

  • Soroban یک پلت فرم قدرتمند برای ساخت قراردادهای هوشمند در Stellar فراهم می کند.
  • Stellar SDK و Freighter API تعامل با قراردادهای Stellar را از برنامه های تحت وب آسان می کند.
  • سیستم های رای گیری غیرمتمرکز می توانند شفافیت و تغییر ناپذیری را برای فرآیندهای انتخاباتی فراهم کنند.

همانطور که به بررسی توسعه Stellar ادامه می دهید، می توانید ویژگی های بیشتری را به این dApp اضافه کنید، مانند:

  • اجرای تفویض رأی
  • افزودن محدودیت های زمانی برای دوره های رای گیری
  • ایجاد انواع مختلف سیستم های رای گیری (به عنوان مثال، انتخاب رتبه بندی شده)

چیزی که من خلق کردم

این آموزش ساخت یک سیستم رای گیری غیرمتمرکز در شبکه استلار است. آی تی:

  1. توسعه دهندگان را با پلتفرم قرارداد هوشمند Stellar، Soroban آشنا می کند
  2. استفاده عملی از مفاهیم کلیدی Stellar مانند حساب ها و تراکنش ها را به نمایش می گذارد

این آموزش به عنوان نقطه شروعی برای توسعه دهندگان برای ایجاد برنامه های پیچیده تر در شبکه Stellar عمل می کند و نوآوری و پذیرش پلتفرم را تشویق می کند.

سفر

پیاده سازی و طراحی قرارداد هوشمند

برای این پروژه، من یک سیستم رای گیری غیرمتمرکز اولیه را در Stellar با استفاده از Soroban، پلت فرم قرارداد هوشمند Stellar پیاده سازی کردم. قرارداد هوشمند برای ثبت ایمن آرا طراحی شده است و تضمین می کند که هر رأی غیرقابل تغییر و شفاف است. ویژگی های کلیدی عبارتند از ثبت نام کاربر، ارسال رای، و شمارش آرا. هر رأی‌دهنده فقط یک بار می‌تواند رأی بدهد و همه رأی‌ها در بلاک چین Stellar ثبت می‌شوند که شفافیت و نتایج غیرقابل دستکاری را تضمین می‌کند.

انگیزه

انگیزه پشت این پروژه ایجاد راه حلی بود که به نیاز به انتخابات آزاد و عادلانه، به ویژه در کشور من، توجه کند. با استفاده از فناوری بلاک چین استلار، هدف ایجاد یک سیستم رای‌گیری بود که یکپارچگی انتخاباتی را افزایش می‌دهد، اعتماد به فرآیند دموکراتیک را ارتقا می‌دهد، دسترسی را افزایش می‌دهد و چالش‌های انتخاباتی خاص را برطرف می‌کند.

چیزی که یاد گرفتم

از طریق این پروژه، من درک عمیق تری از سادگی و قدرت Soroban برای توسعه قراردادهای هوشمند به دست آوردم. من بهترین روش‌ها برای طراحی برنامه‌های غیرمتمرکز در Stellar و اهمیت ایجاد رابط‌های کاربرپسند برای برنامه‌های بلاک چین را یاد گرفتم. به‌علاوه، چالش‌ها و ملاحظات بالقوه را هنگام پیاده‌سازی سیستم‌های رأی‌گیری در بلاک چین، مانند امنیت، مقیاس‌پذیری و پذیرش کاربر شناسایی کردم.

تجربه با اکوسیستم

تجربه من با اکوسیستم استلار بسیار مثبت بود. مستندات جامع و جامعه حمایتی شروع به کار با Soroban و توسعه قراردادهای هوشمند را آسان کرده است. ویژگی‌های قوی و سهولت استفاده این پلتفرم به من این امکان را می‌دهد تا بدون گرفتار شدن در پیچیدگی‌های فنی، روی اجرای عملکردهای اصلی سیستم رأی‌گیری تمرکز کنم.

برنامه های آینده

با حرکت رو به جلو، امیدوارم سیستم رای‌گیری را با ترکیب ویژگی‌های پیشرفته‌تر، مانند ردیابی رای بی‌درنگ و اقدامات امنیتی بهبودیافته، تقویت کنم. من همچنین قصد دارم موارد استفاده دیگر را برای برنامه های غیرمتمرکز در Stellar بررسی کنم و از قابلیت های این پلتفرم برای مقابله با چالش های مختلف دنیای واقعی استفاده کنم. علاوه بر این، من قصد دارم با به اشتراک گذاشتن تجربیات خود و کمک به توسعه دهندگان دیگر برای شروع بلاک چین و توسعه قراردادهای هوشمند، به مشارکت در جامعه Stellar ادامه دهم.

این پروژه یک سفر پربار بوده است و من در مورد پتانسیل Stellar و Soroban برای هدایت نوآوری و تغییرات مثبت در بخش های مختلف هیجان زده هستم.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا