paint-brush
सॉलिडिटी स्मार्ट कॉन्ट्रैक्ट कैसे लिखें और इसे रोपस्टेन पर कैसे लागू करें?द्वारा@johnjvester
677 रीडिंग
677 रीडिंग

सॉलिडिटी स्मार्ट कॉन्ट्रैक्ट कैसे लिखें और इसे रोपस्टेन पर कैसे लागू करें?

द्वारा John Vester35m2022/08/05
Read on Terminal Reader
Read this story w/o Javascript

बहुत लंबा; पढ़ने के लिए

स्मार्ट अनुबंध दो पक्षों को एक समझौते में प्रवेश करने की अनुमति देते हैं। एक अनुबंध को बार-बार पुन: उपयोग करने का तरीका दिखाने के लिए स्मार्ट अनुबंधों में गहरी गोता लगाएँ।

People Mentioned

Mention Thumbnail
Mention Thumbnail

Companies Mentioned

Mention Thumbnail
Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - सॉलिडिटी स्मार्ट कॉन्ट्रैक्ट कैसे लिखें और इसे रोपस्टेन पर कैसे लागू करें?
John Vester HackerNoon profile picture


" फुल-स्टैक डेवलपर से Web3 पायनियर की ओर बढ़ना प्रकाशन ने फुल-स्टैक डेवलपर्स को Web3 विकास की दुनिया में एक झलक देने के लिए एक उच्च-स्तरीय अवलोकन प्रदान किया। यदि आपको उस लेख की समीक्षा करने का अवसर नहीं मिला है, तो एक नज़र डालने पर विचार करें, क्योंकि यह वहाँ भी Web3 का एक अच्छा परिचय प्रदान करता है।


मेरे मूल लेख के अंतिम परिणाम ने प्रदर्शित किया कि कैसे एक गृहस्वामी संघ (HOA) अपने चुनावी मतपत्र की मेजबानी के लिए Web3 तकनीक का उपयोग कर सकता है। मूल डिजाइन के साथ समस्या यह है कि अंतर्निहित स्मार्ट अनुबंध केवल एक हां या ना में उत्तर की अनुमति देता है। यह Web3 तकनीकों का उपयोग करके HOA मतपत्र बनाने के लिए आवश्यक अन्य अवधारणाओं को पेश करते हुए स्मार्ट अनुबंध को सरल रखने के लिए डिज़ाइन द्वारा किया गया था।


इस प्रकाशन का उद्देश्य एक ऐसे एप्लिकेशन का निर्माण करने के लिए स्मार्ट अनुबंधों में गहराई से उतरना है जो न केवल एक एचओए मतपत्र के लिए यथार्थवादी जरूरतों और कार्यों को कैप्चर करता है बल्कि एक ऐसा डिजाइन करता है जिसे एक चुनाव से अगले चुनाव में पुन: उपयोग किया जा सकता है।

स्मार्ट अनुबंधों के बारे में

आरंभ करने से पहले, आइए एक स्मार्ट अनुबंध को परिभाषित करें:

"स्मार्ट कॉन्ट्रैक्ट एक प्रोग्राम है जो एथेरियम पर एक पते पर चलता है। वे डेटा और फ़ंक्शंस से बने होते हैं जो लेनदेन प्राप्त करने पर निष्पादित हो सकते हैं। यहां एक संक्षिप्त विवरण दिया गया है कि एक स्मार्ट अनुबंध क्या होता है।"


स्रोत Ethereum.org


गंबल मशीन

मानो या न मानो, एक साधारण गंबल मशीन में स्मार्ट अनुबंध का एक आसान उदाहरण पाया जा सकता है:


गंबल मशीन से खरीदारी से जुड़े खर्च को लोग आसानी से समझ जाते हैं। आम तौर पर, यह एक (यूएस) तिमाही है। यहां यह बताना महत्वपूर्ण है कि ग्राहक गुमनाम है, क्योंकि गंबल मशीन को यह जानने की आवश्यकता नहीं है कि कोई व्यक्ति उन्हें स्वादिष्ट गम का एक टुकड़ा देने से पहले कौन है।


अनाम उपभोक्ता मुद्रा को गंबल मशीन में रखता है और अनुबंध की शर्तों को स्वीकार करने के लिए डायल को घुमाता है। यह कदम महत्वपूर्ण है क्योंकि लेन-देन पारदर्शी और पीयर-टू-पीयर है: आपके और मशीन के बीच। लेन-देन भी सुरक्षित है क्योंकि आपको गंबल मशीन का उपयोग करने के लिए अपेक्षित मुद्रा की आपूर्ति करनी होगी।


एक बार जब मुद्रा गंबल मशीन के अंदर गिर जाती है, तो अनुबंध की शर्तें स्वीकार कर ली जाती हैं, और एक गंबल मशीन के नीचे की ओर लुढ़क जाता है, जिससे ग्राहक अपनी खरीदारी प्राप्त कर सकता है। इस बिंदु पर, अनुबंध पूरी तरह से निष्पादित किया जाता है।


ग्राहक को जो प्रदान किया गया है उसे स्वीकार करना चाहिए, जिसका अर्थ है कि वे अपनी मुद्रा वापस पाने के लिए गंबल वापस नहीं कर सकते हैं या डायल को उलट नहीं सकते हैं। उसी तरह, स्मार्ट अनुबंध आमतौर पर अपरिवर्तनीय और अपरिवर्तनीय होते हैं।

स्मार्ट अनुबंध उपयोग के मामले

वित्तीय रूप से संचालित उदाहरणों के अलावा, कुछ परिदृश्य जहां अज्ञात, भरोसेमंद, विकेन्द्रीकृत और पारदर्शी इंटरैक्शन जो अपरिवर्तनीय और अपरिवर्तनीय हैं, उन्हें लागू किया जा सकता है:

  • नैदानिक परीक्षण - स्वतंत्र परीक्षणों के परिणाम
  • चुनाव - वोट डाले गए प्रतिभागियों
  • पहचान - व्यक्तियों को यह निर्धारित करने की अनुमति दें कि वे किसके साथ अपनी पहचान साझा करते हैं
  • बीमा पॉलिसी - व्यक्तिगत नीतियां और शर्तें
  • उत्पाद और आपूर्ति ट्रैकिंग - उत्पादन और आपूर्ति ट्रैकिंग के लिए स्थिति ट्रैकिंग
  • अचल संपत्ति और भूमि - अचल संपत्ति और भूमि से संबंधित कार्य, जिसका उपयोग वर्तमान मालिक को किसी भी समय प्राप्त करने के लिए किया जा सकता है
  • रिकॉर्डिंग सूचना - आधिकारिक रिकॉर्ड और प्रतिलेख (जैसे गेटिसबर्ग संबोधन )


हर मामले में, परिणामों को बदलने या संशोधित करने की क्षमता के बिना, स्मार्ट अनुबंध की सामग्री को जितनी बार संभव हो, याद किया जा सकता है और समीक्षा की जा सकती है। उपरोक्त प्रत्येक उपयोग का मामला अंतर्निहित जानकारी के लिए रिकॉर्ड की प्रणाली के रूप में स्मार्ट अनुबंध प्रदान करता है।

स्मार्ट कॉन्ट्रैक्ट क्या नहीं है

इस समय, कुछ बाहरी लोगों को छोड़कर, स्मार्ट अनुबंध कानूनी रूप से बाध्यकारी समझौते नहीं हैं। इसका अर्थ यह है कि यदि आप अपने स्मार्ट अनुबंध के परिणाम से संतुष्ट नहीं हैं, तो किसी न्यायालय प्रणाली में अपने मुद्दे को किसी न्यायाधीश के समक्ष रखना संभव नहीं है।

एरिज़ोना राज्य में कुछ अपवाद हैं जहां स्मार्ट अनुबंधों को कानूनी रूप से बाध्यकारी माना जाता है। इसके अतिरिक्त, यदि आप कैलिफ़ोर्निया राज्य में हैं और आपका विवाह लाइसेंस एक स्मार्ट अनुबंध में निहित है, तो वह अनुबंध कानूनी रूप से भी बाध्यकारी है। उम्मीद यह है कि भविष्य में अधिक सरकारें स्मार्ट अनुबंधों को कानूनी रूप से बाध्यकारी समझौतों के रूप में मान्यता देंगी।

केस का उपयोग करें: एक यथार्थवादी HOA मतपत्र बनाना

"फुल-स्टैक डेवलपर से वेब3 पायनियर की ओर बढ़ना" प्रकाशन से सरल बाइनरी (हां/नहीं) स्मार्ट अनुबंध पर निर्माण, आइए चीजों को एक कदम आगे बढ़ाएं और मान लें कि एक पड़ोस के लिए HOA मतपत्र के लिए निम्नलिखित आवश्यकता मौजूद है जिसमें एकल है भरने की स्थिति:

  • HOA अध्यक्ष का चयन करें


आदर्श रूप से, लक्ष्य यह होगा कि हर बार HOA चुनाव होने पर एकल स्मार्ट अनुबंध का उपयोग किया जाए। राष्ट्रपति पद के लिए दौड़ने वालों को एक चुनाव से दूसरे चुनाव में बदलने की उम्मीद है।

अब, आइए अपनी जरूरतों को पूरा करने के लिए एक स्मार्ट अनुबंध बनाना शुरू करें।

हमारे नए स्मार्ट अनुबंध को परिभाषित करना

सॉलिडिटी का उपयोग करते हुए, मैंने के साथ काम किया पॉल मैकविनी , जिसने हमारा गढ़ा स्मार्ट अनुबंध HOA मतपत्र के लिए जैसा कि नीचे दिखाया गया है:


 // SPDX-License-Identifier: MIT pragma solidity ^0.8.13; /********************************************************/ /* For learning purposes ONLY. Do not use in production */ /********************************************************/ // Download into project folder with `npm install @openzeppelin/contracts` import "@openzeppelin/contracts/access/Ownable.sol"; // Inherits the Ownable contract so we can use its functions and modifiers contract HOABallot is Ownable { // Custom type to describe a Presidential Candidate and hold votes struct Candidate { string name; uint256 votes; } // Array of Presidential Candidates Candidate[] public candidates; // Add a President Candidate - onlyOwner function addCandidate(string memory _name) public onlyOwner { require(bytes(_name).length > 0, "addCandidate Error: Please enter a name"); candidates.push(Candidate({name: _name, votes: 0})); } // Remove a Candidate - onlyOwner function removeCandidate(string memory _name) public onlyOwner { require(bytes(_name).length > 0, "removeCandidate Error: Please enter a name"); bool foundCandidate = false; uint256 index; bytes32 nameEncoded = keccak256(abi.encodePacked(_name)); // Set index number for specific candidate for (uint256 i = 0; i < candidates.length; i++) { if (keccak256(abi.encodePacked(candidates[i].name)) == nameEncoded) { index = i; foundCandidate = true; } } // Make sure a candidate was found require(foundCandidate, "removeCandidate Error: Candidate not found"); // shift candidate to be removed to the end of the array and the rest forward for (uint256 i = index; i < candidates.length - 1; i++) { candidates[i] = candidates[i + 1]; } // remove last item from array candidates.pop(); } // Reset the President Vote Counts - onlyOwner function resetVoteCount() public onlyOwner { for (uint256 p = 0; p < candidates.length; p++) { candidates[p].votes = 0; } } // Add a vote to a candidate by name function addVoteByName(string memory _name) public { require(bytes(_name).length > 0, "addVoteByName Error: Please enter a name"); // Encode name so only need to do once bytes32 nameEncoded = keccak256(abi.encodePacked(_name)); for (uint256 i = 0; i < candidates.length; i++) { // solidity can't compare strings directly, need to compare hash if (keccak256(abi.encodePacked(candidates[i].name)) == nameEncoded) { candidates[i].votes += 1; } } } // Returns all the Presidential Candidates and their vote counts function getCandidates() public view returns (Candidate[] memory) { return candidates; } function getWinner() public view returns (Candidate memory winner) { uint256 winningVoteCount = 0; for (uint256 i = 0; i < candidates.length; i++) { if (candidates[i].votes > winningVoteCount) { winningVoteCount = candidates[i].votes; winner = candidates[i]; } } return winner; } }


यहाँ स्मार्ट अनुबंध के डिज़ाइन से संबंधित कुछ प्रमुख बातें दी गई हैं:


  • डिफ़ॉल्ट रूप से, मतपत्र पर कोई उम्मीदवार नहीं हैं।
  • AddCandidate() फ़ंक्शन का उपयोग करके उम्मीदवारों को (केवल स्मार्ट अनुबंध स्वामी द्वारा) जोड़ा जा सकता है।
  • इसी तरह, उम्मीदवारों को (केवल स्मार्ट अनुबंध स्वामी द्वारा) removeCandidate() फ़ंक्शन का उपयोग करके हटाया जा सकता है।
  • वोट डालने से getCandidates () फ़ंक्शन का लाभ मिलेगा, जिसका उपयोग संबंधित Dapp में addVoteByName () फ़ंक्शन को कॉल करने के लिए किया जा सकता है।
  • वर्तमान वोट गणना निर्धारित करने के लिए उसी getCandidates() विधि को कॉल किया जा सकता है।
  • OpenZeppelin का स्वामित्व अनुबंध अनुबंध के स्वामित्व को सक्षम बनाता है, साथ ही स्वामित्व को किसी अन्य पते पर स्थानांतरित करने की क्षमता भी देता है।


अब, स्मार्ट अनुबंध को उपयोग के लिए तैयार करते हैं।

स्मार्ट अनुबंध का उपयोग करने की तैयारी

अपने स्मार्ट अनुबंध का उपयोग करने में सक्षम होने के लिए, हम एक साधारण ट्रफल परियोजना का निर्माण करेंगे और अनुबंध को रोपस्टेन टेस्टनेट पर तैनात करेंगे। ऐसा करने के लिए, हमें सबसे पहले Truffle के नवीनतम संस्करण की आवश्यकता होगी। साथ एनपीएम स्थापित , कमांड चलाएँ:


 npm install -g truffle


नवीनतम संस्करण को स्थापित करने से हमें इस तक पहुंच प्राप्त होगी ट्रफल डैशबोर्ड , जो हमारे स्मार्ट अनुबंध को तैनात करना इतना आसान और काफी सुरक्षित बना देगा, क्योंकि हमें अपनी निजी वॉलेट कुंजी या स्मरणीय वाक्यांश साझा नहीं करने होंगे। हालांकि हम इस पर थोड़ी देर बाद पहुंचेंगे।


इसके बाद, एक नई निर्देशिका बनाएं और एक नया Truffle प्रोजेक्ट प्रारंभ करें।


 mkdir hoa-ballot-contract && cd hoa-ballot-contract truffle init


यह एक बेयरबोन स्मार्ट कॉन्ट्रैक्ट प्रोजेक्ट बनाएगा जिसे हम फिट होने पर भर सकते हैं। तो अपने पसंदीदा कोड संपादक में प्रोजेक्ट खोलें, और चलिए इसे प्राप्त करते हैं!


OpenZeppelin का लाभ उठाने के लिए, निम्न कमांड को प्रोजेक्ट फ़ोल्डर में भी निष्पादित करने की आवश्यकता है:


 npm install @openzeppelin/contracts


Truffle-config.js फ़ाइल खोलें और हम networks ऑब्जेक्ट के अंदर Truffle डैशबोर्ड जोड़ देंगे। सभी टिप्पणी-आउट बॉयलरप्लेट के अलावा, हमारी वस्तु अब इस तरह दिखनी चाहिए:


 networks: { dashboard: { port: 24012, } }


अगले चरण के लिए, हम एक नई स्मार्ट अनुबंध फ़ाइल बनाएंगे। अनुबंध फ़ोल्डर के अंदर, एक नई फ़ाइल बनाएं और इसे HOABallot.sol नाम दें। यहां से, हम केवल ऊपर दिए गए स्मार्ट अनुबंध में पेस्ट करेंगे।


इस अनुबंध को लागू करने से पहले हमें जो आखिरी चीज करने की जरूरत है, वह है परिनियोजन स्क्रिप्ट की स्थापना। नीचे दी गई सामग्री का उपयोग करते हुए, हमें 2_hoaballot_migration.js नामक माइग्रेशन फ़ोल्डर में एक नई फ़ाइल बनाने की आवश्यकता है।


 const HOABallot = artifacts.require("HOABallot"); Module.exports = function (deployer) { deployer.deploy(HOABallot); }


अब हम अपने अनुबंध को रोपस्टेन टेस्टनेट पर तैनात करने के लिए तैयार हैं। एक नई टर्मिनल विंडो में, डैशबोर्ड शुरू करने के लिए निम्न कमांड टाइप करें:


 truffle dashboard


एक बार यह चलने के बाद, हमारे ब्राउज़र को एक इंटरफ़ेस के साथ पॉप अप करना चाहिए जो हमें अपना वॉलेट कनेक्ट करने के लिए कहेगा। यदि यह आपके लिए पॉप अप नहीं होता है, तो localhost:24012 पर नेविगेट करें।


मेटामास्क बटन को सिंगल-क्लिक करने से ब्राउज़र प्लग-इन के माध्यम से मेटामास्क लॉन्च हो जाएगा। यदि आपके पास वॉलेट ब्राउज़र एक्सटेंशन इंस्टॉल नहीं है, तो आप इसे यहां प्राप्त कर सकते हैं मेटामास्क.io . खाता बनाने के लिए चरणों का पालन करें और फिर कनेक्ट करने के लिए ट्रफल डैशबोर्ड पर वापस आएं:


एक वैध पासवर्ड दर्ज करने और अनलॉक बटन का उपयोग करने के बाद, ट्रफल डैशबोर्ड नेटवर्क के उपयोग की पुष्टि करता है:


CONFIRM बटन पर क्लिक करने के बाद, Truffle डैशबोर्ड अब अनुरोधों को सुन रहा है:


तैनाती को अंजाम देने के लिए हमें रोपस्टेन एथ की आवश्यकता होगी। यदि आपके पास कोई नहीं है, तो आप कर सकते हैं इस नल पर कुछ अनुरोध करें .


अब हमें बस इतना करना है कि अनुबंध को तैनात किया जाए। अपनी मूल टर्मिनल विंडो में, सुनिश्चित करें कि आप प्रोजेक्ट फ़ोल्डर में हैं और कमांड टाइप करें:


 truffle migrate --network dashboard


Truffle स्वचालित रूप से हमारे स्मार्ट अनुबंध को संकलित करेगा और फिर अनुरोध को डैशबोर्ड के माध्यम से रूट करेगा। प्रत्येक अनुरोध नीचे सूचीबद्ध समान प्रवाह का पालन करेगा।


सबसे पहले, ट्रफल डैशबोर्ड अनुरोध को संसाधित करने के लिए पुष्टिकरण मांगता है:


प्रोसेस बटन दबाने पर, मेटामास्क प्लग-इन पुष्टि के लिए भी पूछेगा:


पुष्टिकरण बटन प्रत्येक अनुरोध को संसाधित करने के लिए इस संबद्ध वॉलेट से धन निकालने की अनुमति देगा।


जब प्रक्रिया पूरी हो जाती है, तो ट्रफल माइग्रेट कमांड जारी करने के लिए उपयोग की जाने वाली टर्मिनल विंडो में निम्नलिखित जानकारी दिखाई देगी:


 2_hoaballot_migration.js ======================== Deploying 'HOABallot' --------------------- > transaction hash: 0x5370b6f9ee1f69e92cc6289f9cb0880386f15bff389b54ab09a966c5d144f59esage. > Blocks: 0 Seconds: 32 > contract address: 0x2981d347e288E2A4040a3C17c7e5985422e3cAf2 > block number: 12479257 > block timestamp: 1656386400 > account: 0x7fC3EF335D16C0Fd4905d2C44f49b29BdC233C94 > balance: 41.088173901232893417 > gas used: 1639525 (0x190465) > gas price: 2.50000001 gwei > value sent: 0 ETH > total cost: 0.00409881251639525 ETH > Saving migration to chain. > Saving artifacts ------------------------------------- > Total cost: 0.00409881251639525 ETH Summary ======= > Total deployments: 1 > Final cost: 0.00409881251639525 ETH


अब, अनुबंध पता मान का उपयोग करके, हम निम्न URL का उपयोग करके स्मार्ट अनुबंध को मान्य कर सकते हैं:

https://ropsten.etherscan.io/address/0x2981d347e288E2A4040a3C17c7e5985422e3cAf2


अब हम स्विच कर सकते हैं और डैप का निर्माण शुरू कर सकते हैं।

React का उपयोग करके HOA बैलेट डैप बनाना

मैं रिएक्ट सीएलआई का उपयोग करके hoa-ballot-client नामक एक रिएक्ट एप्लिकेशन बनाऊंगा:


 npx create-react-app hoa-ballot-client


इसके बाद, मैंने निर्देशिकाओं को नव-निर्मित फ़ोल्डर में बदल दिया और वेब3 और ओपनजेप्लिन निर्भरता को रिएक्ट एप्लिकेशन में स्थापित करने के लिए निम्नलिखित को निष्पादित किया:

 cd hoa-ballot-client npm install web3 npm install @openzeppelin/contracts —save


HOABallot.sol स्मार्ट अनुबंध फ़ाइल की सामग्री के आधार पर, मैंने बिल्ड/अनुबंध फ़ोल्डर में नेविगेट किया और HOBallot.json फ़ाइल खोली, फिर abi.js फ़ाइल के hoaBallot स्थिरांक के लिए "abi" गुण के लिए मानों का उपयोग किया नीचे दिखाया गया है:


 export const hoaBallot = [ { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "OwnershipTransferred", "type": "event" }, { "inputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "name": "candidates", "outputs": [ { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "uint256", "name": "votes", "type": "uint256" } ], "stateMutability": "view", "type": "function", "constant": true }, { "inputs": [], "name": "owner", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function", "constant": true }, { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "string", "name": "_name", "type": "string" } ], "name": "addCandidate", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "string", "name": "_name", "type": "string" } ], "name": "removeCandidate", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "resetVoteCount", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "string", "name": "_name", "type": "string" } ], "name": "addVoteByName", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "getCandidates", "outputs": [ { "components": [ { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "uint256", "name": "votes", "type": "uint256" } ], "internalType": "struct HOABallot.Candidate[]", "name": "", "type": "tuple[]" } ], "stateMutability": "view", "type": "function", "constant": true }, { "inputs": [], "name": "getWinner", "outputs": [ { "components": [ { "internalType": "string", "name": "name", "type": "string" }, { "internalType": "uint256", "name": "votes", "type": "uint256" } ], "internalType": "struct HOABallot.Candidate", "name": "winner", "type": "tuple" } ], "stateMutability": "view", "type": "function", "constant": true } ];


इस फ़ाइल को रिएक्ट एप्लिकेशन के src फ़ोल्डर के अंदर एक नव-निर्मित abi फ़ोल्डर में रखा गया था।


अब, हमें React Apps.js फ़ाइल को अपडेट करने की आवश्यकता है। आइए पहले फ़ाइल के शीर्ष से शुरू करें, जिसे नीचे दिखाए अनुसार कॉन्फ़िगर करने की आवश्यकता है:


 import React, { useState } from "react"; import { hoaBallot } from "./abi/abi"; import Web3 from "web3"; import "./App.css"; const web3 = new Web3(Web3.givenProvider); const contractAddress = "0x2981d347e288E2A4040a3C17c7e5985422e3cAf2"; const storageContract = new web3.eth.Contract(hoaBallot, contractAddress);


अनुबंध पता कई तरीकों से पाया जा सकता है। इस मामले में, मैंने ट्रफल - माइग्रेट सीएलआई कमांड में परिणामों का उपयोग किया। एक अन्य विकल्प इथरस्कैन साइट का उपयोग करना है।


अब, जो कुछ बचा है, वह निम्नलिखित चीजों को पूरा करने के लिए मानक रिएक्ट कोड बनाना है:


  • एक HOA राष्ट्रपति पद के उम्मीदवार को जोड़ें
  • एक HOA राष्ट्रपति पद के उम्मीदवार को हटा दें
  • HOA राष्ट्रपति पद के उम्मीदवारों की सूची प्राप्त करें
  • एक HOA राष्ट्रपति पद के उम्मीदवार के लिए वोट करें
  • HOA अध्यक्ष का निर्धारण करें


अपने "मूविंग फ्रॉम फुल-स्टैक डेवलपर टू वेब3 पायनियर" प्रकाशन में, मैंने एनएवी घटक भी जोड़ा, ताकि आसान संदर्भ के लिए मतदाता का पता प्रदर्शित किया जा सके।


अपडेट किया गया रिएक्ट एप्लिकेशन अब निम्नानुसार दिखाई देता है:


 const web3 = new Web3(Web3.givenProvider); const contractAddress = "0x2981d347e288E2A4040a3C17c7e5985422e3cAf2"; const storageContract = new web3.eth.Contract(hoaBallot, contractAddress); const gasMultiplier = 1.5; const useStyles = makeStyles((theme) => ({ root: { "& > *": { margin: theme.spacing(1), }, }, })); const StyledTableCell = styled(TableCell)(({ theme }) => ({ [`&.${tableCellClasses.head}`]: { backgroundColor: theme.palette.common.black, color: theme.palette.common.white, fontSize: 14, fontWeight: 'bold' }, [`&.${tableCellClasses.body}`]: { fontSize: 14 }, })); function App() { const classes = useStyles(); const [newCandidateName, setNewCandidateName] = useState(""); const [account, setAccount] = useState(""); const [owner, setOwner] = useState(""); const [candidates, updateCandidates] = useState([]); const [winner, setWinner] = useState("unknown candidate"); const [waiting, setWaiting] = useState(false); const loadAccount = async(useSpinner) => { if (useSpinner) { setWaiting(true); } const web3 = new Web3(Web3.givenProvider || "http://localhost:8080"); const accounts = await web3.eth.getAccounts(); setAccount(accounts[0]); if (useSpinner) { setWaiting(false); } } const getOwner = async (useSpinner) => { if (useSpinner) { setWaiting(true); } const owner = await storageContract.methods.owner().call(); setOwner(owner); if (useSpinner) { setWaiting(false); } }; const getCandidates = async (useSpinner) => { if (useSpinner) { setWaiting(true); } const candidates = await storageContract.methods.getCandidates().call(); updateCandidates(candidates); await determineWinner(); if (useSpinner) { setWaiting(false); } }; const determineWinner = async () => { const winner = await storageContract.methods.getWinner().call(); if (winner && winner.name) { setWinner(winner.name); } else { setWinner("<unknown candidate>") } } const vote = async (candidate) => { setWaiting(true); const gas = (await storageContract.methods.addVoteByName(candidate).estimateGas({ data: candidate, from: account })) * gasMultiplier; let gasAsInt = gas.toFixed(0); await storageContract.methods.addVoteByName(candidate).send({ from: account, data: candidate, gasAsInt, }); await getCandidates(false); setWaiting(false); } const removeCandidate = async (candidate) => { setWaiting(true); const gas = (await storageContract.methods.removeCandidate(candidate).estimateGas({ data: candidate, from: account })) * gasMultiplier; let gasAsInt = gas.toFixed(0); await storageContract.methods.removeCandidate(candidate).send({ from: account, data: candidate, gasAsInt, }); await getCandidates(false); setWaiting(false); } const addCandidate = async () => { setWaiting(true); const gas = (await storageContract.methods.addCandidate(newCandidateName).estimateGas({ data: newCandidateName, from: account })) * gasMultiplier; let gasAsInt = gas.toFixed(0); await storageContract.methods.addCandidate(newCandidateName).send({ from: account, data: newCandidateName, gasAsInt, }); await getCandidates(false); setWaiting(false); } React.useEffect(() => { setWaiting(true); getOwner(false).then(r => { loadAccount(false).then(r => { getCandidates(false).then(r => { setWaiting(false); }); }); }); // eslint-disable-next-line react-hooks/exhaustive-deps },[]); return ( <div className={classes.root}> <Nav /> <div className="main"> <div className="card"> <Typography variant="h3"> HOABallot </Typography> {(owner && owner.length > 0) && ( <div className="paddingBelow"> <Typography variant="caption" > This ballot is owned by: {owner} </Typography> </div> )} {waiting && ( <div className="spinnerArea" > <CircularProgress /> <Typography gutterBottom> Processing Request ... please wait </Typography> </div> )} {(owner && owner.length > 0 && account && account.length > 0 && owner === account) && ( <div className="ownerActions generalPadding"> <Grid container spacing={3}> <Grid item xs={12}> <Typography variant="h6" gutterBottom> Ballot Owner Actions </Typography> </Grid> <Grid item xs={6} sm={6}> <TextField id="newCandidateName" value={newCandidateName} label="Candidate Name" variant="outlined" onChange={event => { const { value } = event.target; setNewCandidateName(value); }} /> </Grid> <Grid item xs={6} sm={6}> <Button id="addCandidateButton" className="button" variant="contained" color="primary" type="button" size="large" onClick={addCandidate}>Add New Candidate</Button> </Grid> </Grid> </div> )} <Typography variant="h5" gutterBottom className="generalPadding"> Candidates </Typography> {(!candidates || candidates.length === 0) && ( <div> <div className="paddingBelow"> <Typography variant="normal"> No candidates current exist. </Typography> </div> <div> <Typography variant="normal" gutterBottom> Ballot owner must use the <strong>ADD NEW CANDIDATE</strong> button to add candidates. </Typography> </div> </div> )} {(candidates && candidates.length > 0) && ( <div> <TableContainer component={Paper}> <Table sx={{ minWidth: 650 }} aria-label="customized table"> <TableHead> <TableRow> <StyledTableCell>Candidate Name</StyledTableCell> <StyledTableCell align="right">Votes</StyledTableCell> <StyledTableCell align="center">Actions</StyledTableCell> </TableRow> </TableHead> <TableBody> {candidates.map((row) => ( <TableRow key={row.name} sx={{ '&:last-child td, &:last-child th': { border: 0 } }} > <TableCell component="th" scope="row"> {row.name} </TableCell> <TableCell align="right">{row.votes}</TableCell> <TableCell align="center"> <Button color="success" variant="contained" onClick={() => { vote(row.name); }} > Vote </Button> &nbsp; {(owner && owner.length > 0 && account && account.length > 0 && owner === account) && <Button color="error" variant="contained" onClick={() => { removeCandidate(row.name); }} > Remove Candidate </Button> } </TableCell> </TableRow> ))} </TableBody> </Table> </TableContainer> <div className="generalPadding"> <Typography variant="normal" gutterBottom> {winner} is winning the election. </Typography> </div> </div> )} </div> </div> </div> ); } export default App;


प्रतिक्रिया-आधारित डैप शुरू करने के लिए, यार्न सीएलआई का उपयोग किया जा सकता है:


 yarn start


एक बार संकलित और मान्य होने के बाद, आवेदन स्क्रीन पर दिखाई देगा, जैसा कि नीचे दिखाया गया है:



वीडियो के दौरान:


  • मैंने पुष्टि की है कि मैं अनुबंध का स्वामी था, क्योंकि "आपका कनेक्टेड पता" मान "यह मतपत्र इसके स्वामित्व में है" मान के लिए एक सटीक मिलान है और मतपत्र स्वामी कार्रवाई अनुभाग प्रदर्शित होता है।
  • अनुबंध के मालिक के रूप में, मैं चुनाव के लिए उम्मीदवारों को स्थापित करने के लिए नए उम्मीदवार जोड़ें बटन को देखने और उपयोग करने में सक्षम था। मैंने इस उदाहरण के लिए डेव ब्राउन और स्टीव स्मिथ नामों का इस्तेमाल किया।
  • अनुबंध के मालिक के रूप में, मैं उम्मीदवार को हटाने के बटन का भी उपयोग कर सकता था।
  • दोनों उम्मीदवारों को बनाने के बाद, मैंने वांछित उम्मीदवार के समान पंक्ति पर VOTE बटन का उपयोग करके दो उम्मीदवारों में से एक को वोट दिया। मैंने डेव ब्राउन को वोट दिया।
  • चुनाव के वर्तमान विजेता को उम्मीदवारों की तालिका के नीचे प्रदर्शित किया गया है। इस मामले में, यह डेव ब्राउन है।


स्मार्ट अनुबंध को लागू करने के बाद से, कोई भी निम्नलिखित URL पर पूरा इतिहास देख सकता है:


https://ropsten.etherscan.io/address/0x2981d347e288E2A4040a3C17c7e5985422e3cAf2


निष्कर्ष

2021 से, मैं निम्नलिखित मिशन वक्तव्य के अनुसार जीने की कोशिश कर रहा हूं, जो मुझे लगता है कि किसी भी प्रौद्योगिकी पेशेवर पर लागू हो सकता है:


"अपना समय उन सुविधाओं/कार्यक्षमताओं को प्रदान करने पर केंद्रित करें जो आपकी बौद्धिक संपदा के मूल्य का विस्तार करती हैं। अन्य सभी चीजों के लिए ढांचे, उत्पादों और सेवाओं का लाभ उठाएं।"
जे वेस्टर


स्मार्ट अनुबंध दो पक्षों को एक समझौते में प्रवेश करने की अनुमति देने की क्षमता प्रदान करते हैं जहां अनुबंध का परिणाम लेनदेन का एक सेट-इन-स्टोन आधिकारिक रिकॉर्ड बन जाता है। एक स्मार्ट अनुबंध को अपनाना मेरे व्यक्तिगत मिशन वक्तव्य का पालन करता है जिसमें अंतर्निहित ढांचा इस तरह के अनुबंध की आवश्यकता होने पर पहिया को फिर से शुरू करने से बचता है।


साथ ही, स्मार्ट अनुबंध डिज़ाइन स्वयं एक कदम आगे बढ़ता है और पुन: प्रयोज्य कारक से मेरे मिशन कथन को पूरा करता है। इस उदाहरण में, वर्तमान चुनाव में विभिन्न उम्मीदवारों के चलने के बावजूद, समान HOA स्मार्ट अनुबंध का उपयोग किया जा सकता है। यहां हम हर बार चुनाव होने पर एक नया स्मार्ट अनुबंध बनाने से बचने के लिए स्मार्ट अनुबंध की शक्ति का लाभ उठाते हैं।


Google के ETH से USD कनवर्टर का उपयोग करके किसी एक लेन-देन के रूपांतरण मूल्य को देखने के लिए इथरस्कैन का उपयोग करते समय, प्रति लेन-देन की लागत 0.0001348975 ETH के लिए 0.24 (USD) थी। विडंबना यह है कि जब मैं बच्चा था तब एक गमबेल मशीन से एक मामूली गमबेल की कीमत थी।


यदि आप स्मार्ट अनुबंधों के बारे में अधिक जानना चाहते हैं, तो ConsenSys की टीम ने आपके विचारों को प्रोटोटाइप बनाने में मदद करने के लिए उत्कृष्ट संसाधन प्रदान किए हैं, यह देखने के लिए कि क्या स्मार्ट अनुबंध अपनाना एक वैध उपयोग का मामला है।


यदि आप इस लेख के स्रोत कोड में रुचि रखते हैं, तो आप इसे निम्नलिखित URL पर पा सकते हैं:


https://github.com/paul-mcaviney/smart-contract-deep-dive/blob/main/HOABallot.sol

https://gitlab.com/johnjvester/hoa-ballot-contract

https://gitlab.com/johnjvester/hoa-ballot-client


आपका दिन वाकई बहुत अच्छा हो!