From b4f3a8e09262a08308a88a4741995ce003e0bb17 Mon Sep 17 00:00:00 2001 From: Joshua <62268199+minimalsm@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:13:38 +0000 Subject: [PATCH] i18n(mr): translation import part 07 of 13 (23 files) --- .../mr/developers/docs/transactions/index.md | 231 +++ .../mr/developers/docs/web2-vs-web3/index.md | 62 + .../index.md | 300 ++++ .../tutorials/all-you-can-cache/index.md | 867 ++++++++++ .../developers/tutorials/app-plasma/index.md | 1256 ++++++++++++++ .../index.md | 131 ++ .../index.md | 585 +++++++ .../index.md | 101 ++ .../index.md | 372 ++++ .../index.md | 144 ++ .../index.md | 129 ++ .../erc-721-vyper-annotated-code/index.md | 644 +++++++ .../tutorials/erc20-annotated-code/index.md | 917 ++++++++++ .../erc20-with-safety-rails/index.md | 217 +++ .../tutorials/ethereum-for-web2-auth/index.md | 886 ++++++++++ .../index.md | 156 ++ .../index.md | 102 ++ .../index.md | 1540 +++++++++++++++++ .../hello-world-smart-contract/index.md | 366 ++++ .../index.md | 151 ++ .../tutorials/how-to-mint-an-nft/index.md | 335 ++++ .../index.md | 108 ++ .../index.md | 708 ++++++++ 23 files changed, 10308 insertions(+) create mode 100644 public/content/translations/mr/developers/docs/transactions/index.md create mode 100644 public/content/translations/mr/developers/docs/web2-vs-web3/index.md create mode 100644 public/content/translations/mr/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md create mode 100644 public/content/translations/mr/developers/tutorials/all-you-can-cache/index.md create mode 100644 public/content/translations/mr/developers/tutorials/app-plasma/index.md create mode 100644 public/content/translations/mr/developers/tutorials/calling-a-smart-contract-from-javascript/index.md create mode 100644 public/content/translations/mr/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md create mode 100644 public/content/translations/mr/developers/tutorials/deploying-your-first-smart-contract/index.md create mode 100644 public/content/translations/mr/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md create mode 100644 public/content/translations/mr/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md create mode 100644 public/content/translations/mr/developers/tutorials/eip-1271-smart-contract-signatures/index.md create mode 100644 public/content/translations/mr/developers/tutorials/erc-721-vyper-annotated-code/index.md create mode 100644 public/content/translations/mr/developers/tutorials/erc20-annotated-code/index.md create mode 100644 public/content/translations/mr/developers/tutorials/erc20-with-safety-rails/index.md create mode 100644 public/content/translations/mr/developers/tutorials/ethereum-for-web2-auth/index.md create mode 100644 public/content/translations/mr/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md create mode 100644 public/content/translations/mr/developers/tutorials/guide-to-smart-contract-security-tools/index.md create mode 100644 public/content/translations/mr/developers/tutorials/hello-world-smart-contract-fullstack/index.md create mode 100644 public/content/translations/mr/developers/tutorials/hello-world-smart-contract/index.md create mode 100644 public/content/translations/mr/developers/tutorials/how-to-implement-an-erc721-market/index.md create mode 100644 public/content/translations/mr/developers/tutorials/how-to-mint-an-nft/index.md create mode 100644 public/content/translations/mr/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md create mode 100644 public/content/translations/mr/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md diff --git a/public/content/translations/mr/developers/docs/transactions/index.md b/public/content/translations/mr/developers/docs/transactions/index.md new file mode 100644 index 00000000000..7b6ab93d7d2 --- /dev/null +++ b/public/content/translations/mr/developers/docs/transactions/index.md @@ -0,0 +1,231 @@ +--- +title: "व्यवहार" +description: "Ethereum व्यवहारांचे विहंगावलोकन – ते कसे कार्य करतात, त्यांची डेटा संरचना, आणि त्यांना ॲप्लिकेशनद्वारे कसे पाठवायचे." +lang: mr +--- + +व्यवहार हे खात्यांमधून क्रिप्टोग्राफिकली स्वाक्षरी केलेल्या सूचना आहेत. एक खाते Ethereum नेटवर्कची स्थिती अद्ययावत करण्यासाठी व्यवहार सुरू करेल. सर्वात सोपा व्यवहार म्हणजे एका खात्यातून दुसऱ्या खात्यात ETH हस्तांतरित करणे. + +## पूर्वतयारी {#prerequisites} + +हे पान तुम्हाला अधिक चांगल्या प्रकारे समजण्यास मदत करण्यासाठी, आम्ही शिफारस करतो की तुम्ही प्रथम [खाती](/developers/docs/accounts/) आणि आमचा [Ethereum चा परिचय](/developers/docs/intro-to-ethereum/) वाचा. + +## व्यवहार म्हणजे काय? {#whats-a-transaction} + +Ethereum व्यवहार म्हणजे बाह्य-मालकीच्या खात्याद्वारे सुरू केलेली क्रिया, दुसऱ्या शब्दांत, मानवाद्वारे व्यवस्थापित केलेले खाते, कराराद्वारे नाही. उदाहरणार्थ, जर बॉबने ॲलिसला १ ETH पाठवले, तर बॉबच्या खात्यातून पैसे वजा केले पाहिजेत आणि ॲलिसच्या खात्यात जमा केले पाहिजेत. ही स्थिती-बदलणारी क्रिया एका व्यवहारामध्ये होते. + +![व्यवहारामुळे स्थितीतील बदल दर्शवणारे रेखाचित्र](./tx.png) +_[Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf) वरून रुपांतरित रेखाचित्र_ + +व्यवहार, जे EVM ची स्थिती बदलतात, ते संपूर्ण नेटवर्कवर प्रसारित करणे आवश्यक आहे. कोणताही नोड EVM वर व्यवहार कार्यान्वित करण्याची विनंती प्रसारित करू शकतो; हे घडल्यानंतर, एक व्हॅलिडेटर तो व्यवहार कार्यान्वित करेल आणि परिणामी स्थितीतील बदल उर्वरित नेटवर्कमध्ये प्रसारित करेल. + +व्यवहारांसाठी शुल्क आवश्यक आहे आणि त्यांना प्रमाणित ब्लॉकमध्ये समाविष्ट करणे आवश्यक आहे. हे विहंगावलोकन सोपे करण्यासाठी आम्ही गॅस शुल्क आणि प्रमाणीकरण यावर इतरत्र चर्चा करू. + +सादर केलेल्या व्यवहारामध्ये खालील माहिती समाविष्ट असते: + +- `from` – प्रेषकाचा पत्ता, जो व्यवहारावर स्वाक्षरी करेल. हे बाह्य-मालकीचे खाते असेल कारण करार खाती व्यवहार पाठवू शकत नाहीत +- `to` – प्राप्तकर्त्याचा पत्ता (जर बाह्य-मालकीचे खाते असेल, तर व्यवहार मूल्य हस्तांतरित करेल. जर करार खाते असेल तर, व्यवहार करार कोड कार्यान्वित करेल) +- `signature` – प्रेषकाचा ओळखकर्ता. जेव्हा प्रेषकाची खाजगी की व्यवहारावर स्वाक्षरी करते तेव्हा हे तयार केले जाते आणि पुष्टी करते की प्रेषकाने या व्यवहारास अधिकृत केले आहे +- `nonce` - एक क्रमशः वाढणारा काउंटर जो खात्यामधील व्यवहार क्रमांक दर्शवतो +- `value` – प्रेषकाकडून प्राप्तकर्त्याकडे हस्तांतरित करायची ETH ची रक्कम (WEI मध्ये दर्शवलेले, जिथे १ ETH = १e+१८ wei) +- `input data` – ऐच्छिक डेटा समाविष्ट करण्यासाठी वैकल्पिक फील्ड +- `gasLimit` – व्यवहारामुळे वापरल्या जाऊ शकणाऱ्या गॅस युनिट्सची कमाल रक्कम. [EVM](/developers/docs/evm/opcodes) प्रत्येक संगणकीय पायरीसाठी आवश्यक असलेल्या गॅसच्या युनिट्सची माहिती देते +- `maxPriorityFeePerGas` - व्हॅलिडेटरला टीप म्हणून समाविष्ट करण्यासाठी वापरलेल्या गॅसची कमाल किंमत +- `maxFeePerGas` - व्यवहारासाठी प्रति युनिट गॅससाठी देण्यास तयार असलेले कमाल शुल्क (`baseFeePerGas` आणि `maxPriorityFeePerGas` सह) + +गॅस म्हणजे व्हॅलिडेटरद्वारे व्यवहार प्रक्रिया करण्यासाठी आवश्यक असलेल्या गणनेचा संदर्भ. वापरकर्त्यांना या गणनेसाठी शुल्क भरावे लागते. `gasLimit`, आणि `maxPriorityFeePerGas` व्हॅलिडेटरला दिले जाणारे कमाल व्यवहार शुल्क निश्चित करतात. [गॅसवर अधिक](/developers/docs/gas/). + +व्यवहार ऑब्जेक्ट काहीसा असा दिसेल: + +```js +{ + from: "0xEA674fdDe714fd979de3EdF0F56AA9716B898ec8", + to: "0xac03bb73b6a9e108530aff4df5077c2b3d481e5a", + gasLimit: "21000", + maxFeePerGas: "300", + maxPriorityFeePerGas: "10", + nonce: "0", + value: "10000000000" +} +``` + +परंतु व्यवहार ऑब्जेक्टवर प्रेषकाच्या खाजगी की वापरून स्वाक्षरी करणे आवश्यक आहे. हे सिद्ध करते की व्यवहार केवळ प्रेषकाकडूनच आला आहे आणि तो फसवणुकीने पाठवला गेला नाही. + +Geth सारखा Ethereum क्लायंट ही स्वाक्षरी प्रक्रिया हाताळेल. + +उदाहरण [JSON-RPC](/developers/docs/apis/json-rpc) कॉल: + +```json +{ + "id": 2, + "jsonrpc": "2.0", + "method": "account_signTransaction", + "params": [ + { + "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db", + "gas": "0x55555", + "maxFeePerGas": "0x1234", + "maxPriorityFeePerGas": "0x1234", + "input": "0xabcd", + "nonce": "0x0", + "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", + "value": "0x1234" + } + ] +} +``` + +उदाहरण प्रतिसाद: + +```json +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", + "tx": { + "nonce": "0x0", + "maxFeePerGas": "0x1234", + "maxPriorityFeePerGas": "0x1234", + "gas": "0x55555", + "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", + "value": "0x1234", + "input": "0xabcd", + "v": "0x26", + "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e", + "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", + "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e" + } + } +} +``` + +- `raw` हे स्वाक्षरी केलेला व्यवहार [रिकर्सिव्ह लेंथ प्रिफिक्स (RLP)](/developers/docs/data-structures-and-encoding/rlp) एन्कोड केलेल्या स्वरूपात आहे +- `tx` हे JSON स्वरूपात स्वाक्षरी केलेला व्यवहार आहे + +स्वाक्षरी हॅशसह, व्यवहार क्रिप्टोग्राफिकली सिद्ध केला जाऊ शकतो की तो प्रेषकाकडून आला आहे आणि नेटवर्कवर सादर केला गेला आहे. + +### डेटा फील्ड {#the-data-field} + +बहुतेक व्यवहार बाह्य-मालकीच्या खात्यातून करारावर प्रवेश करतात. +बहुतेक करार Solidity मध्ये लिहिलेले आहेत आणि ते त्यांच्या डेटा फील्डचा अर्थ [ॲप्लिकेशन बायनरी इंटरफेस (ABI)](/glossary/#abi) नुसार लावतात. + +पहिले चार बाइट्स फंक्शनच्या नावाचा आणि वितर्कांचा हॅश वापरून कोणते फंक्शन कॉल करायचे हे निर्दिष्ट करतात. +[या डेटाबेस](https://www.4byte.directory/signatures/) चा वापर करून तुम्ही सिलेक्टरमधून फंक्शन ओळखू शकता. + +उर्वरित कॉलगडाटा वितर्क आहेत, जे [ABI स्पेसिफिकेशन्समध्ये निर्दिष्ट केल्याप्रमाणे एन्कोड केलेले आहेत](https://docs.soliditylang.org/en/latest/abi-spec.html#formal-specification-of-the-encoding). + +उदाहरणार्थ, [या व्यवहारावर](https://etherscan.io/tx/0xd0dcbe007569fcfa1902dae0ab8b4e078efe42e231786312289b1eee5590f6a1) एक नजर टाकूया. +कॉलडाटा पाहण्यासाठी **अधिक पाहण्यासाठी क्लिक करा** वापरा. + +फंक्शन सिलेक्टर `0xa9059cbb` आहे. [या स्वाक्षरीसह अनेक ज्ञात फंक्शन्स](https://www.4byte.directory/signatures/?bytes4_signature=0xa9059cbb) आहेत. +या प्रकरणात, [करार स्रोत कोड](https://etherscan.io/address/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48#code) Etherscan वर अपलोड केला आहे, म्हणून आम्हाला माहित आहे की फंक्शन `transfer(address,uint256)` आहे. + +उर्वरित डेटा आहे: + +``` +0000000000000000000000004f6742badb049791cd9a37ea913f2bac38d01279 +000000000000000000000000000000000000000000000000000000003b0559f4 +``` + +ABI स्पेसिफिकेशन्सनुसार, पूर्णांक मूल्ये (जसे की पत्ते, जे २०-बाइट पूर्णांक आहेत) ABI मध्ये ३२-बाइट शब्दांच्या रूपात दिसतात, ज्यांच्या समोर शून्यांनी पॅडिंग केलेले असते. +म्हणून आम्हाला माहित आहे की `to` पत्ता [`4f6742badb049791cd9a37ea913f2bac38d01279`](https://etherscan.io/address/0x4f6742badb049791cd9a37ea913f2bac38d01279) आहे. +`value` 0x3b0559f4 = ९९०२०६४५२ आहे. + +## व्यवहारांचे प्रकार {#types-of-transactions} + +Ethereum वर काही वेगवेगळ्या प्रकारचे व्यवहार आहेत: + +- नियमित व्यवहार: एका खात्यातून दुसऱ्या खात्यात केलेला व्यवहार. +- करार उपयोजन व्यवहार: 'to' पत्त्याशिवाय केलेला व्यवहार, जिथे डेटा फील्ड करार कोडसाठी वापरले जाते. +- कराराची अंमलबजावणी: उपयोजित स्मार्ट कराराशी संवाद साधणारा व्यवहार. या प्रकरणात, 'to' पत्ता स्मार्ट करार पत्ता आहे. + +### गॅसवर {#on-gas} + +नमूद केल्याप्रमाणे, व्यवहार कार्यान्वित करण्यासाठी [गॅस](/developers/docs/gas/) खर्च येतो. साध्या हस्तांतरण व्यवहारांना २१००० युनिट्स गॅसची आवश्यकता असते. + +म्हणून बॉबला ॲलिसला १ ETH पाठवण्यासाठी १९० gwei च्या `baseFeePerGas` आणि १० gwei च्या `maxPriorityFeePerGas` वर, बॉबला खालील शुल्क भरावे लागेल: + +``` +(१९० + १०) * २१००० = ४,२००,००० gwei +--किंवा-- +०.००४२ ETH +``` + +बॉबच्या खात्यातून **-१.००४२ ETH** डेबिट केले जातील (ॲलिससाठी १ ETH + गॅस शुल्कात ०.००४२ ETH) + +ॲलिसच्या खात्यात **+१.० ETH** जमा केले जातील + +आधार शुल्क **-०.००३९९ ETH** बर्न केले जाईल + +व्हॅलिडेटर **+०.०००२१० ETH** टीप ठेवतो + +![न वापरलेला गॅस कसा परत केला जातो हे दर्शवणारे रेखाचित्र](./gas-tx.png) +_[Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf) वरून रुपांतरित रेखाचित्र_ + +व्यवहारात न वापरलेला कोणताही गॅस वापरकर्त्याच्या खात्यात परत केला जातो. + +### स्मार्ट करार संवाद {#smart-contract-interactions} + +स्मार्ट कराराचा समावेश असलेल्या कोणत्याही व्यवहारासाठी गॅस आवश्यक आहे. + +स्मार्ट करारांमध्ये [`view`](https://docs.soliditylang.org/en/latest/contracts.html#view-functions) किंवा [`pure`](https://docs.soliditylang.org/en/latest/contracts.html#pure-functions) म्हणून ओळखले जाणारे फंक्शन्स देखील असू शकतात, जे कराराची स्थिती बदलत नाहीत. त्यामुळे, EOA मधून या फंक्शन्सना कॉल करण्यासाठी कोणत्याही गॅसची आवश्यकता नसते. या परिस्थितीसाठी अंतर्निहित RPC कॉल [`eth_call`](/developers/docs/apis/json-rpc#eth_call) आहे. + +`eth_call` वापरून प्रवेश करण्याच्या विपरीत, हे `view` किंवा `pure` फंक्शन्स सामान्यतः अंतर्गतपणे (म्हणजे, करारातूनच किंवा दुसऱ्या करारातून) कॉल केले जातात, ज्यासाठी गॅस खर्च येतो. + +## व्यवहार जीवनचक्र {#transaction-lifecycle} + +एकदा व्यवहार सादर केल्यावर खालील गोष्टी घडतात: + +1. एक व्यवहार हॅश क्रिप्टोग्राफिकली तयार केला जातो: + `0x97d99bc7729211111a21b12c933c949d4f31684f1d6954ff477d0477538ff017` +2. त्यानंतर व्यवहार नेटवर्कवर प्रसारित केला जातो आणि इतर सर्व प्रलंबित नेटवर्क व्यवहारांचा समावेश असलेल्या व्यवहार पूलमध्ये जोडला जातो. +3. एका व्हॅलिडेटरने तुमचा व्यवहार निवडून तो ब्लॉकमध्ये समाविष्ट करणे आवश्यक आहे जेणेकरून व्यवहार सत्यापित होईल आणि तो "यशस्वी" मानला जाईल. +4. जसजसा वेळ जाईल तसतसे तुमच्या व्यवहाराचा समावेश असलेला ब्लॉक "न्याय्य" आणि नंतर "अंतिम" म्हणून अपग्रेड केला जाईल. हे अपग्रेड्स तुमचा व्यवहार यशस्वी झाल्याची आणि तो कधीही बदलला जाणार नाही याची अधिक खात्री देतात. एकदा एखादा ब्लॉक "अंतिम" झाला की तो फक्त नेटवर्क स्तरावरील हल्ल्यानेच बदलला जाऊ शकतो ज्यासाठी अब्जावधी डॉलर्स खर्च येऊ शकतो. + +## एक दृश्यात्मक डेमो {#a-visual-demo} + +ऑस्टिनला व्यवहार, गॅस आणि मायनिंगमधून तुम्हाला मार्गदर्शन करताना पहा. + + + +## टाइप्ड ट्रान्झॅक्शन एनव्हेलप {#typed-transaction-envelope} + +Ethereum मध्ये मूळतः व्यवहारांसाठी एकच स्वरूप होते. प्रत्येक व्यवहारामध्ये नॉन्स, गॅस प्राइस, गॅस लिमिट, टू ॲड्रेस, व्हॅल्यू, डेटा, v, r आणि s यांचा समावेश होता. हे फील्ड्स [RLP-एन्कोडेड](/developers/docs/data-structures-and-encoding/rlp/) आहेत, जे असे दिसतात: + +`RLP([nonce, gasPrice, gasLimit, to, value, data, v, r, s])` + +ॲक्सेस लिस्ट्स आणि [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) सारख्या नवीन वैशिष्ट्यांची अंमलबजावणी करण्यासाठी, जुन्या व्यवहार स्वरूपांवर परिणाम न करता, Ethereum आता अनेक प्रकारच्या व्यवहारांना समर्थन देण्यासाठी विकसित झाले आहे. + +[EIP-2718](https://eips.ethereum.org/EIPS/eip-2718) हे या वर्तनास परवानगी देते. व्यवहारांचा अर्थ असा लावला जातो: + +`TransactionType || TransactionPayload` + +जिथे फील्ड्स खालीलप्रमाणे परिभाषित आहेत: + +- `TransactionType` - ० ते ०x७f मधील एक संख्या, एकूण १२८ संभाव्य व्यवहार प्रकारांसाठी. +- `TransactionPayload` - व्यवहार प्रकाराने परिभाषित केलेली एक अनियंत्रित बाइट ॲरे. + +`TransactionType` मूल्यावर आधारित, व्यवहार खालीलप्रमाणे वर्गीकृत केला जाऊ शकतो: + +1. **प्रकार ० (लेगसी) व्यवहार:** Ethereum च्या लाँचपासून वापरले जाणारे मूळ व्यवहार स्वरूप. त्यामध्ये [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) मधील वैशिष्ट्ये जसे की डायनॅमिक गॅस शुल्क गणना किंवा स्मार्ट करारांसाठी ॲक्सेस लिस्ट्स यांचा समावेश नाही. लेगसी व्यवहारांमध्ये त्यांच्या सिरियलाइज्ड स्वरूपात त्यांचा प्रकार दर्शविणारा विशिष्ट उपसर्ग नसतो, [रिकर्सिव्ह लेंथ प्रिफिक्स (RLP)](/developers/docs/data-structures-and-encoding/rlp) एन्कोडिंग वापरताना ते `0xf8` बाइटने सुरू होतात. या व्यवहारांसाठी TransactionType मूल्य `0x0` आहे. + +2. **प्रकार १ व्यवहार:** Ethereum च्या [बर्लिन अपग्रेड](/ethereum-forks/#berlin) चा भाग म्हणून [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930) मध्ये सादर केलेले, या व्यवहारांमध्ये `accessList` पॅरामीटरचा समावेश आहे. ही यादी पत्ते आणि स्टोरेज की निर्दिष्ट करते ज्यावर व्यवहार प्रवेश करण्याची अपेक्षा करतो, ज्यामुळे स्मार्ट करारांचा समावेश असलेल्या जटिल व्यवहारांसाठी [गॅस](/developers/docs/gas/) खर्च कमी होण्यास मदत होते. EIP-1559 शुल्क बाजारातील बदल प्रकार १ व्यवहारांमध्ये समाविष्ट नाहीत. प्रकार १ व्यवहारांमध्ये `yParity` पॅरामीटरचा देखील समावेश असतो, जो `0x0` किंवा `0x1` असू शकतो, जो secp256k1 स्वाक्षरीच्या y-मूल्याची समानता दर्शवतो. ते `0x01` बाइटने सुरू झाल्यामुळे ओळखले जातात आणि त्यांचे TransactionType मूल्य `0x1` आहे. + +3. **प्रकार २ व्यवहार**, सामान्यतः EIP-1559 व्यवहार म्हणून ओळखले जातात, हे Ethereum च्या [लंडन अपग्रेड](/ethereum-forks/#london) मध्ये, [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) मध्ये सादर केलेले व्यवहार आहेत. ते Ethereum नेटवर्कवर मानक व्यवहार प्रकार बनले आहेत. हे व्यवहार एक नवीन शुल्क बाजार यंत्रणा सादर करतात जी व्यवहार शुल्काचे आधार शुल्क आणि प्राधान्य शुल्कामध्ये विभाजन करून अंदाजक्षमता सुधारते. ते `0x02` बाइटने सुरू होतात आणि त्यात `maxPriorityFeePerGas` आणि `maxFeePerGas` सारख्या फील्ड्सचा समावेश असतो. प्रकार २ व्यवहार आता त्यांच्या लवचिकता आणि कार्यक्षमतेमुळे डिफॉल्ट आहेत, विशेषतः उच्च नेटवर्क गर्दीच्या काळात वापरकर्त्यांना व्यवहार शुल्क अधिक अंदाजे व्यवस्थापित करण्यात मदत करण्याच्या त्यांच्या क्षमतेमुळे पसंत केले जातात. या व्यवहारांसाठी TransactionType मूल्य `0x2` आहे. + +4. **प्रकार ३ (ब्लॉब) व्यवहार** Ethereum च्या [डेनकून अपग्रेड](/ethereum-forks/#dencun) चा भाग म्हणून [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) मध्ये सादर करण्यात आले. हे व्यवहार "ब्लॉब" डेटा (बायनरी लार्ज ऑब्जेक्ट्स) अधिक कार्यक्षमतेने हाताळण्यासाठी डिझाइन केलेले आहेत, विशेषतः लेयर २ रोलअप्सना कमी खर्चात Ethereum नेटवर्कवर डेटा पोस्ट करण्याचा मार्ग प्रदान करून फायदा देतात. ब्लॉब व्यवहारांमध्ये `blobVersionedHashes`, `maxFeePerBlobGas`, आणि `blobGasPrice` सारख्या अतिरिक्त फील्ड्सचा समावेश असतो. ते `0x03` बाइटने सुरू होतात आणि त्यांचे TransactionType मूल्य `0x3` आहे. ब्लॉब व्यवहार Ethereum च्या डेटा उपलब्धता आणि स्केलिंग क्षमतांमध्ये एक महत्त्वपूर्ण सुधारणा दर्शवतात. + +5. **प्रकार ४ व्यवहार** Ethereum च्या [पेक्ट्रा अपग्रेड](/roadmap/pectra/) चा भाग म्हणून [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) मध्ये सादर करण्यात आले. हे व्यवहार खाते अमूर्ततेसह फॉरवर्ड-कंपॅटिबल होण्यासाठी डिझाइन केलेले आहेत. ते EOAs ला त्यांची मूळ कार्यक्षमता धोक्यात न घालता तात्पुरते स्मार्ट करार खात्यांसारखे वागण्याची परवानगी देतात. त्यामध्ये `authorization_list` पॅरामीटरचा समावेश आहे, जो EOA आपला अधिकार कोणत्या स्मार्ट कराराला सोपवतो हे निर्दिष्ट करतो. व्यवहारानंतर, EOA च्या कोड फील्डमध्ये सोपवलेल्या स्मार्ट कराराचा पत्ता असेल. + +## पुढील वाचन {#further-reading} + +- [EIP-2718: टाइप्ड ट्रान्झॅक्शन एनव्हेलप](https://eips.ethereum.org/EIPS/eip-2718) + +_तुम्हाला मदत केलेल्या सामुदायिक संसाधनाबद्दल माहिती आहे का?_ हे पृष्ठ संपादित करा आणि ते जोडा!_ + +## संबंधित विषय {#related-topics} + +- [खाती](/developers/docs/accounts/) +- [Ethereum व्हर्च्युअल मशीन (EVM)](/developers/docs/evm/) +- [गॅस](/developers/docs/gas/) diff --git a/public/content/translations/mr/developers/docs/web2-vs-web3/index.md b/public/content/translations/mr/developers/docs/web2-vs-web3/index.md new file mode 100644 index 00000000000..5bb571f4f9c --- /dev/null +++ b/public/content/translations/mr/developers/docs/web2-vs-web3/index.md @@ -0,0 +1,62 @@ +--- +title: "Web2 विरुद्ध Web3" +description: "इथेरियम ब्लॉकचेन तंत्रज्ञानावर तयार केलेल्या विकेंद्रित वेब3 ॲप्लिकेशन्सची केंद्रीकृत वेब2 सेवांसोबत तुलना करा." +lang: mr +--- + +वेब2 म्हणजे आज आपल्यापैकी बहुतेकांना माहीत असलेल्या इंटरनेटची आवृत्ती. तुमच्या वैयक्तिक डेटाच्या बदल्यात सेवा पुरवणाऱ्या कंपन्यांचे वर्चस्व असलेले इंटरनेट. इथेरियमच्या संदर्भात, वेब3 म्हणजे ब्लॉकचेनवर चालणारे विकेंद्रित ॲप्स. हे असे ॲप्स आहेत जे कोणालाही त्यांच्या वैयक्तिक डेटाचे मुद्रीकरण न करता सहभागी होण्याची परवानगी देतात. + +अधिक नवशिक्यांसाठी अनुकूल संसाधन शोधत आहात का? आमची [वेब3 ची ओळख](/web3/) पहा. + +## वेब3 चे फायदे {#web3-benefits} + +इथेरियमच्या मूळ विकेंद्रीकरणामुळे अनेक वेब3 डेव्हलपर्सनी dapps तयार करणे निवडले आहे: + +- नेटवर्कवर असलेल्या कोणालाही सेवा वापरण्याची परवानगी आहे – किंवा दुसऱ्या शब्दांत, परवानगीची आवश्यकता नाही. +- कोणीही तुम्हाला ब्लॉक करू शकत नाही किंवा सेवेचा ॲक्सेस नाकारू शकत नाही. +- नेटिव्ह टोकन, इथर (ETH) द्वारे पेमेंट अंतर्भूत आहेत. +- इथेरियम ट्युरिंग-कम्प्लीट आहे, म्हणजे तुम्ही जवळजवळ काहीही प्रोग्राम करू शकता. + +## व्यावहारिक तुलना {#practical-comparisons} + +| वेब2 | Web3 | +| ------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | +| ट्विटर कोणतेही खाते किंवा ट्वीट सेन्सॉर करू शकते | वेब3 ट्वीट्स सेन्सॉर करता येणार नाहीत कारण नियंत्रण विकेंद्रित आहे | +| पेमेंट सेवा विशिष्ट प्रकारच्या कामासाठी पेमेंटला परवानगी न देण्याचा निर्णय घेऊ शकते | वेब3 पेमेंट ॲप्सना कोणत्याही वैयक्तिक डेटाची आवश्यकता नसते आणि ते पेमेंट रोखू शकत नाहीत | +| गिग-इकॉनॉमी ॲप्सचे सर्व्हर बंद होऊ शकतात आणि कामगारांच्या उत्पन्नावर परिणाम होऊ शकतो | वेब3 सर्व्हर बंद होऊ शकत नाहीत – ते त्यांच्या बॅकएंड म्हणून इथेरियम, हजारो संगणकांचे विकेंद्रित नेटवर्क वापरतात | + +याचा अर्थ असा नाही की सर्व सेवांचे dapp मध्ये रूपांतर करणे आवश्यक आहे. ही उदाहरणे वेब2 आणि वेब3 सेवांमधील मुख्य फरकांची निदर्शक आहेत. + +## वेब3 च्या मर्यादा {#web3-limitations} + +सध्या वेब3 मध्ये काही मर्यादा आहेत: + +- स्केलेबिलिटी – व्यवहार वेब3 वर धीमे आहेत कारण ते विकेंद्रित आहेत. पेमेंटसारख्या स्टेटमधील बदलांवर नोडद्वारे प्रक्रिया करणे आणि संपूर्ण नेटवर्कमध्ये प्रसारित करणे आवश्यक आहे. +- UX – वेब3 ॲप्लिकेशन्सशी संवाद साधण्यासाठी अतिरिक्त पायऱ्या, सॉफ्टवेअर आणि शिक्षणाची आवश्यकता असू शकते. हे अवलंबण्यात एक अडथळा असू शकतो. +- ॲक्सेसिबिलिटी – आधुनिक वेब ब्राउझरमध्ये एकत्रीकरणाच्या अभावामुळे वेब3 बहुतेक वापरकर्त्यांसाठी कमी ॲक्सेसिबल बनते. +- खर्च – बहुतेक यशस्वी dapps त्यांच्या कोडचा खूप छोटा भाग ब्लॉकचेनवर ठेवतात कारण ते महाग आहे. + +## केंद्रीकरण विरुद्ध विकेंद्रीकरण {#centralization-vs-decentralization} + +खालील तक्त्यामध्ये, आम्ही केंद्रीकृत आणि विकेंद्रित डिजिटल नेटवर्क्सचे काही ढोबळ फायदे आणि तोटे सूचीबद्ध करतो. + +| केंद्रीकृत प्रणाली | विकेंद्रित प्रणाली | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| कमी नेटवर्क व्यास (सर्व सहभागी एका केंद्रीय प्राधिकरणाशी जोडलेले असतात); माहिती त्वरीत प्रसारित होते, कारण प्रसार मोठ्या प्रमाणात संगणकीय संसाधने असलेल्या केंद्रीय प्राधिकरणाद्वारे हाताळला जातो. | नेटवर्कवरील सर्वात दूरचे सहभागी एकमेकांपासून संभाव्यतः अनेक एजेस दूर असू शकतात. नेटवर्कच्या एका बाजूने प्रसारित केलेल्या माहितीला दुसऱ्या बाजूला पोहोचायला बराच वेळ लागू शकतो. | +| सहसा उच्च कार्यक्षमता (उच्च थ्रुपुट, एकूण कमी संगणकीय संसाधने खर्च) आणि अंमलबजावणी करणे सोपे. | सहसा कमी कार्यक्षमता (कमी थ्रुपुट, अधिक एकूण संगणकीय संसाधने खर्च) आणि अंमलबजावणी करणे अधिक क्लिष्ट. | +| परस्परविरोधी डेटाच्या बाबतीत, निराकरण स्पष्ट आणि सोपे आहे: सत्याचा अंतिम स्त्रोत केंद्रीय प्राधिकरण आहे. | ज्या डेटाच्या स्टेटवर सहभागींनी सिंक केलेले असणे अपेक्षित आहे, त्याबद्दल पीअर्स परस्परविरोधी दावे करत असल्यास, विवाद निराकरणासाठी एका प्रोटोकॉलची (बहुतेकदा क्लिष्ट) आवश्यकता असते. | +| अयशस्वी होण्याचा एकच बिंदू: दुर्भावनापूर्ण घटक केंद्रीय प्राधिकरणाला लक्ष्य करून नेटवर्क बंद करू शकतात. | अयशस्वी होण्याचा एकही बिंदू नाही: सहभागींच्या मोठ्या भागावर हल्ला झाला/काढून टाकले तरीही नेटवर्क कार्य करू शकते. | +| नेटवर्क सहभागींमध्ये समन्वय खूप सोपा आहे आणि एका केंद्रीय प्राधिकरणाद्वारे हाताळला जातो. केंद्रीय प्राधिकरण नेटवर्क सहभागींना अगदी कमी घर्षणासह अपग्रेड, प्रोटोकॉल अपडेट्स इत्यादी स्वीकारण्यास भाग पाडू शकते. | समन्वय अनेकदा कठीण असतो, कारण नेटवर्क-स्तरीय निर्णय, प्रोटोकॉल अपग्रेड इत्यादींमध्ये कोणत्याही एका एजंटचा अंतिम निर्णय नसतो. सर्वात वाईट परिस्थितीत, जेव्हा प्रोटोकॉल बदलांबद्दल मतभेद असतात तेव्हा नेटवर्कमध्ये फूट पडण्याची शक्यता असते. | +| केंद्रीय प्राधिकरण डेटा सेन्सॉर करू शकते, संभाव्यतः नेटवर्कच्या काही भागांना उर्वरित नेटवर्कशी संवाद साधण्यापासून तोडू शकते. | सेन्सॉरशिप खूप कठीण आहे, कारण माहितीला नेटवर्कमध्ये प्रसारित होण्याचे अनेक मार्ग आहेत. | +| नेटवर्कमधील सहभाग केंद्रीय प्राधिकरणाद्वारे नियंत्रित केला जातो. | कोणीही नेटवर्कमध्ये सहभागी होऊ शकतो; कोणतेही “गेटकीपर” नाहीत. आदर्शपणे, सहभागाचा खर्च खूप कमी असतो. | + +लक्षात घ्या की हे सामान्य नमुने आहेत जे प्रत्येक नेटवर्कमध्ये खरे ठरतीलच असे नाही. शिवाय, प्रत्यक्षात एखादे नेटवर्क किती प्रमाणात केंद्रीकृत/विकेंद्रित आहे हे एका स्पेक्ट्रमवर अवलंबून असते; कोणतेही नेटवर्क पूर्णपणे केंद्रीकृत किंवा पूर्णपणे विकेंद्रित नसते. + +## पुढील वाचन {#further-reading} + +- [वेब3 काय आहे?](/web3/) - _ethereum.org_ +- [वेब 3.0 ॲप्लिकेशनची रचना](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application) - _प्रीती कासिरेड्डी_ +- [विकेंद्रीकरणाचा अर्थ](https://medium.com/@VitalikButerin/the-meaning-of-decentralization-a0c92b76a274) _6 फेब्रुवारी, 2017 - विटालिक बुटेरिन_ +- [विकेंद्रीकरण का महत्त्वाचे आहे](https://onezero.medium.com/why-decentralization-matters-5e3f79f7638e) _18 फेब्रुवारी, 2018 - ख्रिस डिक्सन_ +- [वेब 3.0 काय आहे आणि ते का महत्त्वाचे आहे](https://medium.com/fabric-ventures/what-is-web-3-0-why-it-matters-934eb07f3d2b) _31 डिसेंबर, 2019 - मॅक्स मर्श आणि रिचर्ड मुइरहेड_ +- [आम्हाला वेब 3.0 ची गरज का आहे](https://gavofyork.medium.com/why-we-need-web-3-0-5da4f2bf95ab) _12 सप्टेंबर, 2018 - गॅविन वुड_ diff --git a/public/content/translations/mr/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md b/public/content/translations/mr/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md new file mode 100644 index 00000000000..7faec1170f9 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/a-developers-guide-to-ethereum-part-one/index.md @@ -0,0 +1,300 @@ +--- +title: "एका Python डेव्हलपरसाठी Ethereum ची ओळख, भाग 1" +description: "Ethereum डेव्हलपमेंटची ओळख, विशेषतः Python प्रोग्रामिंग भाषेचे ज्ञान असलेल्यांसाठी उपयुक्त" +author: Marc Garreau +lang: mr +tags: [ "python", "web3.py" ] +skill: beginner +published: 2020-09-08 +source: Snake charmers +sourceUrl: https://snakecharmers.ethereum.org/a-developers-guide-to-ethereum-pt-1/ +--- + +तर, तुम्ही या Ethereum नावाच्या गोष्टीबद्दल ऐकले आहे आणि या गहन जगात प्रवेश करण्यास तयार आहात का? ही पोस्ट ब्लॉकचेनच्या काही मूलभूत गोष्टींवर पटकन प्रकाश टाकेल, त्यानंतर तुम्हाला एका सिम्युलेटेड Ethereum नोडशी संवाद साधायला लावेल – ब्लॉक डेटा वाचणे, खात्यातील शिल्लक तपासणे आणि व्यवहार पाठवणे. या प्रक्रियेत, ॲप्स बनवण्याच्या पारंपरिक पद्धती आणि हे नवीन विकेंद्रित प्रतिमान (paradigm) यांमधील फरक आम्ही अधोरेखित करू. + +## (अंदाजित) पूर्वतयारी {#soft-prerequisites} + +ही पोस्ट विविध प्रकारच्या डेव्हलपर्ससाठी सोपी आणि सहज समजण्याजोगी असावी अशी आमची इच्छा आहे. [Python टूल्स](/developers/docs/programming-languages/python/) यात सामील असतील, पण ती केवळ कल्पना पोहोचवण्याचे एक माध्यम आहेत - तुम्ही Python डेव्हलपर नसाल तरी काही हरकत नाही. तथापि, तुम्हाला आधीपासून काय माहित आहे याबद्दल मी काही गृहीतके धरणार आहे, जेणेकरून आपण पटकन Ethereum-विशिष्ट भागांकडे जाऊ शकू. + +गृहीतके: + +- तुम्ही टर्मिनलमध्ये काम करू शकता, +- तुम्ही Python कोडच्या काही ओळी लिहिल्या आहेत, +- Python आवृत्ती 3.6 किंवा त्याहून अधिक तुमच्या मशीनवर इंस्टॉल केलेले आहे ([व्हर्च्युअल एन्व्हायर्नमेंट](https://realpython.com/effective-python-environment/#virtual-environments) वापरण्यास जोरदार प्रोत्साहन दिले जाते), आणि +- तुम्ही `pip`, Python चे पॅकेज इंस्टॉलर वापरले आहे. + पुन्हा एकदा, यापैकी काहीही असत्य असल्यास, किंवा तुम्ही या लेखातील कोड पुन्हा वापरण्याची योजना करत नसल्यास, तरीही तुम्ही हे सहजपणे समजून घेऊ शकता. + +## ब्लॉकचेन्स, थोडक्यात {#blockchains-briefly} + +Ethereum चे वर्णन करण्याचे अनेक मार्ग आहेत, पण त्याच्या केंद्रस्थानी एक ब्लॉकचेन आहे. ब्लॉकचेन हे ब्लॉक्सच्या मालिकेपासून बनलेले असतात, चला तर मग तिथूनच सुरुवात करूया. सोप्या भाषेत सांगायचे झाल्यास, Ethereum ब्लॉकचेनवरील प्रत्येक ब्लॉक म्हणजे काही मेटाडेटा आणि व्यवहारांची सूची. JSON फॉरमॅटमध्ये, ते असे काहीतरी दिसते: + +```json +{ + "number": 1234567, + "hash": "0xabc123...", + "parentHash": "0xdef456...", + ..., + "transactions": [...] +} +``` + +प्रत्येक [ब्लॉक](/developers/docs/blocks/) मध्ये त्याच्या आधीच्या ब्लॉकचा संदर्भ असतो; `parentHash` म्हणजे फक्त मागील ब्लॉकचा हॅश. + +टीप: Ethereum ठराविक आकाराची मूल्ये (“हॅश”) तयार करण्यासाठी हॅश फंक्शन्सचा नियमित वापर करते. हॅश Ethereum मध्ये महत्त्वाची भूमिका बजावतात, पण सध्यासाठी तुम्ही त्यांना युनिक आयडी म्हणून समजू शकता. + +![एका ब्लॉकचेनचे चित्र, ज्यात प्रत्येक ब्लॉकच्या आतील डेटा दर्शविला आहे](./blockchain-diagram.png) + +_एक ब्लॉकचेन मूलतः एक लिंक्ड लिस्ट आहे; प्रत्येक ब्लॉकला मागील ब्लॉकचा संदर्भ असतो._ + +ही डेटा स्ट्रक्चर काही नवीन नाही, परंतु नेटवर्कचे संचालन करणारे नियम (म्हणजेच, पीअर-टू-पीअर प्रोटोकॉल) नवीन आहेत. येथे कोणतेही केंद्रीय प्राधिकरण नाही; नेटवर्क टिकवून ठेवण्यासाठी पीअर्सच्या नेटवर्कला एकत्र काम करावे लागते, आणि पुढील ब्लॉकमध्ये कोणते व्यवहार समाविष्ट करायचे हे ठरवण्यासाठी स्पर्धा करावी लागते. म्हणून, जेव्हा तुम्हाला तुमच्या मित्राला काही पैसे पाठवायचे असतील, तेव्हा तुम्हाला तो व्यवहार नेटवर्कवर प्रसारित करावा लागेल, आणि नंतर तो आगामी ब्लॉकमध्ये समाविष्ट होण्याची वाट पाहावी लागेल. + +एका वापरकर्त्याकडून दुसऱ्या वापरकर्त्याकडे पैसे खरोखरच पाठवले गेले आहेत हे पडताळून पाहण्याचा ब्लॉकचेनसाठी एकमेव मार्ग म्हणजे त्या ब्लॉकचेनचे मूळ चलन (म्हणजेच, त्या ब्लॉकचेनद्वारे तयार केलेले आणि शासित) वापरणे. Ethereum मध्ये, या चलनास ईथर म्हणतात, आणि Ethereum ब्लॉकचेनमध्ये खात्यातील शिलकीची एकमेव अधिकृत नोंद असते. + +## एक नवीन प्रतिमान (paradigm) {#a-new-paradigm} + +या नवीन विकेंद्रित टेक स्टॅकने नवीन डेव्हलपर टूल्स तयार केले आहेत. अशी टूल्स अनेक प्रोग्रामिंग भाषांमध्ये अस्तित्वात आहेत, परंतु आपण Python च्या दृष्टिकोनातून पाहणार आहोत. पुन्हा सांगतो: Python तुमची पसंतीची भाषा नसली तरीही, हे समजून घेण्यासाठी जास्त अडचण येऊ नये. + +Ethereum शी संवाद साधू इच्छिणारे Python डेव्हलपर बहुधा [Web3.py](https://web3py.readthedocs.io/) चा वापर करतात. Web3.py ही एक लायब्ररी आहे जी तुम्हाला Ethereum नोडशी जोडण्याची आणि त्यातून डेटा पाठवण्याची आणि प्राप्त करण्याची पद्धत खूप सोपी करते. + +टीप: “Ethereum नोड” आणि “Ethereum क्लायंट” हे शब्द एकमेकांसाठी वापरले जातात. दोन्ही बाबतीत, याचा अर्थ Ethereum नेटवर्कमधील एक सहभागी चालवत असलेले सॉफ्टवेअर असा होतो. हे सॉफ्टवेअर ब्लॉक डेटा वाचू शकते, चेनमध्ये नवीन ब्लॉक जोडल्यावर अपडेट्स मिळवू शकते, नवीन व्यवहार प्रसारित करू शकते आणि बरेच काही. तांत्रिकदृष्ट्या, क्लायंट हे सॉफ्टवेअर आहे, तर नोड हे सॉफ्टवेअर चालवणारा संगणक आहे. + +[Ethereum क्लायंट](/developers/docs/nodes-and-clients/) [IPC](https://wikipedia.org/wiki/Inter-process_communication), HTTP, किंवा Websockets द्वारे पोहोचण्यायोग्य होण्यासाठी कॉन्फिगर केले जाऊ शकतात, म्हणून Web3.py ला हे कॉन्फिगरेशन प्रतिबिंबित करावे लागेल. Web3.py या कनेक्शन पर्यायांना **प्रोव्हायडर्स** म्हणून संबोधते. Web3.py इंस्टन्सला तुमच्या नोडशी जोडण्यासाठी तुम्हाला तीन प्रोव्हायडर्सपैकी एक निवडावा लागेल. + +![तुमचा ॲप्लिकेशन Ethereum नोडशी जोडण्यासाठी web3.py IPC चा कसा वापर करते हे दर्शवणारे एक चित्र](./web3py-and-nodes.png) + +_Ethereum नोड आणि Web3.py ला एकाच प्रोटोकॉलद्वारे संवाद साधण्यासाठी कॉन्फिगर करा, उदा., या चित्रात IPC._ + +एकदा Web3.py योग्यरित्या कॉन्फिगर झाल्यावर, तुम्ही ब्लॉकचेनशी संवाद साधण्यास सुरुवात करू शकता. पुढे काय येणार आहे याची झलक म्हणून येथे Web3.py वापराची काही उदाहरणे आहेत: + +```python +# ब्लॉक डेटा वाचा: +w3.eth.get_block('latest') + +# एक व्यवहार पाठवा: +w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...}) +``` + +## इन्स्टॉलेशन {#installation} + +या वॉकथ्रूमध्ये, आपण फक्त Python इंटरप्रिटरमध्ये काम करणार आहोत. आपण कोणत्याही डिरेक्टरीज, फाइल्स, क्लासेस किंवा फंक्शन्स तयार करणार नाही. + +टीप: खालील उदाहरणांमध्ये, `$` ने सुरू होणारे कमांड्स टर्मिनलमध्ये चालवण्यासाठी आहेत. ( `$ ` टाइप करू नका, ते फक्त ओळीची सुरुवात दर्शवते.) + +सर्वप्रथम, एक्सप्लोर करण्यासाठी वापरकर्ता-स्नेही वातावरणासाठी [IPython](https://ipython.org/) इंस्टॉल करा. IPython टॅब कंप्लिशनसारख्या इतर वैशिष्ट्यांसह, Web3.py मध्ये काय शक्य आहे हे पाहणे खूप सोपे करते. + +```bash +pip install ipython +``` + +Web3.py `web3` या नावाने प्रकाशित केले आहे. ते असे इंस्टॉल करा: + +```bash +pip install web3 +``` + +आणखी एक गोष्ट - आपण नंतर एक ब्लॉकचेन सिम्युलेट करणार आहोत, ज्यासाठी आणखी काही डिपेन्डन्सीज आवश्यक आहेत. तुम्ही त्या याप्रमाणे इंस्टॉल करू शकता: + +```bash +pip install 'web3[tester]' +``` + +तुम्ही आता पूर्णपणे तयार आहात! + +टीप: `web3[tester]` पॅकेज Python 3.10.xx पर्यंत काम करते. + +## एक सँडबॉक्स सुरू करा {#spin-up-a-sandbox} + +तुमच्या टर्मिनलमध्ये `ipython` रन करून एक नवीन Python एन्व्हायर्नमेंट उघडा. हे `python` रन करण्यासारखेच आहे, परंतु यात अधिक अतिरिक्त वैशिष्ट्ये आहेत. + +```bash +ipython +``` + +हे तुम्ही चालवत असलेल्या Python आणि IPython च्या आवृत्त्यांविषयी काही माहिती प्रिंट करेल, त्यानंतर तुम्हाला इनपुटची वाट पाहणारा एक प्रॉम्प्ट दिसेल: + +```python +In [1]: +``` + +तुम्ही आता एक इंटरॲक्टिव्ह Python शेल पाहत आहात. मूलतः, हे खेळण्यासाठी एक सँडबॉक्स आहे. जर तुम्ही इथपर्यंत पोहोचला असाल, तर आता Web3.py इम्पोर्ट करण्याची वेळ आली आहे: + +```python +In [1]: from web3 import Web3 +``` + +## Web3 मॉड्यूलची ओळख {#introducing-the-web3-module} + +Ethereum चे प्रवेशद्वार असण्याव्यतिरिक्त, [Web3](https://web3py.readthedocs.io/en/stable/overview.html#base-api) मॉड्यूल काही सोयीस्कर फंक्शन्स देखील प्रदान करते. चला काही एक्सप्लोर करूया. + +एका Ethereum ॲप्लिकेशनमध्ये, तुम्हाला सामान्यतः चलनाची परिमाणे (denominations) रूपांतरित करण्याची आवश्यकता असेल. Web3 मॉड्यूल यासाठीच काही हेल्पर मेथड्स पुरवते: [from_wei](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.from_wei) आणि [to_wei](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.to_wei). + + +टीप: संगणक दशांश गणित हाताळण्यात कुप्रसिद्ध आहेत. यावर मात करण्यासाठी, डेव्हलपर्स अनेकदा डॉलरची रक्कम सेंटमध्ये साठवतात. उदाहरणार्थ, $5.99 किंमत असलेली वस्तू डेटाबेसमध्ये 599 म्हणून साठवली जाऊ शकते. + +ईथरमधील व्यवहार हाताळतानाही असाच पॅटर्न वापरला जातो. तथापि, दोन दशांश स्थळांऐवजी, ईथरला 18 आहेत! ईथरच्या सर्वात लहान परिमाणाला wei म्हणतात, म्हणून व्यवहार पाठवताना तेच मूल्य निर्दिष्ट केले जाते. + +1 ईथर = 1000000000000000000 wei + +1 wei = 0.000000000000000001 ईथर + + + +काही मूल्ये wei मध्ये आणि wei मधून रूपांतरित करण्याचा प्रयत्न करा. लक्षात घ्या की ईथर आणि wei मध्ये [अनेक परिमाणांसाठी नावे आहेत](https://web3py.readthedocs.io/en/stable/troubleshooting.html#how-do-i-convert-currency-denominations). त्यापैकी एक अधिक प्रसिद्ध नाव म्हणजे **gwei**, कारण व्यवहार शुल्क अनेकदा यात दर्शवले जाते. + +```python +In [2]: Web3.to_wei(1, 'ether') +Out[2]: 1000000000000000000 + +In [3]: Web3.from_wei(500000000, 'gwei') +Out[3]: Decimal('0.5') +``` + +Web3 मॉड्यूलवरील इतर युटिलिटी मेथड्समध्ये डेटा फॉरमॅट कन्व्हर्टर्स (उदा., [`toHex`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.toHex)), ॲड्रेस हेल्पर्स (उदा., [`isAddress`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.isAddress)), आणि हॅश फंक्शन्स (उदा., [`keccak`](https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.keccak)) यांचा समावेश आहे. यापैकी बऱ्याच गोष्टी या मालिकेत नंतर समाविष्ट केल्या जातील. सर्व उपलब्ध मेथड्स आणि प्रॉपर्टीज पाहण्यासाठी, `Web3` टाइप करून IPython च्या ऑटो-कम्प्लीटचा वापर करा. आणि पीरियडनंतर टॅब की दोनदा दाबा. + +## चेनशी बोला {#talk-to-the-chain} + +सोयीस्कर मेथड्स छान आहेत, पण चला आता ब्लॉकचेनकडे वळूया. पुढील पायरी म्हणजे Ethereum नोडशी संवाद साधण्यासाठी Web3.py कॉन्फिगर करणे. येथे आपल्याकडे IPC, HTTP किंवा Websocket प्रोव्हायडर्स वापरण्याचा पर्याय आहे. + +आपण या मार्गावर जाणार नाही, परंतु HTTP प्रोव्हायडर वापरून संपूर्ण वर्कफ्लोचे उदाहरण असे काहीतरी दिसेल: + +- एक Ethereum नोड डाउनलोड करा, उदा., [Geth](https://geth.ethereum.org/). +- एका टर्मिनल विंडोमध्ये Geth सुरू करा आणि नेटवर्क सिंक होण्याची वाट पाहा. डीफॉल्ट HTTP पोर्ट `8545` आहे, पण ते कॉन्फिगर करता येते. +- `localhost:8545` वर HTTP द्वारे नोडशी कनेक्ट करण्यासाठी Web3.py ला सांगा. + `w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))` +- नोडशी संवाद साधण्यासाठी `w3` इंस्टन्स वापरा. + +हे करण्याची ही एक “वास्तविक” पद्धत असली तरी, सिंक करण्याच्या प्रक्रियेला तास लागतात आणि जर तुम्हाला फक्त एक डेव्हलपमेंट एन्व्हायर्नमेंट हवे असेल तर ते अनावश्यक आहे. Web3.py या उद्देशासाठी चौथा प्रोव्हायडर उपलब्ध करतो, तो म्हणजे **EthereumTesterProvider**. हा टेस्टर प्रोव्हायडर एका सिम्युलेटेड Ethereum नोडला जोडतो, ज्यामध्ये शिथिल परवानग्या आणि खेळण्यासाठी बनावट चलन असते. + +![EthereumTesterProvider तुमच्या web3.py ॲप्लिकेशनला सिम्युलेटेड Ethereum नोडशी जोडत असल्याचे दर्शवणारे एक चित्र](./ethereumtesterprovider.png) + +_EthereumTesterProvider एका सिम्युलेटेड नोडशी कनेक्ट होतो आणि जलद डेव्हलपमेंट एन्व्हायर्नमेंटसाठी उपयुक्त आहे._ + +त्या सिम्युलेटेड नोडला [eth-tester](https://github.com/ethereum/eth-tester) म्हणतात आणि आपण तो `pip install web3[tester]` कमांडचा भाग म्हणून इंस्टॉल केला. या टेस्टर प्रोव्हायडरचा वापर करण्यासाठी Web3.py कॉन्फिगर करणे इतके सोपे आहे: + +```python +In [4]: w3 = Web3(Web3.EthereumTesterProvider()) +``` + +आता तुम्ही चेन सर्फ करण्यास तयार आहात! असं सहसा कोणी म्हणत नाही. मी हे आताच तयार केले. चला एक छोटीशी सफर करूया. + +## छोटीशी सफर {#the-quick-tour} + +सर्वात आधी, एक सॅनिटी चेक: + +```python +In [5]: w3.is_connected() +Out[5]: True +``` + +आपण टेस्टर प्रोव्हायडर वापरत असल्यामुळे, ही चाचणी खूप महत्त्वाची नाही, पण जर ती अयशस्वी झाली, तर शक्यता आहे की `w3` व्हेरिएबल इन्स्टँटिएट करताना तुम्ही काहीतरी चुकीचे टाइप केले असेल. तुम्ही आतील कंस समाविष्ट केले आहेत याची खात्री करा, म्हणजे `Web3.EthereumTesterProvider()`. + +## सफरीचा थांबा #1: [खाती](/developers/docs/accounts/) {#tour-stop-1-accounts} + +सोयीसाठी, टेस्टर प्रोव्हायडरने काही खाती तयार केली आहेत आणि त्यात आधीच चाचणीसाठी ईथर भरलेले आहेत. + +प्रथम, त्या खात्यांची यादी पाहूया: + +```python +In [6]: w3.eth.accounts +Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf', + '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF', + '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...] +``` + +तुम्ही हा कमांड चालवल्यास, तुम्हाला `0x` ने सुरू होणाऱ्या दहा स्ट्रिंगची यादी दिसेल. प्रत्येक एक **पब्लिक ॲड्रेस** आहे आणि काही बाबतीत, तो चेकिंग खात्यावरील खाते क्रमांकासारखा आहे. तुम्हाला ईथर पाठवू इच्छिणाऱ्या व्यक्तीला तुम्ही हा ॲड्रेस द्याल. + +सांगितल्याप्रमाणे, टेस्टर प्रोव्हायडरने या प्रत्येक खात्यात काही चाचणी ईथर आधीच भरलेले आहेत. पहिल्या खात्यात किती शिल्लक आहे ते पाहूया: + +```python +In [7]: w3.eth.get_balance(w3.eth.accounts[0]) +Out[7]: 1000000000000000000000000 +``` + +किती तरी शून्य आहेत! खोट्या बँकेत जाऊन आनंद साजरा करण्यापूर्वी, चलनांच्या परिमाणांबद्दलचा पूर्वीचा धडा आठवा. ईथर मूल्ये सर्वात लहान परिमाण, wei मध्ये दर्शविली जातात. ते ईथरमध्ये रूपांतरित करा: + +```python +In [8]: w3.from_wei(1000000000000000000000000, 'ether') +Out[8]: Decimal('1000000') +``` + +दहा लाख चाचणी ईथर - तरीही वाईट नाही. + +## सफरीचा थांबा #2: ब्लॉक डेटा {#tour-stop-2-block-data} + +या सिम्युलेटेड ब्लॉकचेनच्या स्थितीवर एक नजर टाकूया: + +```python +In [9]: w3.eth.get_block('latest') +Out[9]: AttributeDict({ + 'number': 0, + 'hash': HexBytes('0x9469878...'), + 'parentHash': HexBytes('0x0000000...'), + ... + 'transactions': [] +}) +``` + +एका ब्लॉकबद्दल बरीच माहिती परत मिळते, पण येथे फक्त काही गोष्टी नमूद करायच्या आहेत: + +- ब्लॉक क्रमांक शून्य आहे - तुम्ही टेस्टर प्रोव्हायडर कितीही वेळापूर्वी कॉन्फिगर केले असले तरीही. वास्तविक Ethereum नेटवर्कच्या विपरीत, जे दर 12 सेकंदांनी एक नवीन ब्लॉक जोडते, हे सिम्युलेशन तुम्ही त्याला काही काम देईपर्यंत थांबेल. +- `transactions` ही एक रिकामी यादी आहे, त्याच कारणासाठी: आपण अद्याप काहीही केलेले नाही. हा पहिला ब्लॉक एक **रिकामा ब्लॉक** आहे, फक्त चेन सुरू करण्यासाठी. +- लक्षात घ्या की `parentHash` फक्त रिकाम्या बाइट्सचा एक समूह आहे. हे सूचित करते की हा चेनमधील पहिला ब्लॉक आहे, ज्याला **जेनेसिस ब्लॉक** असेही म्हणतात. + +## सफरीचा थांबा #3: [व्यवहार](/developers/docs/transactions/) {#tour-stop-3-transactions} + +आपण ब्लॉक शून्यवर अडकलो आहोत जोपर्यंत प्रलंबित व्यवहार होत नाही, चला तर मग एक व्यवहार करूया. एका खात्यातून दुसऱ्या खात्यात काही चाचणी ईथर पाठवा: + +```python +In [10]: tx_hash = w3.eth.send_transaction({ + 'from': w3.eth.accounts[0], + 'to': w3.eth.accounts[1], + 'value': w3.to_wei(3, 'ether'), + 'gas': 21000 +}) +``` + +हा सहसा तो क्षण असतो जिथे तुम्ही तुमचा व्यवहार नवीन ब्लॉकमध्ये समाविष्ट होण्यासाठी काही सेकंद वाट पाहता. संपूर्ण प्रक्रिया काहीशी अशी आहे: + +1. एक व्यवहार सबमिट करा आणि व्यवहार हॅश जपून ठेवा. व्यवहार असलेला ब्लॉक तयार आणि प्रसारित होईपर्यंत, व्यवहार “प्रलंबित” असतो. + `tx_hash = w3.eth.send_transaction({ … })` +2. व्यवहार ब्लॉकमध्ये समाविष्ट होण्याची वाट पाहा: + `w3.eth.wait_for_transaction_receipt(tx_hash)` +3. ॲप्लिकेशन लॉजिक सुरू ठेवा. यशस्वी व्यवहार पाहण्यासाठी: + `w3.eth.get_transaction(tx_hash)` + +आमचे सिम्युलेटेड एन्व्हायर्नमेंट व्यवहार तात्काळ एका नवीन ब्लॉकमध्ये जोडेल, त्यामुळे आपण लगेच व्यवहार पाहू शकतो: + +```python +In [11]: w3.eth.get_transaction(tx_hash) +Out[11]: AttributeDict({ + 'hash': HexBytes('0x15e9fb95dc39...'), + 'blockNumber': 1, + 'transactionIndex': 0, + 'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf', + 'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF', + 'value': 3000000000000000000, + ... +}) +``` + +तुम्हाला येथे काही ओळखीचे तपशील दिसतील: `from`, `to` आणि `value` फील्ड्स आपल्या `send_transaction` कॉलच्या इनपुटशी जुळले पाहिजेत. दुसरी दिलासादायक गोष्ट म्हणजे हा व्यवहार ब्लॉक क्रमांक 1 मध्ये पहिला व्यवहार (`'transactionIndex': 0`) म्हणून समाविष्ट केला गेला. + +या व्यवहाराची यशस्वीता आपण दोन्ही संबंधित खात्यांमधील शिल्लक तपासून सहज पडताळू शकतो. तीन ईथर एका खात्यातून दुसऱ्या खात्यात हस्तांतरित झाले पाहिजेत. + +```python +In [12]: w3.eth.get_balance(w3.eth.accounts[0]) +Out[12]: 999996999979000000000000 + +In [13]: w3.eth.get_balance(w3.eth.accounts[1]) +Out[13]: 1000003000000000000000000 +``` + +दुसरे बरोबर दिसत आहे! शिल्लक 1,000,000 वरून 1,000,003 ईथर झाली. पण पहिल्या खात्याचे काय झाले? असे दिसते की त्याने तीन ईथरपेक्षा थोडे जास्त गमावले आहेत. अरेरे, जीवनात काहीही विनामूल्य नाही, आणि Ethereum सार्वजनिक नेटवर्क वापरण्यासाठी तुम्हाला तुमच्या पीअर्सना त्यांच्या सहाय्यक भूमिकेसाठी भरपाई देणे आवश्यक आहे. व्यवहार सबमिट करणाऱ्या खात्यातून एक छोटे व्यवहार शुल्क कापले गेले - हे शुल्क म्हणजे गॅसच्या जळलेल्या प्रमाणाला (ETH हस्तांतरणासाठी 21000 गॅस युनिट्स) नेटवर्कच्या क्रियाकलापानुसार बदलणाऱ्या बेस फीने गुणले जाते, अधिक व्यवहाराला ब्लॉकमध्ये समाविष्ट करणाऱ्या व्हॅलिडेटरला जाणारी टीप. + +[गॅस](/developers/docs/gas/#post-london) बद्दल अधिक + +टीप: सार्वजनिक नेटवर्कवर, व्यवहार शुल्क नेटवर्कच्या मागणीनुसार आणि तुम्हाला व्यवहार किती लवकर प्रक्रिया करायचा आहे यावर अवलंबून बदलते. तुम्हाला शुल्क कसे मोजले जाते याच्या तपशिलात स्वारस्य असल्यास, माझी ब्लॉकमध्ये व्यवहार कसे समाविष्ट केले जातात यावरील पूर्वीची पोस्ट पाहा. + +## आणि श्वास घ्या {#and-breathe} + +आपण हे बऱ्याच वेळेपासून करत आहोत, त्यामुळे ब्रेक घेण्यासाठी हे एक चांगले ठिकाण आहे. हे गहन जग पुढेही चालू आहे, आणि आपण या मालिकेच्या दुसऱ्या भागात एक्सप्लोर करणे सुरू ठेवू. येणाऱ्या काही संकल्पना: वास्तविक नोडशी कनेक्ट करणे, स्मार्ट कॉन्ट्रॅक्ट्स आणि टोकन्स. तुमचे काही पुढील प्रश्न आहेत का? मला कळवा! तुमचा अभिप्राय आपण येथून पुढे कुठे जायचे हे ठरवेल. [Twitter](https://twitter.com/wolovim) द्वारे विनंत्यांचे स्वागत आहे. diff --git a/public/content/translations/mr/developers/tutorials/all-you-can-cache/index.md b/public/content/translations/mr/developers/tutorials/all-you-can-cache/index.md new file mode 100644 index 00000000000..74ebf5c1c7b --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/all-you-can-cache/index.md @@ -0,0 +1,867 @@ +--- +title: "तुम्ही कॅशे करू शकता ते सर्व" +description: "स्वस्त रोलअप व्यवहारांसाठी कॅशिंग करार कसा तयार करायचा आणि वापरायचा ते शिका" +author: Ori Pomerantz +tags: [ "स्तर 2", "कॅशिंग", "स्टोरेज" ] +skill: intermediate +published: 2022-09-15 +lang: mr +--- + +रोलअप वापरताना, व्यवहारातील एका बाइटची किंमत स्टोरेज स्लॉटच्या किंमतीपेक्षा खूप जास्त असते. म्हणून, शक्य तितकी माहिती ऑनचेन कॅशे करणे अर्थपूर्ण आहे. + +या लेखात, तुम्ही कॅशिंग करार कसा तयार करायचा आणि वापरायचा हे शिकाल. ज्या पॅरामीटर व्हॅल्यूचा अनेक वेळा वापर होण्याची शक्यता आहे, ती कॅशे केली जाईल आणि (पहिल्या वापरानंतर) कमी बाइट्ससह वापरासाठी उपलब्ध होईल. तसेच, हा कॅशे वापरणारा ऑफचेन कोड कसा लिहायचा हेही शिकाल. + +तुम्हाला हा लेख वगळून थेट सोर्स कोड बघायचा असेल, तर [तो इथे आहे](https://github.com/qbzzt/20220915-all-you-can-cache). डेव्हलपमेंट स्टॅक [Foundry](https://getfoundry.sh/introduction/installation/) आहे. + +## एकूण डिझाइन {#overall-design} + +सोपेपणासाठी, आपण असे गृहीत धरू की सर्व व्यवहार पॅरामीटर्स `uint256` आहेत, ज्यांची लांबी 32 बाइट्स आहे. जेव्हा आपल्याला व्यवहार प्राप्त होतो, तेव्हा आपण प्रत्येक पॅरामीटरचे अशा प्रकारे विश्लेषण करू: + +1. जर पहिला बाइट `0xFF` असेल, तर पुढील 32 बाइट्स पॅरामीटर व्हॅल्यू म्हणून घ्या आणि कॅशेमध्ये लिहा. + +2. जर पहिला बाइट `0xFE` असेल, तर पुढील 32 बाइट्स पॅरामीटर व्हॅल्यू म्हणून घ्या, परंतु कॅशेमध्ये लिहू _नका_. + +3. इतर कोणत्याही व्हॅल्यूसाठी, शीर्ष चार बिट्स अतिरिक्त बाइट्सची संख्या म्हणून घ्या आणि खालचे चार बिट्स कॅशे कीचे सर्वात महत्त्वपूर्ण बिट्स म्हणून घ्या. येथे काही उदाहरणे आहेत: + + | कॉलडेटामधील बाइट्स | कॅशे की | + | :----------------- | -------: | + | 0x0F | 0x0F | + | 0x10,0x10 | 0x10 | + | 0x12,0xAC | 0x02AC | + | 0x2D,0xEA, 0xD6 | 0x0DEAD6 | + +## कॅशे मॅनिप्युलेशन {#cache-manipulation} + +कॅशे [`Cache.sol`](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/Cache.sol) मध्ये इम्प्लिमेंट केले आहे. चला ओळीनुसार पाहूया. + +```solidity +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + + +contract Cache { + + bytes1 public constant INTO_CACHE = 0xFF; + bytes1 public constant DONT_CACHE = 0xFE; +``` + +हे कॉन्स्टंट्स विशेष प्रकरणांचे अर्थ लावण्यासाठी वापरले जातात, जिथे आपण सर्व माहिती प्रदान करतो आणि ती कॅशेमध्ये लिहावी की नाही हे ठरवतो. कॅशेमध्ये लिहिण्यासाठी पूर्वी न वापरलेल्या स्टोरेज स्लॉटमध्ये प्रत्येकी 22100 गॅसच्या दराने दोन [`SSTORE`](https://www.evm.codes/#55) ऑपरेशन्सची आवश्यकता असते, म्हणून आपण ते ऐच्छिक ठेवतो. + +```solidity + + mapping(uint => uint) public val2key; +``` + +व्हॅल्यूज आणि त्यांच्या कीजमधील [मॅपिंग](https://www.geeksforgeeks.org/solidity/solidity-mappings/). तुम्ही व्यवहार पाठवण्यापूर्वी व्हॅल्यूज एन्कोड करण्यासाठी ही माहिती आवश्यक आहे. + +```solidity + // लोकेशन n मध्ये की n+1 साठी व्हॅल्यू आहे, कारण आपल्याला + // शून्य "कॅशेमध्ये नाही" म्हणून जतन करणे आवश्यक आहे. + uint[] public key2val; +``` + +आपण कीज ते व्हॅल्यूजच्या मॅपिंगसाठी ॲरे वापरू शकतो कारण आपण कीज नियुक्त करतो आणि सोपेपणासाठी आपण ते क्रमाने करतो. + +```solidity + function cacheRead(uint _key) public view returns (uint) { + require(_key <= key2val.length, "Reading uninitialize cache entry"); + return key2val[_key-1]; + } // cacheRead +``` + +कॅशेमधून व्हॅल्यू वाचा. + +```solidity + // एखादी व्हॅल्यू कॅशेमध्ये आधीच नसल्यास ती लिहा + // चाचणी काम करण्यासाठी फक्त पब्लिक + function cacheWrite(uint _value) public returns (uint) { + // जर व्हॅल्यू आधीच कॅशेमध्ये असेल, तर सध्याची की परत करा + if (val2key[_value] != 0) { + return val2key[_value]; + } +``` + +एकच व्हॅल्यू एकापेक्षा जास्त वेळा कॅशेमध्ये टाकण्यात काहीच अर्थ नाही. जर व्हॅल्यू आधीच तिथे असेल, तर फक्त अस्तित्वात असलेली की परत करा. + +```solidity + // 0xFE हा एक विशेष केस असल्यामुळे, कॅशेमध्ये ठेवता येणारी सर्वात मोठी की + // 0x0D आणि त्यानंतर 15 0xFF's आहे. जर कॅशेची लांबी आधीच इतकी + // मोठी असेल, तर फेल करा. + // 1 2 3 4 5 6 7 8 9 A B C D E F + require(key2val.length+1 < 0x0DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, + "cache overflow"); +``` + +मला नाही वाटत की आपल्याला इतका मोठा कॅशे कधी मिळेल (अंदाजे 1.8\*1037 नोंदी, ज्यासाठी सुमारे 1027 टीबी स्टोरेज लागेल). तथापि, ["640kB नेहमीच पुरेसे असेल"](https://quoteinvestigator.com/2011/09/08/640k-enough/) हे आठवण्याइतका मी जुना आहे. ही चाचणी खूपच स्वस्त आहे. + +```solidity + // पुढील की वापरून व्हॅल्यू लिहा + val2key[_value] = key2val.length+1; +``` + +रिव्हर्स लुकअप (व्हॅल्यूपासून कीपर्यंत) जोडा. + +```solidity + key2val.push(_value); +``` + +फॉरवर्ड लुकअप (कीपासून व्हॅल्यूपर्यंत) जोडा. कारण आपण व्हॅल्यूज क्रमाने नियुक्त करतो, आपण ते फक्त शेवटच्या ॲरे व्हॅल्यूनंतर जोडू शकतो. + +```solidity + return key2val.length; + } // cacheWrite +``` + +`key2val` ची नवीन लांबी परत करा, जो तो सेल आहे जिथे नवीन व्हॅल्यू संग्रहित केली आहे. + +```solidity + function _calldataVal(uint startByte, uint length) + private pure returns (uint) +``` + +हे फंक्शन कॉलडेटामधून अनियंत्रित लांबीची (32 बाइट्सपर्यंत, वर्ड साइज) व्हॅल्यू वाचते. + +```solidity + { + uint _retVal; + + require(length < 0x21, + "_calldataVal length limit is 32 bytes"); + require(length + startByte <= msg.data.length, + "_calldataVal trying to read beyond calldatasize"); +``` + +हे फंक्शन इंटरनल आहे, त्यामुळे जर उर्वरित कोड योग्यरित्या लिहिला असेल, तर या चाचण्यांची आवश्यकता नाही. तथापि, त्यांची किंमत जास्त नाही म्हणून त्या असण्यात काही हरकत नाही. + +```solidity + assembly { + _retVal := calldataload(startByte) + } +``` + +हा कोड [Yul](https://docs.soliditylang.org/en/v0.8.16/yul.html) मध्ये आहे. हे कॉलडेटामधून 32 बाइट व्हॅल्यू वाचते. जर कॉलडेटा `startByte+32` च्या आधी थांबला तरीही हे कार्य करते कारण EVM मधील अनइनिशियलाइज्ड स्पेस शून्य मानली जाते. + +```solidity + _retVal = _retVal >> (256-length*8); +``` + +आम्हाला 32 बाइट व्हॅल्यूच हवी आहे असे नाही. यामुळे अतिरिक्त बाइट्स काढून टाकले जातात. + +```solidity + return _retVal; + } // _calldataVal + + + // _fromByte पासून सुरू होणाऱ्या कॉलडेटामधून एकच पॅरामीटर वाचा + function _readParam(uint _fromByte) internal + returns (uint _nextByte, uint _parameterValue) + { +``` + +कॉलडेटामधून एकच पॅरामीटर वाचा. लक्षात ठेवा की आम्हाला केवळ आपण वाचलेली व्हॅल्यूच नाही, तर पुढील बाइटचे स्थान देखील परत करणे आवश्यक आहे कारण पॅरामीटर्स 1 बाइट ते 33 बाइट्स लांब असू शकतात. + +```solidity + // पहिला बाइट आपल्याला बाकीच्यांचा अर्थ कसा लावायचा हे सांगतो + uint8 _firstByte; + + _firstByte = uint8(_calldataVal(_fromByte, 1)); +``` + +Solidity संभाव्य धोकादायक [इंप्लिसिट टाइप कन्व्हर्शन्स](https://docs.soliditylang.org/en/v0.8.16/types.html#implicit-conversions) प्रतिबंधित करून बग्सची संख्या कमी करण्याचा प्रयत्न करते. डाउनग्रेड, उदाहरणार्थ 256 बिट्सवरून 8 बिट्सपर्यंत, स्पष्टपणे नमूद करणे आवश्यक आहे. + +```solidity + + // व्हॅल्यू वाचा, पण कॅशेमध्ये लिहू नका + if (_firstByte == uint8(DONT_CACHE)) + return(_fromByte+33, _calldataVal(_fromByte+1, 32)); + + // व्हॅल्यू वाचा आणि कॅशेमध्ये लिहा + if (_firstByte == uint8(INTO_CACHE)) { + uint _param = _calldataVal(_fromByte+1, 32); + cacheWrite(_param); + return(_fromByte+33, _param); + } + + // जर आपण इथे पोहोचलो तर याचा अर्थ आपल्याला कॅशेमधून वाचण्याची गरज आहे + + // वाचण्यासाठी अतिरिक्त बाइट्सची संख्या + uint8 _extraBytes = _firstByte / 16; +``` + +खालचा [निबल](https://en.wikipedia.org/wiki/Nibble) घ्या आणि कॅशेमधून व्हॅल्यू वाचण्यासाठी इतर बाइट्ससह एकत्र करा. + +```solidity + uint _key = (uint256(_firstByte & 0x0F) << (8*_extraBytes)) + + _calldataVal(_fromByte+1, _extraBytes); + + return (_fromByte+_extraBytes+1, cacheRead(_key)); + + } // _readParam + + + // n पॅरामीटर्स वाचा (फंक्शन्सना किती पॅरामीटर्स अपेक्षित आहेत हे माहीत असते) + function _readParams(uint _paramNum) internal returns (uint[] memory) { +``` + +आपण आपल्याकडे असलेल्या पॅरामीटर्सची संख्या कॉलडेटामधूनच मिळवू शकलो असतो, परंतु आपल्याला कॉल करणार्‍या फंक्शन्सना किती पॅरामीटर्स अपेक्षित आहेत हे माहीत असते. त्यांनाच आपल्याला सांगू देणे सोपे आहे. + +```solidity + // आपण वाचलेले पॅरामीटर्स + uint[] memory params = new uint[](_paramNum); + + // पॅरामीटर्स बाइट 4 पासून सुरू होतात, त्याआधी फंक्शन सिग्नेचर असते + uint _atByte = 4; + + for(uint i=0; i<_paramNum; i++) { + (_atByte, params[i]) = _readParam(_atByte); + } +``` + +आपल्याला आवश्यक असलेली संख्या मिळेपर्यंत पॅरामीटर्स वाचा. जर आपण कॉलडेटाच्या पुढे गेलो, तर `_readParams` कॉल रिव्हर्ट करेल. + +```solidity + + return(params); + } // readParams + + // _readParams च्या चाचणीसाठी, चार पॅरामीटर्स वाचण्याची चाचणी + function fourParam() public + returns (uint256,uint256,uint256,uint256) + { + uint[] memory params; + params = _readParams(4); + return (params[0], params[1], params[2], params[3]); + } // fourParam +``` + +Foundry चा एक मोठा फायदा हा आहे की ते Solidity मध्ये चाचण्या लिहिण्याची परवानगी देते ([खालील कॅशेची चाचणी पहा](#testing-the-cache)). यामुळे युनिट टेस्ट्स खूप सोप्या होतात. हे एक फंक्शन आहे जे चार पॅरामीटर्स वाचते आणि त्यांना परत करते जेणेकरून चाचणी ते योग्य होते की नाही हे तपासू शकेल. + +```solidity + // एक व्हॅल्यू मिळवा, असे बाइट्स परत करा जे ते एन्कोड करतील (शक्य असल्यास कॅशे वापरून) + function encodeVal(uint _val) public view returns(bytes memory) { +``` + +`encodeVal` हे एक फंक्शन आहे जे ऑफचेन कोड कॅशे वापरणारा कॉलडेटा तयार करण्यात मदत करण्यासाठी कॉल करते. हे एकच व्हॅल्यू प्राप्त करते आणि ते एन्कोड करणारे बाइट्स परत करते. हे फंक्शन `view` आहे, त्यामुळे त्याला व्यवहाराची आवश्यकता नाही आणि बाहेरून कॉल केल्यावर कोणताही गॅस लागत नाही. + +```solidity + uint _key = val2key[_val]; + + // व्हॅल्यू अजून कॅशेमध्ये नाही, ती जोडा + if (_key == 0) + return bytes.concat(INTO_CACHE, bytes32(_val)); +``` + +[EVM](/developers/docs/evm/) मध्ये सर्व अनइनिशियलाइज्ड स्टोरेज शून्य मानले जाते. त्यामुळे जर आपण अशा व्हॅल्यूसाठी की शोधली जी तिथे नाही, तर आपल्याला शून्य मिळतो. त्या बाबतीत, ते एन्कोड करणारे बाइट्स `INTO_CACHE` (जेणेकरून पुढच्या वेळी ते कॅशे केले जाईल) असतात, त्यानंतर वास्तविक व्हॅल्यू असते. + +```solidity + // जर की <0x10 असेल, तर ती एकच बाइट म्हणून परत करा + if (_key < 0x10) + return bytes.concat(bytes1(uint8(_key))); +``` + +सिंगल बाइट्स सर्वात सोपे आहेत. आपण `bytes` प्रकाराला बाइट ॲरेमध्ये बदलण्यासाठी [`bytes.concat`](https://docs.soliditylang.org/en/v0.8.16/types.html#the-functions-bytes-concat-and-string-concat) वापरतो, ज्याची कोणतीही लांबी असू शकते. नाव असूनही, फक्त एक युक्तिवाद दिल्यावर ते व्यवस्थित काम करते. + +```solidity + // दोन बाइट व्हॅल्यू, 0x1vvv म्हणून एन्कोड केलेली + if (_key < 0x1000) + return bytes.concat(bytes2(uint16(_key) | 0x1000)); +``` + +जेव्हा आपल्याकडे 163 पेक्षा कमी असलेली की असते, तेव्हा आपण ती दोन बाइट्समध्ये व्यक्त करू शकतो. आपण आधी `_key`, जे 256 बिट व्हॅल्यू आहे, ते 16 बिट व्हॅल्यूमध्ये रूपांतरित करतो आणि पहिल्या बाइटमध्ये अतिरिक्त बाइट्सची संख्या जोडण्यासाठी लॉजिकल ऑर वापरतो. मग आपण ते `bytes2` व्हॅल्यूमध्ये टाकतो, जे `bytes` मध्ये रूपांतरित केले जाऊ शकते. + +```solidity + // खालील ओळी लूप म्हणून करण्याचा कदाचित एक हुशार मार्ग आहे, + // पण हे एक व्ह्यू फंक्शन आहे म्हणून मी प्रोग्रामरच्या वेळेसाठी आणि + // सोपेपणासाठी ऑप्टिमाइझ करत आहे. + + if (_key < 16*256**2) + return bytes.concat(bytes3(uint24(_key) | (0x2 * 16 * 256**2))); + if (_key < 16*256**3) + return bytes.concat(bytes4(uint32(_key) | (0x3 * 16 * 256**3))); + . + . + . + if (_key < 16*256**14) + return bytes.concat(bytes15(uint120(_key) | (0xE * 16 * 256**14))); + if (_key < 16*256**15) + return bytes.concat(bytes16(uint128(_key) | (0xF * 16 * 256**15))); +``` + +इतर व्हॅल्यूज (3 बाइट्स, 4 बाइट्स, इत्यादी) त्याच प्रकारे हाताळल्या जातात, फक्त फील्ड आकार भिन्न असतात. + +```solidity + // जर आपण इथे पोहोचलो, तर काहीतरी चुकले आहे. + revert("Error in encodeVal, should not happen"); +``` + +जर आपण इथे पोहोचलो तर याचा अर्थ आपल्याला एक की मिळाली आहे जी 16\*25615 पेक्षा कमी नाही. परंतु `cacheWrite` कीज मर्यादित करते त्यामुळे आपण 14\*25616 पर्यंत पोहोचू शकत नाही (ज्याचा पहिला बाइट 0xFE असेल, म्हणून ते `DONT_CACHE` सारखे दिसेल). परंतु भविष्यात एखादा प्रोग्रामर बग आणल्यास चाचणी जोडण्यासाठी आपल्याला जास्त खर्च येत नाही. + +```solidity + } // encodeVal + +} // Cache +``` + +### कॅशेची चाचणी {#testing-the-cache} + +Foundry चा एक फायदा हा आहे की [ते तुम्हाला Solidity मध्ये चाचण्या लिहिण्याची परवानगी देते](https://getfoundry.sh/forge/tests/overview/), ज्यामुळे युनिट चाचण्या लिहिणे सोपे होते. `Cache` क्लाससाठीच्या चाचण्या [येथे](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/test/Cache.t.sol) आहेत. कारण चाचणी कोड पुनरावृत्तीचा आहे, जसे चाचण्या असतात, हा लेख फक्त मनोरंजक भाग स्पष्ट करतो. + +```solidity +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; + + +// कन्सोलसाठी `forge test -vv` चालवणे आवश्यक आहे. +import "forge-std/console.sol"; +``` + +हे फक्त बॉयलरप्लेट आहे जे चाचणी पॅकेज आणि `console.log` वापरण्यासाठी आवश्यक आहे. + +```solidity +import "src/Cache.sol"; +``` + +आपण ज्या कराराची चाचणी घेत आहोत ते आपल्याला माहित असणे आवश्यक आहे. + +```solidity +contract CacheTest is Test { + Cache cache; + + function setUp() public { + cache = new Cache(); + } +``` + +`setUp` फंक्शन प्रत्येक चाचणीपूर्वी कॉल केले जाते. या प्रकरणात आपण फक्त एक नवीन कॅशे तयार करतो, जेणेकरून आपल्या चाचण्या एकमेकांवर परिणाम करणार नाहीत. + +```solidity + function testCaching() public { +``` + +चाचण्या ही अशी फंक्शन्स आहेत ज्यांची नावे `test` ने सुरू होतात. हे फंक्शन मूलभूत कॅशे कार्यक्षमता तपासते, व्हॅल्यूज लिहिणे आणि त्या पुन्हा वाचणे. + +```solidity + for(uint i=1; i<5000; i++) { + cache.cacheWrite(i*i); + } + + for(uint i=1; i<5000; i++) { + assertEq(cache.cacheRead(i), i*i); +``` + +[`assert...` फंक्शन्स](https://getfoundry.sh/reference/forge-std/std-assertions/) वापरून तुम्ही प्रत्यक्ष चाचणी कशी करता हे येथे दिले आहे. या प्रकरणात, आम्ही तपासतो की आम्ही लिहिलेली व्हॅल्यू हीच आम्ही वाचलेली व्हॅल्यू आहे. आपण `cache.cacheWrite` चा निकाल सोडून देऊ शकतो कारण आपल्याला माहित आहे की कॅशे की रेषीयपणे नियुक्त केल्या जातात. + +```solidity + } + } // testCaching + + + // एकाच व्हॅल्यूला अनेक वेळा कॅशे करा, की तीच + // राहील याची खात्री करा + function testRepeatCaching() public { + for(uint i=1; i<100; i++) { + uint _key1 = cache.cacheWrite(i); + uint _key2 = cache.cacheWrite(i); + assertEq(_key1, _key2); + } +``` + +प्रथम आम्ही प्रत्येक व्हॅल्यू कॅशेमध्ये दोनदा लिहितो आणि कीज समान असल्याची खात्री करतो (म्हणजे दुसरे लिखाण खरोखरच झाले नाही). + +```solidity + for(uint i=1; i<100; i+=3) { + uint _key = cache.cacheWrite(i); + assertEq(_key, i); + } + } // testRepeatCaching +``` + +सिद्धांतानुसार, एक बग असू शकतो जो सलग कॅशे लेखनावर परिणाम करत नाही. म्हणून येथे आम्ही काही असे लेखन करतो जे सलग नाहीत आणि पाहतो की व्हॅल्यूज अद्याप पुन्हा लिहिल्या जात नाहीत. + +```solidity + // मेमरी बफरमधून एक uint वाचा (आपण पाठवलेले पॅरामीटर्स + // परत मिळतात याची खात्री करण्यासाठी) + function toUint256(bytes memory _bytes, uint256 _start) internal pure + returns (uint256) +``` + +`bytes memory` बफरमधून 256 बिट वर्ड वाचा. हे युटिलिटी फंक्शन आम्हाला कॅशे वापरणारे फंक्शन कॉल चालवल्यावर योग्य परिणाम मिळतात की नाही हे सत्यापित करू देते. + +```solidity + { + require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); + uint256 tempUint; + + assembly { + tempUint := mload(add(add(_bytes, 0x20), _start)) + } +``` + +Yul `uint256` च्या पलीकडे डेटा स्ट्रक्चर्सला समर्थन देत नाही, म्हणून जेव्हा तुम्ही अधिक अत्याधुनिक डेटा स्ट्रक्चरचा संदर्भ देता, जसे की मेमरी बफर `_bytes`, तेव्हा तुम्हाला त्या स्ट्रक्चरचा ॲड्रेस मिळतो. Solidity `bytes memory` व्हॅल्यूज 32 बाइट वर्ड म्हणून संग्रहित करते ज्यात लांबी असते, त्यानंतर वास्तविक बाइट्स असतात, त्यामुळे बाइट क्रमांक `_start` मिळवण्यासाठी आपल्याला `_bytes+32+_start` मोजणे आवश्यक आहे. + +```solidity + + return tempUint; + } // toUint256 + + // fourParams() साठी फंक्शन सिग्नेचर, सौजन्याने + // https://www.4byte.directory/signatures/?bytes4_signature=0x3edc1e6d + bytes4 constant FOUR_PARAMS = 0x3edc1e6d; + + // आपल्याला योग्य व्हॅल्यूज परत मिळत आहेत हे पाहण्यासाठी फक्त काही कॉन्स्टंट व्हॅल्यूज + uint256 constant VAL_A = 0xDEAD60A7; + uint256 constant VAL_B = 0xBEEF; + uint256 constant VAL_C = 0x600D; + uint256 constant VAL_D = 0x600D60A7; +``` + +चाचणीसाठी आपल्याला आवश्यक असलेले काही कॉन्स्टंट्स. + +```solidity + function testReadParam() public { +``` + +`readParams` वापरणारे फंक्शन `fourParams()` ला कॉल करा, जेणेकरून आपण पॅरामीटर्स योग्यरित्या वाचू शकतो की नाही हे तपासता येईल. + +```solidity + address _cacheAddr = address(cache); + bool _success; + bytes memory _callInput; + bytes memory _callOutput; +``` + +आपण कॅशे वापरून फंक्शन कॉल करण्यासाठी सामान्य ABI यंत्रणा वापरू शकत नाही, म्हणून आपल्याला निम्न स्तरावरील [`
.call()`](https://docs.soliditylang.org/en/v0.8.16/types.html#members-of-addresses) यंत्रणा वापरण्याची आवश्यकता आहे. ती यंत्रणा इनपुट म्हणून `bytes memory` घेते आणि ते (तसेच बुलियन व्हॅल्यू) आउटपुट म्हणून परत करते. + +```solidity + // पहिला कॉल, कॅशे रिकामा आहे + _callInput = bytes.concat( + FOUR_PARAMS, +``` + +एकाच करारासाठी कॅश्ड फंक्शन्स (थेट व्यवहारांमधून कॉल करण्यासाठी) आणि नॉन-कॅश्ड फंक्शन्स (इतर स्मार्ट करारांमधून कॉल करण्यासाठी) दोन्हीला समर्थन देणे उपयुक्त आहे. हे करण्यासाठी, आपल्याला सर्व काही [एका `fallback` फंक्शनमध्ये](https://docs.soliditylang.org/en/v0.8.16/contracts.html#fallback-function) टाकण्याऐवजी, योग्य फंक्शनला कॉल करण्यासाठी Solidity यंत्रणेवर अवलंबून राहणे आवश्यक आहे. हे केल्याने कंपोझेबिलिटी खूप सोपी होते. बहुतेक प्रकरणांमध्ये फंक्शन ओळखण्यासाठी एकच बाइट पुरेसा असेल, म्हणून आपण तीन बाइट्स (16\*3=48 गॅस) वाया घालवत आहोत. तथापि, मी हे लिहित असताना त्या 48 गॅसची किंमत 0.07 सेंट आहे, जी सोप्या, कमी बग प्रोन कोडसाठी वाजवी किंमत आहे. + +```solidity + // पहिली व्हॅल्यू, ती कॅशेमध्ये जोडा + cache.INTO_CACHE(), + bytes32(VAL_A), +``` + +पहिली व्हॅल्यू: एक फ्लॅग जो सांगतो की ही एक पूर्ण व्हॅल्यू आहे जी कॅशेमध्ये लिहिली पाहिजे, त्यानंतर व्हॅल्यूचे 32 बाइट्स. इतर तीन व्हॅल्यूज सारख्याच आहेत, फक्त `VAL_B` कॅशेमध्ये लिहिलेली नाही आणि `VAL_C` तिसरा आणि चौथा दोन्ही पॅरामीटर आहे. + +```solidity + . + . + . + ); + (_success, _callOutput) = _cacheAddr.call(_callInput); +``` + +येथेच आपण प्रत्यक्षात `Cache` कराराला कॉल करतो. + +```solidity + assertEq(_success, true); +``` + +आम्ही अपेक्षा करतो की कॉल यशस्वी होईल. + +```solidity + assertEq(cache.cacheRead(1), VAL_A); + assertEq(cache.cacheRead(2), VAL_C); +``` + +आपण रिकाम्या कॅशेने सुरुवात करतो आणि नंतर `VAL_A` आणि त्यानंतर `VAL_C` जोडतो. आम्ही अपेक्षा करतो की पहिल्याची की 1 असेल आणि दुसऱ्याची 2 असेल. + +``` + assertEq(toUint256(_callOutput,0), VAL_A); + assertEq(toUint256(_callOutput,32), VAL_B); + assertEq(toUint256(_callOutput,64), VAL_C); + assertEq(toUint256(_callOutput,96), VAL_C); +``` + +आउटपुट हे चार पॅरामीटर्स आहेत. येथे आम्ही ते योग्य असल्याची पडताळणी करतो. + +```solidity + // दुसरा कॉल, आपण कॅशे वापरू शकतो + _callInput = bytes.concat( + FOUR_PARAMS, + + // कॅशेमधील पहिली व्हॅल्यू + bytes1(0x01), +``` + +16 पेक्षा कमी असलेल्या कॅशे की फक्त एक बाइटच्या असतात. + +```solidity + // दुसरी व्हॅल्यू, ती कॅशेमध्ये जोडू नका + cache.DONT_CACHE(), + bytes32(VAL_B), + + // तिसरी आणि चौथी व्हॅल्यू, समान व्हॅल्यू + bytes1(0x02), + bytes1(0x02) + ); + . + . + . + } // testReadParam +``` + +कॉलनंतरच्या चाचण्या पहिल्या कॉलनंतरच्या चाचण्यांसारख्याच आहेत. + +```solidity + function testEncodeVal() public { +``` + +हे फंक्शन `testReadParam` सारखेच आहे, फक्त फरक एवढाच की पॅरामीटर्स स्पष्टपणे लिहिण्याऐवजी आपण `encodeVal()` वापरतो. + +```solidity + . + . + . + _callInput = bytes.concat( + FOUR_PARAMS, + cache.encodeVal(VAL_A), + cache.encodeVal(VAL_B), + cache.encodeVal(VAL_C), + cache.encodeVal(VAL_D) + ); + . + . + . + assertEq(_callInput.length, 4+1*4); + } // testEncodeVal +``` + +`testEncodeVal()` मधील एकमेव अतिरिक्त चाचणी म्हणजे `_callInput` ची लांबी योग्य आहे की नाही हे तपासणे. पहिल्या कॉलसाठी ते 4+33\*4 आहे. दुसऱ्यासाठी, जिथे प्रत्येक व्हॅल्यू आधीच कॅशेमध्ये आहे, ते 4+1\*4 आहे. + +```solidity + // जेव्हा की एका बाइटपेक्षा जास्त असेल तेव्हा encodeVal ची चाचणी घ्या + // कमाल तीन बाइट्स कारण कॅशे चार बाइट्सपर्यंत भरण्यास + // खूप वेळ लागतो. + function testEncodeValBig() public { + // कॅशेमध्ये अनेक व्हॅल्यूज ठेवा. + // गोष्टी सोप्या ठेवण्यासाठी, व्हॅल्यू n साठी की n वापरा. + for(uint i=1; i<0x1FFF; i++) { + cache.cacheWrite(i); + } +``` + +वरील `testEncodeVal` फंक्शन कॅशेमध्ये फक्त चार व्हॅल्यूज लिहिते, त्यामुळे [फंक्शनचा जो भाग मल्टी-बाइट व्हॅल्यूज हाताळतो](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/Cache.sol#L144-L171) तो तपासला जात नाही. परंतु तो कोड गुंतागुंतीचा आणि त्रुटी-प्रवण आहे. + +या फंक्शनचा पहिला भाग एक लूप आहे जो 1 ते 0x1FFF पर्यंतच्या सर्व व्हॅल्यूज क्रमाने कॅशेमध्ये लिहितो, जेणेकरून आपण त्या व्हॅल्यूज एन्कोड करू शकू आणि त्या कुठे जात आहेत हे जाणून घेऊ शकू. + +```solidity + . + . + . + + _callInput = bytes.concat( + FOUR_PARAMS, + cache.encodeVal(0x000F), // एक बाइट 0x0F + cache.encodeVal(0x0010), // दोन बाइट्स 0x1010 + cache.encodeVal(0x0100), // दोन बाइट्स 0x1100 + cache.encodeVal(0x1000) // तीन बाइट्स 0x201000 + ); +``` + +एक बाइट, दोन बाइट आणि तीन बाइट व्हॅल्यूजची चाचणी घ्या. आम्ही त्यापलीकडे चाचणी करत नाही कारण पुरेशा स्टॅक नोंदी लिहिण्यासाठी खूप वेळ लागेल (किमान 0x10000000, अंदाजे पाव अब्ज). + +```solidity + . + . + . + . + } // testEncodeValBig + + + // अत्यंत लहान बफरमुळे आपल्याला रिव्हर्ट मिळतो की नाही याची चाचणी + function testShortCalldata() public { +``` + +जेव्हा पुरेसे पॅरामीटर्स नसतात तेव्हा असामान्य परिस्थितीत काय होते याची चाचणी घ्या. + +```solidity + . + . + . + (_success, _callOutput) = _cacheAddr.call(_callInput); + assertEq(_success, false); + } // testShortCalldata +``` + +ते रिव्हर्ट होत असल्याने, आपल्याला मिळणारा निकाल `false` असावा. + +``` + // अस्तित्वात नसलेल्या कॅशे कीजसह कॉल करा + function testNoCacheKey() public { + . + . + . + _callInput = bytes.concat( + FOUR_PARAMS, + + // पहिली व्हॅल्यू, ती कॅशेमध्ये जोडा + cache.INTO_CACHE(), + bytes32(VAL_A), + + // दुसरी व्हॅल्यू + bytes1(0x0F), + bytes2(0x1234), + bytes11(0xA10102030405060708090A) + ); +``` + +हे फंक्शन चार पूर्णपणे कायदेशीर पॅरामीटर्स मिळवते, फक्त फरक एवढाच की कॅशे रिकामा आहे त्यामुळे वाचण्यासाठी तेथे कोणतीही व्हॅल्यूज नाहीत. + +```solidity + . + . + . + // अत्यंत लांब बफरसह सर्व काही व्यवस्थित काम करते की नाही याची चाचणी + function testLongCalldata() public { + address _cacheAddr = address(cache); + bool _success; + bytes memory _callInput; + bytes memory _callOutput; + + // पहिला कॉल, कॅशे रिकामा आहे + _callInput = bytes.concat( + FOUR_PARAMS, + + // पहिली व्हॅल्यू, ती कॅशेमध्ये जोडा + cache.INTO_CACHE(), bytes32(VAL_A), + + // दुसरी व्हॅल्यू, ती कॅशेमध्ये जोडा + cache.INTO_CACHE(), bytes32(VAL_B), + + // तिसरी व्हॅल्यू, ती कॅशेमध्ये जोडा + cache.INTO_CACHE(), bytes32(VAL_C), + + // चौथी व्हॅल्यू, ती कॅशेमध्ये जोडा + cache.INTO_CACHE(), bytes32(VAL_D), + + // आणि "गुड लक" साठी आणखी एक व्हॅल्यू + bytes4(0x31112233) + ); +``` + +हे फंक्शन पाच व्हॅल्यूज पाठवते. आम्हाला माहित आहे की पाचवी व्हॅल्यू दुर्लक्षित केली जाते कारण ती वैध कॅशे नोंद नाही, जी समाविष्ट केली नसती तर रिव्हर्ट झाली असती. + +```solidity + (_success, _callOutput) = _cacheAddr.call(_callInput); + assertEq(_success, true); + . + . + . + } // testLongCalldata + +} // CacheTest + +``` + +## एक नमुना ॲप्लिकेशन {#a-sample-app} + +Solidity मध्ये चाचण्या लिहिणे खूप चांगले आहे, पण शेवटी, उपयुक्त होण्यासाठी dapp ला चेनच्या बाहेरून आलेल्या विनंत्यांवर प्रक्रिया करता आली पाहिजे. हा लेख `WORM` सह dapp मध्ये कॅशिंग कसे वापरावे हे दाखवतो, ज्याचा अर्थ "एकदा लिहा, अनेकदा वाचा" असा होतो. जर की अजून लिहिलेली नसेल, तर तुम्ही त्यावर एक व्हॅल्यू लिहू शकता. जर की आधीच लिहिलेली असेल, तर तुम्हाला रिव्हर्ट मिळेल. + +### करार {#the-contract} + +[हा करार आहे](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/src/WORM.sol). हे बहुतेक `Cache` आणि `CacheTest` सह आपण आधीच जे केले आहे त्याचीच पुनरावृत्ती करते, म्हणून आपण फक्त मनोरंजक भाग कव्हर करू. + +```solidity +import "./Cache.sol"; + +contract WORM is Cache { +``` + +`Cache` वापरण्याचा सर्वात सोपा मार्ग म्हणजे तो आपल्या स्वतःच्या करारामध्ये इनहेरिट करणे. + +```solidity + function writeEntryCached() external { + uint[] memory params = _readParams(2); + writeEntry(params[0], params[1]); + } // writeEntryCached +``` + +हे फंक्शन वरील `CacheTest` मधील `fourParam` सारखेच आहे. कारण आपण ABI स्पेसिफिकेशन्सचे पालन करत नाही, त्यामुळे फंक्शनमध्ये कोणतेही पॅरामीटर्स घोषित न करणे चांगले आहे. + +```solidity + // आम्हाला कॉल करणे सोपे करा + // writeEntryCached() साठी फंक्शन सिग्नेचर, सौजन्याने + // https://www.4byte.directory/signatures/?bytes4_signature=0xe4e4f2d3 + bytes4 constant public WRITE_ENTRY_CACHED = 0xe4e4f2d3; +``` + +`writeEntryCached` ला कॉल करणारा बाह्य कोडला `worm.writeEntryCached` वापरण्याऐवजी मॅन्युअली कॉलडेटा तयार करावा लागेल, कारण आम्ही ABI स्पेसिफिकेशन्सचे पालन करत नाही. हे कॉन्स्टंट व्हॅल्यू असल्याने ते लिहिणे सोपे होते. + +लक्षात ठेवा की आम्ही `WRITE_ENTRY_CACHED` ला स्टेट व्हेरिएबल म्हणून परिभाषित केले असले तरी, ते बाहेरून वाचण्यासाठी त्यासाठी गेटर फंक्शन `worm.WRITE_ENTRY_CACHED()` वापरणे आवश्यक आहे. + +```solidity + function readEntry(uint key) public view + returns (uint _value, address _writtenBy, uint _writtenAtBlock) +``` + +रीड फंक्शन `view` आहे, त्यामुळे त्याला व्यवहाराची आवश्यकता नाही आणि गॅस लागत नाही. परिणामी, पॅरामीटरसाठी कॅशे वापरण्याचा कोणताही फायदा नाही. व्ह्यू फंक्शन्ससह, सोपी असलेली मानक यंत्रणा वापरणे सर्वोत्तम आहे. + +### चाचणी कोड {#the-testing-code} + +[हा करारासाठीचा चाचणी कोड आहे](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/test/WORM.t.sol). पुन्हा, आपण फक्त मनोरंजक गोष्टी पाहू. + +```solidity + function testWReadWrite() public { + worm.writeEntry(0xDEAD, 0x60A7); + + vm.expectRevert(bytes("entry already written")); + worm.writeEntry(0xDEAD, 0xBEEF); +``` + +Foundry चाचणीमध्ये पुढील कॉल अयशस्वी व्हावा आणि अयशस्वी होण्याचे नोंदवलेले कारण कसे निर्दिष्ट करावे हे [हे (`vm.expectRevert`)](https://book.getfoundry.sh/cheatcodes/expect-revert#expectrevert) आहे. जेव्हा आपण `.` सिंटॅक्स वापरतो तेव्हा हे लागू होते()` कॉलडेटा तयार करून आणि निम्न-स्तरीय इंटरफेस (`.call()` इत्यादी) वापरून कराराला कॉल करण्याऐवजी. + +```solidity + function testReadWriteCached() public { + uint cacheGoat = worm.cacheWrite(0x60A7); +``` + +येथे आपण या वस्तुस्थितीचा वापर करतो की `cacheWrite` कॅशे की परत करते. हे असे काहीतरी नाही जे आपण उत्पादनात वापरण्याची अपेक्षा करतो, कारण `cacheWrite` स्टेट बदलते आणि म्हणून फक्त व्यवहारादरम्यानच कॉल केले जाऊ शकते. व्यवहारांना रिटर्न व्हॅल्यूज नसतात, जर त्यांचे निकाल असतील तर ते निकाल इव्हेंट म्हणून प्रसारित केले जातात. त्यामुळे `cacheWrite` रिटर्न व्हॅल्यू केवळ ऑनचेन कोडवरूनच ॲक्सेस करता येते आणि ऑनचेन कोडला पॅरामीटर कॅशिंगची आवश्यकता नसते. + +```solidity + (_success,) = address(worm).call(_callInput); +``` + +याद्वारे आपण Solidity ला सांगतो की `.call()` मध्ये दोन रिटर्न व्हॅल्यूज असल्या तरी, आपल्याला फक्त पहिल्याचीच काळजी आहे. + +```solidity + (_success,) = address(worm).call(_callInput); + assertEq(_success, false); +``` + +कारण आपण निम्न-स्तरीय `
.call()` फंक्शन वापरतो, आपण `vm.expectRevert()` वापरू शकत नाही आणि आपल्याला कॉलमधून मिळणाऱ्या बुलियन यश व्हॅल्यूकडे लक्ष द्यावे लागते. + +```solidity + event EntryWritten(uint indexed key, uint indexed value); + + . + . + . + + _callInput = bytes.concat( + worm.WRITE_ENTRY_CACHED(), worm.encodeVal(a), worm.encodeVal(b)); + vm.expectEmit(true, true, false, false); + emit EntryWritten(a, b); + (_success,) = address(worm).call(_callInput); +``` + +Foundry मध्ये कोड [योग्यरित्या इव्हेंट प्रसारित करतो](https://getfoundry.sh/reference/cheatcodes/expect-emit/) की नाही हे तपासण्याचा हा मार्ग आहे. + +### क्लायंट {#the-client} + +Solidity चाचण्यांसोबत एक गोष्ट मिळत नाही ती म्हणजे जावास्क्रिप्ट कोड जो तुम्ही तुमच्या स्वतःच्या ॲप्लिकेशनमध्ये कट आणि पेस्ट करू शकता. तो कोड लिहिण्यासाठी मी WORM ला [Optimism Goerli](https://community.optimism.io/docs/useful-tools/networks/#optimism-goerli) वर तैनात केले, जो [Optimism's](https://www.optimism.io/) नवीन टेस्टनेट आहे. ते [`0xd34335b1d818cee54e3323d3246bd31d94e6a78a`](https://goerli-optimism.etherscan.io/address/0xd34335b1d818cee54e3323d3246bd31d94e6a78a) ॲड्रेसवर आहे. + +[तुम्ही क्लायंटसाठी जावास्क्रिप्ट कोड येथे पाहू शकता](https://github.com/qbzzt/20220915-all-you-can-cache/blob/main/javascript/index.js). ते वापरण्यासाठी: + +1. गिट रिपॉझिटरी क्लोन करा: + + ```sh + git clone https://github.com/qbzzt/20220915-all-you-can-cache.git + ``` + +2. आवश्यक पॅकेजेस स्थापित करा: + + ```sh + cd javascript + yarn + ``` + +3. कॉन्फिगरेशन फाईल कॉपी करा: + + ```sh + cp .env.example .env + ``` + +4. तुमच्या कॉन्फिगरेशनसाठी `.env` संपादित करा: + + | पॅरामीटर | मूल्य | + | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | MNEMONIC | एका खात्यासाठी मेमोनिक ज्यामध्ये व्यवहारासाठी पैसे भरण्यासाठी पुरेसे ETH आहे. [तुम्ही Optimism Goerli नेटवर्कसाठी मोफत ETH येथे मिळवू शकता](https://optimismfaucet.xyz/). | + | OPTIMISM_GOERLI_URL | Optimism Goerli साठी URL. पब्लिक एंडपॉइंट, `https://goerli.optimism.io`, रेट लिमिटेड आहे पण आपल्याला येथे जे हवे आहे त्यासाठी पुरेसा आहे | + +5. `index.js` चालवा. + + ```sh + node index.js + ``` + + हे नमुना ॲप्लिकेशन प्रथम WORM मध्ये एक नोंद लिहिते, कॉलडेटा आणि Etherscan वरील व्यवहाराची लिंक दर्शवते. नंतर ते ती नोंद परत वाचते, आणि ती वापरत असलेली की आणि नोंदीमधील व्हॅल्यूज (व्हॅल्यू, ब्लॉक क्रमांक आणि लेखक) दर्शवते. + +बहुतेक क्लायंट सामान्य Dapp JavaScript आहे. त्यामुळे पुन्हा आपण फक्त मनोरंजक भागांवरच नजर टाकू. + +```javascript +. +. +. +const main = async () => { + const func = await worm.WRITE_ENTRY_CACHED() + + // प्रत्येक वेळी नवीन की आवश्यक आहे + const key = await worm.encodeVal(Number(new Date())) +``` + +दिलेल्या स्लॉटमध्ये फक्त एकदाच लिहिले जाऊ शकते, म्हणून आम्ही स्लॉट पुन्हा वापरत नाही याची खात्री करण्यासाठी टाइमस्टॅम्प वापरतो. + +```javascript +const val = await worm.encodeVal("0x600D") + +// एक नोंद लिहा +const calldata = func + key.slice(2) + val.slice(2) +``` + +Ethers ला कॉल डेटा हेक्स स्ट्रिंग असण्याची अपेक्षा आहे, `0x` नंतर सम संख्येतील हेक्साडेसिमल अंक. `key` आणि `val` दोन्ही `0x` ने सुरू होत असल्याने, आपल्याला ते हेडर काढून टाकणे आवश्यक आहे. + +```javascript +const tx = await worm.populateTransaction.writeEntryCached() +tx.data = calldata + +sentTx = await wallet.sendTransaction(tx) +``` + +Solidity चाचणी कोडप्रमाणे, आपण कॅश्ड फंक्शनला सामान्यपणे कॉल करू शकत नाही. त्याऐवजी, आपल्याला निम्न-स्तरीय यंत्रणा वापरण्याची आवश्यकता आहे. + +```javascript + . + . + . + // नुकतीच लिहिलेली नोंद वाचा + const realKey = '0x' + key.slice(4) // FF फ्लॅग काढा + const entryRead = await worm.readEntry(realKey) + . + . + . +``` + +नोंदी वाचण्यासाठी आपण सामान्य यंत्रणा वापरू शकतो. `view` फंक्शन्ससह पॅरामीटर कॅशिंग वापरण्याची आवश्यकता नाही. + +## निष्कर्ष {#conclusion} + +या लेखातील कोड एक प्रूफ ऑफ कॉन्सेप्ट आहे, उद्देश ही कल्पना समजण्यास सोपी करणे हा आहे. उत्पादनासाठी सज्ज प्रणालीसाठी तुम्ही काही अतिरिक्त कार्यक्षमता लागू करू शकता: + +- `uint256` नसलेल्या व्हॅल्यूज हाताळा. उदाहरणार्थ, स्ट्रिंग्स. +- जागतिक कॅशेऐवजी, कदाचित वापरकर्ते आणि कॅशे यांच्यात मॅपिंग ठेवा. वेगवेगळे वापरकर्ते वेगवेगळ्या व्हॅल्यूज वापरतात. +- ॲड्रेससाठी वापरल्या जाणार्‍या व्हॅल्यूज इतर उद्देशांसाठी वापरल्या जाणार्‍या व्हॅल्यूजपेक्षा वेगळ्या असतात. फक्त ॲड्रेससाठी वेगळा कॅशे असणे अर्थपूर्ण असू शकते. +- सध्या, कॅशे की "प्रथम येणाऱ्यास, सर्वात लहान की" अल्गोरिदमवर आहेत. पहिल्या सोळा व्हॅल्यूज एकाच बाइटमध्ये पाठवल्या जाऊ शकतात. पुढील 4080 व्हॅल्यूज दोन बाइट्समध्ये पाठवल्या जाऊ शकतात. पुढील अंदाजे दहा लाख व्हॅल्यूज तीन बाइट्सच्या आहेत, इत्यादी. एक उत्पादन प्रणालीने कॅशे नोंदींवर वापर काउंटर ठेवावेत आणि त्यांची पुनर्रचना करावी जेणेकरून सोळा _सर्वात सामान्य_ व्हॅल्यूज एक बाइटच्या असतील, पुढील 4080 सर्वात सामान्य व्हॅल्यूज दोन बाइट्सच्या असतील, इत्यादी. + + तथापि, ही एक संभाव्य धोकादायक क्रिया आहे. खालील घटनांचा क्रम कल्पना करा: + + 1. नोआम नेव्ह त्याला टोकन पाठवायचे असलेल्या ॲड्रेसला एन्कोड करण्यासाठी `encodeVal` ला कॉल करतो. तो ॲड्रेस ॲप्लिकेशनवर वापरल्या जाणाऱ्या पहिल्या ॲड्रेसपैकी एक आहे, त्यामुळे एन्कोड केलेली व्हॅल्यू 0x06 आहे. हे एक `view` फंक्शन आहे, व्यवहार नाही, त्यामुळे ते नोआम आणि तो वापरत असलेल्या नोडच्या दरम्यान आहे आणि इतर कोणालाही त्याबद्दल माहिती नाही + + 2. ओवेन ओनर कॅशे पुनर्रचना ऑपरेशन चालवतो. फार कमी लोक प्रत्यक्षात तो ॲड्रेस वापरतात, त्यामुळे तो आता 0x201122 म्हणून एन्कोड केला आहे. एक वेगळी व्हॅल्यू, 1018, 0x06 ला नियुक्त केली आहे. + + 3. नोआम नेव्ह त्याचे टोकन 0x06 वर पाठवतो. ते `0x0000000000000000000000000de0b6b3a7640000` ॲड्रेसवर जातात, आणि त्या ॲड्रेसची प्रायव्हेट की कोणालाच माहीत नसल्याने, ते तिथेच अडकून पडतात. नोआम _खुश नाही_. + + ही समस्या सोडवण्याचे मार्ग आहेत, आणि कॅशे पुनर्रचनेदरम्यान मेमपूलमध्ये असलेल्या व्यवहारांची संबंधित समस्या, पण तुम्हाला त्याबद्दल जागरूक असले पाहिजे. + +मी येथे Optimism सह कॅशिंगचे प्रदर्शन केले आहे, कारण मी Optimism चा कर्मचारी आहे आणि हा रोलअप मला सर्वोत्तम माहीत आहे. परंतु ते कोणत्याही रोलअपसह कार्य केले पाहिजे जे अंतर्गत प्रक्रियेसाठी किमान खर्च आकारते, जेणेकरून तुलनेत L1 वर व्यवहार डेटा लिहिणे हा मोठा खर्च असेल. + +[माझ्या कामाबद्दल अधिक माहितीसाठी येथे पहा](https://cryptodocguy.pro/). + diff --git a/public/content/translations/mr/developers/tutorials/app-plasma/index.md b/public/content/translations/mr/developers/tutorials/app-plasma/index.md new file mode 100644 index 00000000000..9a26c00004e --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/app-plasma/index.md @@ -0,0 +1,1256 @@ +--- +title: "गोपनीयतेचे संरक्षण करणारा ॲप-विशिष्ट प्लाझ्मा लिहा" +description: "या ट्युटोरिअलमध्ये, आम्ही ठेवींसाठी एक अर्ध-गुप्त बँक तयार करतो. बँक एक केंद्रीकृत घटक आहे; तिला प्रत्येक वापरकर्त्याची शिल्लक माहीत असते. तथापि, ही माहिती ऑनचेन साठवली जात नाही. त्याऐवजी, बँक स्टेटचा हॅश पोस्ट करते. प्रत्येक वेळी व्यवहार होतो तेव्हा, बँक नवीन हॅश पोस्ट करते, यासोबतच एक शून्य-ज्ञान पुरावा देखील देते की तिच्याकडे एक स्वाक्षरी केलेला व्यवहार आहे जो हॅश स्टेटला नवीन स्टेटमध्ये बदलतो. हे ट्युटोरिअल वाचल्यानंतर, तुम्हाला शून्य-ज्ञान पुरावे कसे वापरायचे हे तर समजेलच, पण ते का वापरायचे आणि सुरक्षितपणे कसे वापरायचे हे देखील समजेल." +author: Ori Pomerantz +tags: [ "शून्य-ज्ञान", "सर्व्हर", "ऑफचेन", "गोपनीयता" ] +skill: advanced +lang: mr +published: 2025-10-15 +--- + +## प्रस्तावना {#introduction} + +[रोलअप्स](/developers/docs/scaling/zk-rollups/) च्या तुलनेत, [प्लाझ्मा](/developers/docs/scaling/plasma) अखंडतेसाठी Ethereum मेननेट वापरतात, परंतु उपलब्धतेसाठी नाही. या लेखात, आम्ही एक ॲप्लिकेशन लिहितो जे प्लाझ्मासारखे वागते, ज्यात Ethereum अखंडतेची (अनधिकृत बदल नाहीत) हमी देतो परंतु उपलब्धतेची नाही (एक केंद्रीकृत घटक बंद होऊ शकतो आणि संपूर्ण प्रणाली अक्षम करू शकतो). + +आम्ही येथे जे ॲप्लिकेशन लिहित आहोत ते एक गोपनीयता-संरक्षक बँक आहे. वेगवेगळ्या ॲड्रेसवर शिल्लक असलेली खाती आहेत, आणि ते इतर खात्यांमध्ये पैसे (ETH) पाठवू शकतात. बँक स्टेट (खाती आणि त्यांची शिल्लक) आणि व्यवहारांचे हॅश पोस्ट करते, परंतु वास्तविक शिल्लक ऑफचेन ठेवते जिथे ते खाजगी राहू शकतात. + +## डिझाइन {#design} + +ही प्रोडक्शन-रेडी प्रणाली नाही, तर एक शिकवण्याचे साधन आहे. त्यामुळे, ते अनेक सरलीकरण गृहितकांसह लिहिलेले आहे. + +- निश्चित खाते पूल. खात्यांची एक विशिष्ट संख्या आहे, आणि प्रत्येक खाते एका पूर्वनिश्चित ॲड्रेसचे आहे. यामुळे एक अधिक सोपी प्रणाली तयार होते कारण शून्य-ज्ञान पुराव्यांमध्ये व्हेरिएबल-आकाराच्या डेटा स्ट्रक्चर्स हाताळणे कठीण आहे. प्रोडक्शन-रेडी प्रणालीसाठी, आपण [मर्कल रूट](/developers/tutorials/merkle-proofs-for-offline-data-integrity/) स्टेट हॅश म्हणून वापरू शकतो आणि आवश्यक शिलकेसाठी मर्कल पुरावे देऊ शकतो. + +- मेमरी स्टोरेज. प्रोडक्शन प्रणालीवर, रीस्टार्ट झाल्यास सर्व खात्यांमधील शिल्लक जपून ठेवण्यासाठी आम्हाला त्या डिस्कवर लिहिण्याची आवश्यकता आहे. येथे, माहिती सहज गमावली तरी चालेल. + +- फक्त ट्रान्सफर. प्रोडक्शन प्रणालीला बँकेत मालमत्ता जमा करण्याचा आणि त्या काढण्याचा मार्ग आवश्यक असतो. परंतु येथे उद्देश केवळ संकल्पना स्पष्ट करणे आहे, म्हणून ही बँक केवळ ट्रान्सफरपुरती मर्यादित आहे. + +### शून्य-ज्ञान पुरावे {#zero-knowledge-proofs} + +मूलभूत स्तरावर, एक शून्य-ज्ञान पुरावा दर्शवितो की प्रोव्हरला काही डेटा, _Dataprivate_ माहित आहे, जसे की काही सार्वजनिक डेटा, _Datapublic_, आणि _Dataprivate_ यांच्यात एक संबंध _Relationship_ आहे. व्हेरिफायरला _Relationship_ आणि _Datapublic_ माहीत असते. + +गोपनीयता जपण्यासाठी, आपल्याला स्टेट्स आणि व्यवहार खाजगी ठेवण्याची गरज आहे. पण अखंडता सुनिश्चित करण्यासाठी, आम्हाला स्टेट्सचा [क्रिप्टोग्राफिक हॅश](https://en.wikipedia.org/wiki/Cryptographic_hash_function) सार्वजनिक ठेवण्याची गरज आहे. व्यवहार सबमिट करणाऱ्या लोकांना ते व्यवहार खरोखरच झाले आहेत हे सिद्ध करण्यासाठी, आम्हाला व्यवहार हॅश देखील पोस्ट करण्याची आवश्यकता आहे. + +बहुतेक प्रकरणांमध्ये, _Dataprivate_ हे शून्य-ज्ञान पुरावा प्रोग्रामसाठी इनपुट असते आणि _Datapublic_ हे आउटपुट असते. + +_Dataprivate_ मधील ही फील्ड्स: + +- _Staten_, जुनी स्टेट +- _Staten+1_, नवीन स्टेट +- _Transaction_, एक व्यवहार जो जुन्या स्टेटमधून नवीन स्टेटमध्ये बदलतो. या व्यवहारामध्ये ही फील्ड्स समाविष्ट असणे आवश्यक आहे: + - _गंतव्य ॲड्रेस_ जो ट्रान्सफर प्राप्त करतो + - ट्रान्सफर केली जाणारी _रक्कम_ + - प्रत्येक व्यवहारावर एकदाच प्रक्रिया केली जाऊ शकते हे सुनिश्चित करण्यासाठी _नॉन्स_. + स्त्रोत ॲड्रेस व्यवहारामध्ये असण्याची गरज नाही, कारण तो स्वाक्षरीतून परत मिळवता येतो. +- _स्वाक्षरी_, व्यवहार करण्यासाठी अधिकृत असलेली स्वाक्षरी. आमच्या बाबतीत, व्यवहार करण्यासाठी अधिकृत असलेला एकमेव ॲड्रेस स्त्रोत ॲड्रेस आहे. कारण आमची शून्य-ज्ञान प्रणाली ज्या प्रकारे काम करते, आम्हाला Ethereum स्वाक्षरी व्यतिरिक्त, खात्याची सार्वजनिक की देखील आवश्यक आहे. + +ही _Datapublic_ मधील फील्ड्स आहेत: + +- _Hash(Staten)_ जुन्या स्टेटचा हॅश +- _Hash(Staten+1)_ नवीन स्टेटचा हॅश +- _Hash(Transaction)_ त्या व्यवहाराचा हॅश जो स्टेटला _Staten_ मधून _Staten+1_ मध्ये बदलतो. + +संबंध अनेक अटी तपासतो: + +- सार्वजनिक हॅश खरोखरच खाजगी फील्ड्ससाठी योग्य हॅश आहेत. +- व्यवहार, जुन्या स्टेटवर लागू केल्यावर, नवीन स्टेटमध्ये परिणाम करतो. +- स्वाक्षरी व्यवहाराच्या स्त्रोत ॲड्रेसवरून येते. + +क्रिप्टोग्राफिक हॅश फंक्शन्सच्या गुणधर्मांमुळे, या अटी सिद्ध करणे अखंडता सुनिश्चित करण्यासाठी पुरेसे आहे. + +### डेटा स्ट्रक्चर्स {#data-structures} + +प्राथमिक डेटा स्ट्रक्चर सर्व्हरद्वारे धारण केलेली स्टेट आहे. प्रत्येक खात्यासाठी, सर्व्हर खात्याची शिल्लक आणि एक [नॉन्स](https://en.wikipedia.org/wiki/Cryptographic_nonce) चा मागोवा ठेवतो, जो [रिप्ले अटॅक](https://en.wikipedia.org/wiki/Replay_attack) रोखण्यासाठी वापरला जातो. + +### घटक {#components} + +या प्रणालीला दोन घटक आवश्यक आहेत: + +- _सर्व्हर_ जो व्यवहार स्वीकारतो, त्यावर प्रक्रिया करतो, आणि शून्य-ज्ञान पुराव्यांसह हॅश चेनवर पोस्ट करतो. +- एक _स्मार्ट कॉन्ट्रॅक्ट_ जो हॅश साठवतो आणि स्टेट संक्रमण वैध असल्याची खात्री करण्यासाठी शून्य-ज्ञान पुरावे सत्यापित करतो. + +### डेटा आणि नियंत्रण प्रवाह {#flows} + +एका खात्यातून दुसऱ्या खात्यात हस्तांतरण करण्यासाठी विविध घटक ज्या प्रकारे संवाद साधतात ते खालीलप्रमाणे आहेत. + +1. एक वेब ब्राउझर स्वाक्षरी केलेला व्यवहार सबमिट करतो जो स्वाक्षरीकर्त्याच्या खात्यातून वेगळ्या खात्यात हस्तांतरण करण्याची विनंती करतो. + +2. सर्व्हर सत्यापित करतो की व्यवहार वैध आहे: + + - स्वाक्षरीकर्त्याचे बँकेत पुरेशी शिल्लक असलेले खाते आहे. + - प्राप्तकर्त्याचे बँकेत एक खाते आहे. + +3. सर्व्हर स्वाक्षरीकर्त्याच्या शिलकेतून हस्तांतरित केलेली रक्कम वजा करून आणि ती प्राप्तकर्त्याच्या शिलकेत जोडून नवीन स्टेटची गणना करतो. + +4. सर्व्हर एक शून्य-ज्ञान पुरावा तयार करतो की स्टेट बदल वैध आहे. + +5. सर्व्हर Ethereum ला एक व्यवहार सबमिट करतो ज्यात समाविष्ट आहे: + + - नवीन स्टेट हॅश + - व्यवहार हॅश (जेणेकरून व्यवहार पाठवणाऱ्याला कळेल की त्यावर प्रक्रिया झाली आहे) + - शून्य-ज्ञान पुरावा जो नवीन स्टेटमध्ये संक्रमण वैध असल्याचे सिद्ध करतो + +6. स्मार्ट कॉन्ट्रॅक्ट शून्य-ज्ञान पुरावा सत्यापित करतो. + +7. जर शून्य-ज्ञान पुरावा तपासला गेला, तर स्मार्ट कॉन्ट्रॅक्ट या क्रिया करतो: + - सध्याचा स्टेट हॅश नवीन स्टेट हॅशमध्ये अपडेट करणे + - नवीन स्टेट हॅश आणि व्यवहार हॅशसह एक लॉग नोंदणी प्रसारित करणे + +### साधने {#tools} + +क्लायंट-साइड कोडसाठी, आम्ही [Vite](https://vite.dev/), [React](https://react.dev/), [Viem](https://viem.sh/), आणि [Wagmi](https://wagmi.sh/) वापरणार आहोत. ही उद्योग-मानक साधने आहेत; जर तुम्हाला त्यांच्याशी परिचय नसेल, तर तुम्ही [हे ट्यूटोरियल](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/) वापरू शकता. + +सर्व्हरचा बहुतांश भाग [Node](https://nodejs.org/en) वापरून JavaScript मध्ये लिहिलेला आहे. शून्य-ज्ञान भाग [Noir](https://noir-lang.org/) मध्ये लिहिलेला आहे. आम्हाला आवृत्ती `1.0.0-beta.10` आवश्यक आहे, म्हणून तुम्ही [निर्देशानुसार Noir इन्स्टॉल](https://noir-lang.org/docs/getting_started/quick_start) केल्यानंतर, चालवा: + +``` +noirup -v 1.0.0-beta.10 +``` + +आपण जो ब्लॉकचेन वापरतो तो `anvil` आहे, एक स्थानिक चाचणी ब्लॉकचेन जो [Foundry](https://getfoundry.sh/introduction/installation) चा भाग आहे. + +## अंमलबजावणी {#implementation} + +कारण ही एक गुंतागुंतीची प्रणाली आहे, आम्ही ती टप्प्याटप्प्याने लागू करू. + +### टप्पा १ - मॅन्युअल शून्य ज्ञान {#stage-1} + +पहिल्या टप्प्यासाठी, आम्ही ब्राउझरमध्ये एका व्यवहारावर स्वाक्षरी करू आणि नंतर मॅन्युअली शून्य-ज्ञान पुराव्याला माहिती देऊ. शून्य-ज्ञान कोडला ती माहिती `server/noir/Prover.toml` मध्ये मिळण्याची अपेक्षा असते ([येथे](https://noir-lang.org/docs/getting_started/project_breakdown#provertoml-1) दस्तऐवजीकरण केलेले). + +ते कृतीत पाहण्यासाठी: + +1. तुम्ही [Node](https://nodejs.org/en/download) आणि [Noir](https://noir-lang.org/install) इन्स्टॉल केले असल्याची खात्री करा. शक्यतो, ते macOS, Linux, किंवा [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) सारख्या UNIX प्रणालीवर इन्स्टॉल करा. + +2. स्टेज 1 कोड डाउनलोड करा आणि क्लायंट कोड सर्व्ह करण्यासाठी वेब सर्व्हर सुरू करा. + + ```sh + git clone https://github.com/qbzzt/250911-zk-bank.git -b 01-manual-zk + cd 250911-zk-bank + cd client + npm install + npm run dev + ``` + + येथे वेब सर्व्हरची गरज असण्याचे कारण म्हणजे, काही प्रकारची फसवणूक टाळण्यासाठी, अनेक वॉलेट्स (जसे की MetaMask) थेट डिस्कवरून सर्व्ह केलेल्या फाइल्स स्वीकारत नाहीत + +3. वॉलेटसह ब्राउझर उघडा. + +4. वॉलेटमध्ये, एक नवीन पासफ्रेज टाका. लक्षात घ्या की यामुळे तुमचा सध्याचा पासफ्रेज हटवला जाईल, म्हणून _तुमच्याकडे बॅकअप असल्याची खात्री करा_. + + पासफ्रेज `test test test test test test test test test test test junk` आहे, जो anvil साठी डीफॉल्ट चाचणी पासफ्रेज आहे. + +5. [क्लायंट-साइड कोड](http://localhost:5173/) वर ब्राउझ करा. + +6. वॉलेटशी कनेक्ट व्हा आणि तुमचे गंतव्य खाते आणि रक्कम निवडा. + +7. **स्वाक्षरी करा** वर क्लिक करा आणि व्यवहारावर स्वाक्षरी करा. + +8. **Prover.toml** शीर्षकाखाली तुम्हाला मजकूर मिळेल. `server/noir/Prover.toml` त्या मजकूराने बदला. + +9. शून्य-ज्ञान पुरावा कार्यान्वित करा. + + ```sh + cd ../server/noir + nargo execute + ``` + + आउटपुट यासारखे असावे + + ``` + ori@CryptoDocGuy:~/noir/250911-zk-bank/server/noir$ nargo execute + + [zkBank] Circuit witness successfully solved + [zkBank] Witness saved to target/zkBank.gz + [zkBank] Circuit output: (0x199aa62af8c1d562a6ec96e66347bf3240ab2afb5d022c895e6bf6a5e617167b, 0x0cfc0a67cb7308e4e9b254026b54204e34f6c8b041be207e64c5db77d95dd82d, 0x450cf9da6e180d6159290554ae3d8787, 0x6d8bc5a15b9037e52fb59b6b98722a85) + ``` + +10. संदेश योग्यरित्या हॅश झाला आहे की नाही हे पाहण्यासाठी वेब ब्राउझरवर दिसणाऱ्या हॅशशी शेवटच्या दोन मूल्यांची तुलना करा. + +#### `server/noir/Prover.toml` {#server-noir-prover-toml} + +[ही फाइल](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/Prover.toml) Noir द्वारे अपेक्षित माहितीचे स्वरूप दर्शवते. + +```toml +message="send 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 500 finney (milliEth) 0 " +``` + +संदेश मजकूर स्वरूपात आहे, ज्यामुळे वापरकर्त्याला समजणे सोपे होते (जे स्वाक्षरी करताना आवश्यक आहे) आणि Noir कोडला पार्स करणे सोपे होते. रक्कम फिनीमध्ये उद्धृत केली आहे जेणेकरून एकीकडे अंशात्मक हस्तांतरण सक्षम होईल आणि दुसरीकडे ते सहज वाचता येईल. शेवटची संख्या [नॉन्स](https://en.wikipedia.org/wiki/Cryptographic_nonce) आहे. + +स्ट्रिंग १०० अक्षरांची आहे. शून्य-ज्ञान पुरावे व्हेरिएबल-आकाराचा डेटा चांगल्या प्रकारे हाताळत नाहीत, त्यामुळे डेटा पॅड करणे अनेकदा आवश्यक असते. + +```toml +pubKeyX=["0x83",...,"0x75"] +pubKeyY=["0x35",...,"0xa5"] +signature=["0xb1",...,"0x0d"] +``` + +हे तीन पॅरामीटर्स निश्चित-आकाराचे बाइट ॲरे आहेत. + +```toml +[[accounts]] +address="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" +balance=100_000 +nonce=0 + +[[accounts]] +address="0x70997970C51812dc3A010C7d01b50e0d17dc79C8" +balance=100_000 +nonce=0 +``` + +स्ट्रक्चर्सचा ॲरे निर्दिष्ट करण्याचा हा मार्ग आहे. प्रत्येक नोंदीसाठी, आम्ही ॲड्रेस, शिल्लक (milliETH उर्फ [फिनी](https://cryptovalleyjournal.com/glossary/finney/)), आणि पुढील नॉन्स मूल्य निर्दिष्ट करतो. + +#### `client/src/Transfer.tsx` {#client-src-transfer-tsx} + +[ही फाइल](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/client/src/Transfer.tsx) क्लायंट-साइड प्रोसेसिंग लागू करते आणि `server/noir/Prover.toml` फाइल तयार करते (ज्यामध्ये शून्य-ज्ञान पॅरामीटर्स समाविष्ट आहेत). + +येथे अधिक मनोरंजक भागांचे स्पष्टीकरण दिले आहे. + +```tsx +export default attrs => { +``` + +हे फंक्शन `Transfer` React घटक तयार करते, जे इतर फाइल्स आयात करू शकतात. + +```tsx + const accounts = [ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", + "0x90F79bf6EB2c4f870365E785982E1f101E93b906", + "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65", + ] +``` + +हे खाते ॲड्रेस आहेत, जे `test ...` test junk` पासफ्रेजने तयार केलेले ॲड्रेस. तुम्हाला तुमचे स्वतःचे ॲड्रेस वापरायचे असल्यास, फक्त ही व्याख्या सुधारा. + +```tsx + const account = useAccount() + const wallet = createWalletClient({ + transport: custom(window.ethereum!) + }) +``` + +हे [Wagmi हुक्स](https://wagmi.sh/react/api/hooks) आम्हाला [viem](https://viem.sh/) लायब्ररी आणि वॉलेटमध्ये प्रवेश करू देतात. + +```tsx + const message = `send ${toAccount} ${ethAmount*1000} finney (milliEth) ${nonce}`.padEnd(100, " ") +``` + +हा संदेश आहे, जागांनी पॅड केलेला. प्रत्येक वेळी [`useState`](https://react.dev/reference/react/useState) व्हेरिएबल्सपैकी एक बदलतो, घटक पुन्हा काढला जातो आणि `message` अपडेट होतो. + +```tsx + const sign = async () => { +``` + +जेव्हा वापरकर्ता **स्वाक्षरी** बटणावर क्लिक करतो तेव्हा हे फंक्शन कॉल केले जाते. संदेश आपोआप अपडेट होतो, परंतु स्वाक्षरीसाठी वॉलेटमध्ये वापरकर्त्याच्या मंजुरीची आवश्यकता असते आणि गरज नसल्यास आम्ही ती विचारू इच्छित नाही. + +```tsx + const signature = await wallet.signMessage({ + account: fromAccount, + message, + }) +``` + +वॉलेटला [संदेशावर स्वाक्षरी करण्यास](https://viem.sh/docs/accounts/local/signMessage) सांगा. + +```tsx + const hash = hashMessage(message) +``` + +संदेश हॅश मिळवा. डीबगिंगसाठी (Noir कोडच्या) वापरकर्त्याला ते प्रदान करणे उपयुक्त आहे. + +```tsx + const pubKey = await recoverPublicKey({ + hash, + signature + }) +``` + +[सार्वजनिक की मिळवा](https://viem.sh/docs/utilities/recoverPublicKey). [Noir `ecrecover`](https://github.com/colinnielsen/ecrecover-noir) फंक्शनसाठी हे आवश्यक आहे. + +```tsx + setSignature(signature) + setHash(hash) + setPubKey(pubKey) +``` + +स्टेट व्हेरिएबल्स सेट करा. हे केल्याने घटक पुन्हा काढला जातो (`sign` फंक्शन बाहेर पडल्यानंतर) आणि वापरकर्त्याला अपडेट केलेली मूल्ये दर्शवितो. + +```tsx + let proverToml = ` +``` + +`Prover.toml` साठी मजकूर. + +```tsx +message="${message}" + +pubKeyX=${hexToArray(pubKey.slice(4,4+2*32))} +pubKeyY=${hexToArray(pubKey.slice(4+2*32))} +``` + +Viem आम्हाला 65-बाइट हेक्साडेसिमल स्ट्रिंग म्हणून सार्वजनिक की प्रदान करते. पहिला बाइट `0x04` आहे, एक आवृत्ती मार्कर. यानंतर सार्वजनिक कीच्या `x` साठी 32 बाइट्स आणि नंतर सार्वजनिक कीच्या `y` साठी 32 बाइट्स येतात. + +तथापि, Noir ला ही माहिती दोन-बाइट ॲरे म्हणून मिळण्याची अपेक्षा आहे, एक `x` साठी आणि एक `y` साठी. शून्य-ज्ञान पुराव्याचा भाग म्हणून पार्स करण्यापेक्षा येथे क्लायंटवर पार्स करणे सोपे आहे. + +लक्षात घ्या की ही सर्वसाधारणपणे शून्य-ज्ञानामध्ये एक चांगली प्रथा आहे. शून्य-ज्ञान पुराव्याच्या आतील कोड महाग असतो, त्यामुळे शून्य-ज्ञान पुराव्याच्या बाहेर करता येणारे कोणतेही प्रोसेसिंग शून्य-ज्ञान पुराव्याच्या बाहेरच _केले पाहिजे_. + +```tsx +signature=${hexToArray(signature.slice(2,-2))} +``` + +स्वाक्षरी देखील 65-बाइट हेक्साडेसिमल स्ट्रिंग म्हणून प्रदान केली जाते. तथापि, शेवटचा बाइट फक्त सार्वजनिक की पुनर्प्राप्त करण्यासाठी आवश्यक आहे. सार्वजनिक की आधीच Noir कोडला प्रदान केली जाईल, त्यामुळे आम्हाला स्वाक्षरी सत्यापित करण्यासाठी त्याची आवश्यकता नाही आणि Noir कोडला त्याची आवश्यकता नाही. + +```tsx +${accounts.map(accountInProverToml).reduce((a,b) => a+b, "")} +` +``` + +खाते प्रदान करा. + +```tsx + setProverToml(proverToml) + } + + return ( + <> +

Transfer

+``` + +हे घटकाचे HTML (अधिक अचूकपणे, [JSX](https://react.dev/learn/writing-markup-with-jsx)) स्वरूप आहे. + +#### `server/noir/src/main.nr` {#server-noir-src-main-nr} + +[ही फाइल](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/src/main.nr) वास्तविक शून्य-ज्ञान कोड आहे. + +``` +use std::hash::pedersen_hash; +``` + +[पेडरसेन हॅश](https://rya-sge.github.io/access-denied/2024/05/07/pedersen-hash-function/) [Noir मानक लायब्ररी](https://noir-lang.org/docs/noir/standard_library/cryptographic_primitives/hashes#pedersen_hash) सह प्रदान केले आहे. शून्य-ज्ञान पुरावे सामान्यतः हे हॅश फंक्शन वापरतात. मानक हॅश फंक्शन्सच्या तुलनेत [अंकगणित सर्किट्स](https://rareskills.io/post/arithmetic-circuit) मध्ये गणना करणे खूप सोपे आहे. + +``` +use keccak256::keccak256; +use dep::ecrecover; +``` + +ही दोन फंक्शन्स बाह्य लायब्ररी आहेत, जी [`Nargo.toml`](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/Nargo.toml) मध्ये परिभाषित आहेत. त्यांची नावे जशी आहेत तशीच त्यांची कार्ये आहेत, एक फंक्शन जे [keccak256 हॅश](https://emn178.github.io/online-tools/keccak_256.html) ची गणना करते आणि एक फंक्शन जे Ethereum स्वाक्षरी सत्यापित करते आणि स्वाक्षरीकर्त्याचा Ethereum ॲड्रेस पुनर्प्राप्त करते. + +``` +global ACCOUNT_NUMBER : u32 = 5; +``` + +Noir [Rust](https://www.rust-lang.org/) पासून प्रेरित आहे. व्हेरिएबल्स, डीफॉल्टनुसार, स्थिर असतात. अशाप्रकारे आम्ही जागतिक कॉन्फिगरेशन स्थिरांक परिभाषित करतो. विशेषतः, `ACCOUNT_NUMBER` ही आम्ही संग्रहित करत असलेल्या खात्यांची संख्या आहे. + +`u` नावाचे डेटा प्रकार त्या संख्येचे बिट्स, अनसाईन्ड आहेत. समर्थित प्रकार फक्त `u8`, `u16`, `u32`, `u64`, आणि `u128` आहेत. + +``` +global FLAT_ACCOUNT_FIELDS : u32 = 2; +``` + +हे व्हेरिएबल खात्यांच्या पेडरसेन हॅशसाठी वापरले जाते, जसे खाली स्पष्ट केले आहे. + +``` +global MESSAGE_LENGTH : u32 = 100; +``` + +वर स्पष्ट केल्याप्रमाणे, संदेशाची लांबी निश्चित आहे. ते येथे निर्दिष्ट केले आहे. + +``` +global ASCII_MESSAGE_LENGTH : [u8; 3] = [0x31, 0x30, 0x30]; +global HASH_BUFFER_SIZE : u32 = 26+3+MESSAGE_LENGTH; +``` + +[EIP-191 स्वाक्षऱ्यां](https://eips.ethereum.org/EIPS/eip-191)ना 26-बाइटच्या प्रिफिक्ससह बफर आवश्यक आहे, त्यानंतर ASCII मध्ये संदेशाची लांबी, आणि शेवटी संदेश स्वतः. + +``` +struct Account { + balance: u128, + address: Field, + nonce: u32, +} +``` + +आम्ही एका खात्याबद्दल जी माहिती संग्रहित करतो. [`Field`](https://noir-lang.org/docs/noir/concepts/data_types/fields) ही एक संख्या आहे, जी साधारणपणे 253 बिट्सपर्यंत असते, जी थेट [अंकगणित सर्किट](https://rareskills.io/post/arithmetic-circuit) मध्ये वापरली जाऊ शकते जे शून्य-ज्ञान पुरावा लागू करते. येथे आपण 160-बिट Ethereum ॲड्रेस संग्रहित करण्यासाठी `Field` वापरतो. + +``` +struct TransferTxn { + from: Field, + to: Field, + amount: u128, + nonce: u32 +} +``` + +हस्तांतरण व्यवहारासाठी आम्ही संग्रहित करत असलेली माहिती. + +``` +fn flatten_account(account: Account) -> [Field; FLAT_ACCOUNT_FIELDS] { +``` + +एक फंक्शनची व्याख्या. पॅरामीटर `Account` माहिती आहे. परिणाम `Field` व्हेरिएबल्सचा ॲरे आहे, ज्याची लांबी `FLAT_ACCOUNT_FIELDS` आहे. + +``` + let flat = [ + account.address, + ((account.balance << 32) + account.nonce.into()).into(), + ]; +``` + +ॲरेमधील पहिले मूल्य खाते ॲड्रेस आहे. दुसऱ्यामध्ये शिल्लक आणि नॉन्स दोन्ही समाविष्ट आहेत. `.into()` कॉल एका संख्येला तिच्या आवश्यक डेटा प्रकारात बदलतात. `account.nonce` हे `u32` मूल्य आहे, परंतु `account.balance « 32`, जे `u128` मूल्य आहे, त्यात जोडण्यासाठी ते `u128` असणे आवश्यक आहे. ते पहिले `.into()` आहे. दुसरे `u128` परिणामाला `Field` मध्ये रूपांतरित करते जेणेकरून ते ॲरेमध्ये बसेल. + +``` + flat +} +``` + +Noir मध्ये, फंक्शन्स फक्त शेवटी एक मूल्य परत करू शकतात (लवकर परतीचा पर्याय नाही). परतीचे मूल्य निर्दिष्ट करण्यासाठी, आपण ते फंक्शनच्या बंद कंसाच्या अगदी आधी मूल्यांकित करता. + +``` +fn flatten_accounts(accounts: [Account; ACCOUNT_NUMBER]) -> [Field; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER] { +``` + +हे फंक्शन खात्यांच्या ॲरेला `Field` ॲरेमध्ये बदलते, जे पीटरसन हॅशच्या इनपुट म्हणून वापरले जाऊ शकते. + +``` + let mut flat: [Field; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER] = [0; FLAT_ACCOUNT_FIELDS*ACCOUNT_NUMBER]; +``` + +अशाप्रकारे आपण एक म्युटेबल व्हेरिएबल निर्दिष्ट करतो, म्हणजे, _स्थिर नाही_. Noir मधील व्हेरिएबल्सचे मूल्य नेहमीच असणे आवश्यक आहे, म्हणून आम्ही या व्हेरिएबलला सर्व शून्यांनी सुरू करतो. + +``` + for i in 0..ACCOUNT_NUMBER { +``` + +हे एक `for` लूप आहे. लक्षात घ्या की सीमा स्थिर आहेत. Noir लूप्सच्या सीमा संकलनाच्या वेळी ज्ञात असणे आवश्यक आहे. याचे कारण म्हणजे अंकगणित सर्किट्स फ्लो कंट्रोलला समर्थन देत नाहीत. `for` लूपची प्रक्रिया करताना, कंपाइलर त्यातील कोडला अनेक वेळा ठेवतो, प्रत्येक पुनरावृत्तीसाठी एकदा. + +``` + let fields = flatten_account(accounts[i]); + for j in 0..FLAT_ACCOUNT_FIELDS { + flat[i*FLAT_ACCOUNT_FIELDS + j] = fields[j]; + } + } + + flat +} + +fn hash_accounts(accounts: [Account; ACCOUNT_NUMBER]) -> Field { + pedersen_hash(flatten_accounts(accounts)) +} +``` + +शेवटी, आम्ही खात्यांच्या ॲरेला हॅश करणाऱ्या फंक्शनवर पोहोचलो. + +``` +fn find_account(accounts: [Account; ACCOUNT_NUMBER], address: Field) -> u32 { + let mut account : u32 = ACCOUNT_NUMBER; + + for i in 0..ACCOUNT_NUMBER { + if accounts[i].address == address { + account = i; + } + } + +``` + +हे फंक्शन विशिष्ट ॲड्रेस असलेले खाते शोधते. हे फंक्शन मानक कोडमध्ये अत्यंत अकार्यक्षम असेल कारण ते ॲड्रेस सापडल्यानंतरही सर्व खात्यांवर पुनरावृत्ती करते. + +तथापि, शून्य-ज्ञान पुराव्यांमध्ये कोणतेही प्रवाह नियंत्रण नसते. जर आपल्याला एखादी अट तपासायची असेल, तर ती प्रत्येक वेळी तपासावी लागेल. + +`if` विधानांसोबतही असेच काहीसे घडते. वरील लूपमधील `if` विधानाचे या गणितीय विधानांमध्ये भाषांतर केले जाते. + +_conditionresult = accounts[i].address == address_ // समान असल्यास एक, अन्यथा शून्य + +_accountnew = conditionresult\*i + (1-conditionresult)\*accountold_ + +```rust + assert (account < ACCOUNT_NUMBER, f"{address} does not have an account"); + + account +} +``` + +[`assert`](https://noir-lang.org/docs/dev/noir/concepts/assert) फंक्शनमुळे दावा खोटा असल्यास शून्य-ज्ञान पुरावा क्रॅश होतो. या प्रकरणात, जर आपल्याला संबंधित ॲड्रेस असलेले खाते सापडले नाही तर. ॲड्रेसची तक्रार करण्यासाठी, आम्ही [फॉर्मॅट स्ट्रिंग](https://noir-lang.org/docs/noir/concepts/data_types/strings#format-strings) वापरतो. + +```rust +fn apply_transfer_txn(accounts: [Account; ACCOUNT_NUMBER], txn: TransferTxn) -> [Account; ACCOUNT_NUMBER] { +``` + +हे फंक्शन हस्तांतरण व्यवहार लागू करते आणि नवीन खात्यांचा ॲरे परत करते. + +```rust + let from = find_account(accounts, txn.from); + let to = find_account(accounts, txn.to); + + let (txnFrom, txnAmount, txnNonce, accountNonce) = + (txn.from, txn.amount, txn.nonce, accounts[from].nonce); +``` + +आम्ही Noir मध्ये स्वरूप स्ट्रिंगमध्ये संरचना घटकांमध्ये प्रवेश करू शकत नाही, म्हणून आम्ही एक वापरण्यायोग्य प्रत तयार करतो. + +```rust + assert (accounts[from].balance >= txn.amount, + f"{txnFrom} does not have {txnAmount} finney"); + + assert (accounts[from].nonce == txn.nonce, + f"Transaction has nonce {txnNonce}, but the account is expected to use {accountNonce}"); +``` + +या दोन अटी आहेत ज्या व्यवहार अवैध करू शकतात. + +```rust + let mut newAccounts = accounts; + + newAccounts[from].balance -= txn.amount; + newAccounts[from].nonce += 1; + newAccounts[to].balance += txn.amount; + + newAccounts +} +``` + +नवीन खात्यांचा ॲरे तयार करा आणि नंतर तो परत करा. + +```rust +fn readAddress(messageBytes: [u8; MESSAGE_LENGTH]) -> Field +``` + +हे फंक्शन संदेशातून ॲड्रेस वाचते. + +```rust +{ + let mut result : Field = 0; + + for i in 7..47 { +``` + +ॲड्रेस नेहमी 20 बाइट्स (उर्फ 40 हेक्साडेसिमल अंक) लांब असतो आणि वर्ण #7 पासून सुरू होतो. + +```rust + result *= 0x10; + if messageBytes[i] >= 48 & messageBytes[i] <= 57 { // 0-9 + result += (messageBytes[i]-48).into(); + } + if messageBytes[i] >= 65 & messageBytes[i] <= 70 { // A-F + result += (messageBytes[i]-65+10).into() + } + if messageBytes[i] >= 97 & messageBytes[i] <= 102 { // a-f + result += (messageBytes[i]-97+10).into() + } + } + + result +} + +fn readAmountAndNonce(messageBytes: [u8; MESSAGE_LENGTH]) -> (u128, u32) +``` + +संदेशातून रक्कम आणि नॉन्स वाचा. + +```rust +{ + let mut amount : u128 = 0; + let mut nonce: u32 = 0; + let mut stillReadingAmount: bool = true; + let mut lookingForNonce: bool = false; + let mut stillReadingNonce: bool = false; +``` + +संदेशात, ॲड्रेस नंतरची पहिली संख्या फिनीची रक्कम आहे (उर्फ हस्तांतरण करण्यासाठी ETH चा हजारावा भाग). दुसरी संख्या नॉन्स आहे. त्यांच्यामधील कोणत्याही मजकूराकडे दुर्लक्ष केले जाते. + +```rust + for i in 48..MESSAGE_LENGTH { + if messageBytes[i] >= 48 & messageBytes[i] <= 57 { // 0-9 + let digit = (messageBytes[i]-48); + + if stillReadingAmount { + amount = amount*10 + digit.into(); + } + + if lookingForNonce { // We just found it + stillReadingNonce = true; + lookingForNonce = false; + } + + if stillReadingNonce { + nonce = nonce*10 + digit.into(); + } + } else { + if stillReadingAmount { + stillReadingAmount = false; + lookingForNonce = true; + } + if stillReadingNonce { + stillReadingNonce = false; + } + } + } + + (amount, nonce) +} +``` + +[ट्यूपल](https://noir-lang.org/docs/noir/concepts/data_types/tuples) परत करणे हा Noir मध्ये फंक्शनमधून अनेक मूल्ये परत करण्याचा मार्ग आहे. + +```rust +fn readTransferTxn(message: str) -> TransferTxn +{ + let mut txn: TransferTxn = TransferTxn { from: 0, to: 0, amount:0, nonce:0 }; + let messageBytes = message.as_bytes(); + + txn.to = readAddress(messageBytes); + let (amount, nonce) = readAmountAndNonce(messageBytes); + txn.amount = amount; + txn.nonce = nonce; + + txn +} +``` + +हे फंक्शन संदेशाला बाइट्समध्ये रूपांतरित करते, नंतर रकमांना `TransferTxn` मध्ये रूपांतरित करते. + +```rust +// Viem च्या hashMessage च्या समतुल्य +// https://viem.sh/docs/utilities/hashMessage#hashmessage +fn hashMessage(message: str) -> [u8;32] { +``` + +आम्ही खात्यांसाठी पेडरसेन हॅश वापरू शकलो कारण ते फक्त शून्य-ज्ञान पुराव्याच्या आत हॅश केले जातात. तथापि, या कोडमध्ये आपल्याला संदेशाची स्वाक्षरी तपासावी लागेल, जी ब्राउझरद्वारे तयार केली जाते. त्यासाठी, आम्हाला [EIP 191](https://eips.ethereum.org/EIPS/eip-191) मधील Ethereum स्वाक्षरी स्वरूपाचे पालन करणे आवश्यक आहे. याचा अर्थ असा की आम्हाला एका मानक प्रिफिक्ससह एक संयुक्त बफर तयार करणे आवश्यक आहे, ASCII मध्ये संदेशाची लांबी, आणि संदेश स्वतः, आणि ते हॅश करण्यासाठी Ethereum मानक keccak256 वापरणे. + +```rust + // ASCII प्रिफिक्स + let prefix_bytes = [ + 0x19, // \x19 + 0x45, // 'E' + 0x74, // 't' + 0x68, // 'h' + 0x65, // 'e' + 0x72, // 'r' + 0x65, // 'e' + 0x75, // 'u' + 0x6D, // 'm' + 0x20, // ' ' + 0x53, // 'S' + 0x69, // 'i' + 0x67, // 'g' + 0x6E, // 'n' + 0x65, // 'e' + 0x64, // 'd' + 0x20, // ' ' + 0x4D, // 'M' + 0x65, // 'e' + 0x73, // 's' + 0x73, // 's' + 0x61, // 'a' + 0x67, // 'g' + 0x65, // 'e' + 0x3A, // ':' + 0x0A // '\n' + ]; +``` + +जेव्हा एखादे ॲप्लिकेशन वापरकर्त्याला असा संदेश स्वाक्षरी करण्यास सांगते जो व्यवहार म्हणून किंवा इतर कोणत्याही हेतूसाठी वापरला जाऊ शकतो अशा प्रकरणांना टाळण्यासाठी, EIP 191 निर्दिष्ट करते की सर्व स्वाक्षरी केलेले संदेश वर्ण 0x19 (वैध ASCII वर्ण नाही) ने सुरू होतात, त्यानंतर `Ethereum Signed Message:` आणि एक नवीन ओळ येते. + +```rust + let mut buffer: [u8; HASH_BUFFER_SIZE] = [0u8; HASH_BUFFER_SIZE]; + for i in 0..26 { + buffer[i] = prefix_bytes[i]; + } + + let messageBytes : [u8; MESSAGE_LENGTH] = message.as_bytes(); + + if MESSAGE_LENGTH <= 9 { + for i in 0..1 { + buffer[i+26] = ASCII_MESSAGE_LENGTH[i]; + } + + for i in 0..MESSAGE_LENGTH { + buffer[i+26+1] = messageBytes[i]; + } + } + + if MESSAGE_LENGTH >= 10 & MESSAGE_LENGTH <= 99 { + for i in 0..2 { + buffer[i+26] = ASCII_MESSAGE_LENGTH[i]; + } + + for i in 0..MESSAGE_LENGTH { + buffer[i+26+2] = messageBytes[i]; + } + } + + if MESSAGE_LENGTH >= 100 { + for i in 0..3 { + buffer[i+26] = ASCII_MESSAGE_LENGTH[i]; + } + + for i in 0..MESSAGE_LENGTH { + buffer[i+26+3] = messageBytes[i]; + } + } + + assert(MESSAGE_LENGTH < 1000, "Messages whose length is over three digits are not supported"); +``` + +संदेश लांबी 999 पर्यंत हाताळा आणि जर ती जास्त असेल तर अयशस्वी व्हा. मी हा कोड जोडला आहे, जरी संदेशाची लांबी स्थिर असली तरी, कारण तो बदलणे सोपे करते. उत्पादन प्रणालीवर, तुम्ही कदाचित चांगल्या कामगिरीसाठी `MESSAGE_LENGTH` बदलत नाही असे गृहीत धराल. + +```rust + keccak256::keccak256(buffer, HASH_BUFFER_SIZE) +} +``` + +Ethereum मानक `keccak256` फंक्शन वापरा. + +```rust +fn signatureToAddressAndHash( + message: str, + pubKeyX: [u8; 32], + pubKeyY: [u8; 32], + signature: [u8; 64] + ) -> (Field, Field, Field) // ॲड्रेस, हॅशचे पहिले 16 बाइट्स, हॅशचे शेवटचे 16 बाइट्स +{ +``` + +हे फंक्शन स्वाक्षरी सत्यापित करते, ज्यासाठी संदेश हॅश आवश्यक आहे. नंतर ते आपल्याला स्वाक्षरी केलेला ॲड्रेस आणि संदेश हॅश प्रदान करते. संदेश हॅश दोन `Field` मूल्यांमध्ये पुरवला जातो कारण बाइट ॲरेपेक्षा कार्यक्रमाच्या उर्वरित भागात वापरणे सोपे आहे. + +आम्हाला दोन `Field` मूल्ये वापरण्याची आवश्यकता आहे कारण फील्डची गणना मोठ्या संख्येने [मॉड्युलो](https://en.wikipedia.org/wiki/Modulo) केली जाते, परंतु ती संख्या सामान्यतः 256 बिटपेक्षा कमी असते (अन्यथा EVM मध्ये ती गणना करणे कठीण होईल). + +```rust + let hash = hashMessage(message); + + let mut (hash1, hash2) = (0,0); + + for i in 0..16 { + hash1 = hash1*256 + hash[31-i].into(); + hash2 = hash2*256 + hash[15-i].into(); + } +``` + +`hash1` आणि `hash2` ला बदलण्यायोग्य व्हेरिएबल्स म्हणून निर्दिष्ट करा आणि त्यांच्यामध्ये हॅश बाइट बाय बाइट लिहा. + +```rust + ( + ecrecover::ecrecover(pubKeyX, pubKeyY, signature, hash), +``` + +हे [Solidity च्या `ecrecover`](https://docs.soliditylang.org/en/v0.8.30/cheatsheet.html#mathematical-and-cryptographic-functions) सारखेच आहे, पण त्यात दोन महत्त्वाचे फरक आहेत: + +- जर स्वाक्षरी वैध नसेल, तर कॉल `assert` अयशस्वी करतो आणि प्रोग्राम रद्द केला जातो. +- जरी स्वाक्षरी आणि हॅशमधून सार्वजनिक की पुनर्प्राप्त केली जाऊ शकते, तरीही ही प्रक्रिया बाह्यरित्या केली जाऊ शकते आणि म्हणूनच, शून्य-ज्ञान पुराव्याच्या आत करणे योग्य नाही. जर कोणी येथे आम्हाला फसवण्याचा प्रयत्न केला, तर स्वाक्षरी पडताळणी अयशस्वी होईल. + +```rust + hash1, + hash2 + ) +} + +fn main( + accounts: [Account; ACCOUNT_NUMBER], + message: str, + pubKeyX: [u8; 32], + pubKeyY: [u8; 32], + signature: [u8; 64], + ) -> pub ( + Field, // जुन्या खात्यांच्या ॲरेचा हॅश + Field, // नवीन खात्यांच्या ॲरेचा हॅश + Field, // संदेश हॅशचे पहिले 16 बाइट्स + Field, // संदेश हॅशचे शेवटचे 16 बाइट्स + ) +``` + +शेवटी, आपण `main` फंक्शनवर पोहोचतो. आम्हाला हे सिद्ध करावे लागेल की आमच्याकडे असा व्यवहार आहे जो खात्यांच्या हॅशला जुन्या मूल्यातून नवीन मूल्यात वैधपणे बदलतो. आम्हाला हे देखील सिद्ध करावे लागेल की त्याचा हा विशिष्ट व्यवहार हॅश आहे जेणेकरून पाठवणाऱ्याला कळेल की त्यांच्या व्यवहारावर प्रक्रिया झाली आहे. + +```rust +{ + let mut txn = readTransferTxn(message); +``` + +आम्हाला `txn` बदलण्यायोग्य असणे आवश्यक आहे कारण आम्ही संदेशातून ॲड्रेस वाचत नाही, आम्ही ते स्वाक्षरीतून वाचतो. + +```rust + let (fromAddress, txnHash1, txnHash2) = signatureToAddressAndHash( + message, + pubKeyX, + pubKeyY, + signature); + + txn.from = fromAddress; + + let newAccounts = apply_transfer_txn(accounts, txn); + + ( + hash_accounts(accounts), + hash_accounts(newAccounts), + txnHash1, + txnHash2 + ) +} +``` + +### टप्पा 2 - एक सर्व्हर जोडणे {#stage-2} + +दुसऱ्या टप्प्यात, आम्ही एक सर्व्हर जोडतो जो ब्राउझरकडून हस्तांतरण व्यवहार प्राप्त करतो आणि अंमलात आणतो. + +ते कृतीत पाहण्यासाठी: + +1. Vite चालू असल्यास थांबवा. + +2. सर्व्हर समाविष्ट असलेली शाखा डाउनलोड करा आणि तुमच्याकडे सर्व आवश्यक मॉड्यूल्स असल्याची खात्री करा. + + ```sh + git checkout 02-add-server + cd client + npm install + cd ../server + npm install + ``` + + Noir कोड संकलित करण्याची गरज नाही, तो तुम्ही टप्पा 1 साठी वापरलेल्या कोडसारखाच आहे. + +3. सर्व्हर सुरू करा. + + ```sh + npm run start + ``` + +4. एका वेगळ्या कमांड-लाइन विंडोमध्ये, ब्राउझर कोड सर्व्ह करण्यासाठी Vite चालवा. + + ```sh + cd client + npm run dev + ``` + +5. [http://localhost:5173](http://localhost:5173) वर क्लायंट कोडवर ब्राउझ करा + +6. तुम्ही व्यवहार जारी करण्यापूर्वी, तुम्हाला नॉन्स, तसेच तुम्ही पाठवू शकणारी रक्कम माहित असणे आवश्यक आहे. ही माहिती मिळवण्यासाठी, **खाते डेटा अपडेट करा** वर क्लिक करा आणि संदेशावर स्वाक्षरी करा. + + येथे आपल्यासमोर एक द्विधा मनःस्थिती आहे. एकीकडे, आम्ही असा संदेश स्वाक्षरी करू इच्छित नाही जो पुन्हा वापरला जाऊ शकतो ([रिप्ले अटॅक](https://en.wikipedia.org/wiki/Replay_attack)), म्हणूनच आम्हाला प्रथम नॉन्स हवा आहे. तथापि, आमच्याकडे अद्याप नॉन्स नाही. यावरील उपाय म्हणजे असा नॉन्स निवडणे जो एकदाच वापरला जाऊ शकतो आणि जो आपल्याकडे दोन्ही बाजूंनी आधीच आहे, जसे की सध्याची वेळ. + + या उपायामधील समस्या ही आहे की वेळ कदाचित पूर्णपणे समक्रमित नसेल. त्याऐवजी, आम्ही दर मिनिटाला बदलणाऱ्या मूल्यावर स्वाक्षरी करतो. याचा अर्थ असा की रिप्ले हल्ल्यांना आपली असुरक्षिततेची खिडकी जास्तीत जास्त एक मिनिटाची आहे. उत्पादनामध्ये स्वाक्षरी केलेली विनंती TLS द्वारे संरक्षित केली जाईल, आणि बोगद्याच्या दुसऱ्या बाजूला---सर्व्हर---आधीच शिल्लक आणि नॉन्स उघड करू शकतो (त्याला काम करण्यासाठी ते माहित असणे आवश्यक आहे) हे लक्षात घेता, हा एक स्वीकार्य धोका आहे. + +7. एकदा ब्राउझरला शिल्लक आणि नॉन्स परत मिळाल्यावर, ते हस्तांतरण फॉर्म दर्शवते. गंतव्य ॲड्रेस आणि रक्कम निवडा आणि **हस्तांतरण करा** वर क्लिक करा. या विनंतीवर स्वाक्षरी करा. + +8. हस्तांतरण पाहण्यासाठी, एकतर **खाते डेटा अपडेट करा** किंवा तुम्ही सर्व्हर चालवत असलेल्या विंडोमध्ये पहा. सर्व्हर प्रत्येक वेळी बदलल्यावर स्थिती लॉग करतो. + + ``` + ori@CryptoDocGuy:~/x/250911-zk-bank/server$ npm run start + + > server@1.0.0 start + > node --experimental-json-modules index.mjs + + Listening on port 3000 + Txn send 0x90F79bf6EB2c4f870365E785982E1f101E93b906 36000 finney (milliEth) 0 processed + New state: + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 64000 (1) + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 100000 (0) + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) + 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 136000 (0) + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) + Txn send 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 7200 finney (milliEth) 1 processed + New state: + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 56800 (2) + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 107200 (0) + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) + 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 136000 (0) + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) + Txn send 0x90F79bf6EB2c4f870365E785982E1f101E93b906 3000 finney (milliEth) 2 processed + New state: + 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 has 53800 (3) + 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 has 107200 (0) + 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC has 100000 (0) + 0x90F79bf6EB2c4f870365E785982E1f101E93b906 has 139000 (0) + 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 has 100000 (0) + ``` + +#### `server/index.mjs` {#server-index-mjs-1} + +[ही फाइल](https://github.com/qbzzt/250911-zk-bank/blob/02-add-server/server/index.mjs) मध्ये सर्व्हर प्रक्रिया आहे, आणि ती [`main.nr`](https://github.com/qbzzt/250911-zk-bank/blob/02-add-server/server/noir/src/main.nr) येथील Noir कोडसह संवाद साधते. येथे मनोरंजक भागांचे स्पष्टीकरण आहे. + +```js +import { Noir } from '@noir-lang/noir_js' +``` + +[noir.js](https://www.npmjs.com/package/@noir-lang/noir_js) लायब्ररी JavaScript कोड आणि Noir कोड दरम्यान संवाद साधते. + +```js +const circuit = JSON.parse(await fs.readFile("./noir/target/zkBank.json")) +const noir = new Noir(circuit) +``` + +अंकगणित सर्किट लोड करा---मागील टप्प्यात आपण तयार केलेला संकलित Noir प्रोग्राम---आणि ते कार्यान्वित करण्याची तयारी करा. + +```js +// आम्ही फक्त स्वाक्षरी केलेल्या विनंतीच्या बदल्यात खाते माहिती प्रदान करतो +const accountInformation = async signature => { + const fromAddress = await recoverAddress({ + hash: hashMessage("Get account data " + Math.floor((new Date().getTime())/60000)), + signature + }) +``` + +खाते माहिती प्रदान करण्यासाठी, आम्हाला फक्त स्वाक्षरीची आवश्यकता आहे. कारण संदेश काय असणार आहे हे आम्हाला आधीच माहित आहे, आणि म्हणून संदेश हॅश देखील. + +```js +const processMessage = async (message, signature) => { +``` + +एका संदेशावर प्रक्रिया करा आणि त्यात एन्कोड केलेला व्यवहार कार्यान्वित करा. + +```js + // Get the public key + const pubKey = await recoverPublicKey({ + hash, + signature + }) +``` + +आता आम्ही सर्व्हरवर JavaScript चालवत असल्याने, आम्ही सार्वजनिक की क्लायंटऐवजी तेथे पुनर्प्राप्त करू शकतो. + +```js + let noirResult + try { + noirResult = await noir.execute({ + message, + signature: signature.slice(2,-2).match(/.{2}/g).map(x => `0x${x}`), + pubKeyX, + pubKeyY, + accounts: Accounts + }) +``` + +`noir.execute` Noir प्रोग्राम चालवते. पॅरामीटर्स [`Prover.toml`](https://github.com/qbzzt/250911-zk-bank/blob/01-manual-zk/server/noir/Prover.toml) मध्ये प्रदान केलेल्या पॅरामीटर्सच्या समतुल्य आहेत. लक्षात घ्या की लांब मूल्ये हेक्साडेसिमल स्ट्रिंगच्या ॲरे म्हणून (`["0x60", "0xA7"]`) प्रदान केली जातात, एकल हेक्साडेसिमल मूल्य (`0x60A7`) म्हणून नाही, जसे Viem करते. + +```js + } catch (err) { + console.log(`Noir error: ${err}`) + throw Error("Invalid transaction, not processed") + } +``` + +जर काही त्रुटी असेल, तर ती पकडा आणि नंतर क्लायंटला एक सरलीकृत आवृत्ती रिले करा. + +```js + Accounts[fromAccountNumber].nonce++ + Accounts[fromAccountNumber].balance -= amount + Accounts[toAccountNumber].balance += amount +``` + +व्यवहार लागू करा. आम्ही ते Noir कोडमध्ये आधीच केले आहे, परंतु तेथून परिणाम काढण्याऐवजी येथे पुन्हा करणे सोपे आहे. + +```js +let Accounts = [ + { + address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + balance: 5000, + nonce: 0, + }, +``` + +प्रारंभिक `Accounts` रचना. + +### टप्पा 3 - Ethereum स्मार्ट कॉन्ट्रॅक्ट्स {#stage-3} + +1. सर्व्हर आणि क्लायंट प्रक्रिया थांबवा. + +2. स्मार्ट कॉन्ट्रॅक्ट्स असलेली शाखा डाउनलोड करा आणि तुमच्याकडे सर्व आवश्यक मॉड्यूल्स असल्याची खात्री करा. + + ```sh + git checkout 03-smart-contracts + cd client + npm install + cd ../server + npm install + ``` + +3. एका वेगळ्या कमांड-लाइन विंडोमध्ये `anvil` चालवा. + +4. पडताळणी की आणि सॉलिडिटी व्हेरिफायर तयार करा, नंतर व्हेरिफायर कोड सॉलिडिटी प्रोजेक्टमध्ये कॉपी करा. + + ```sh + cd noir + bb write_vk -b ./target/zkBank.json -o ./target --oracle_hash keccak + bb write_solidity_verifier -k ./target/vk -o ./target/Verifier.sol + cp target/Verifier.sol ../../smart-contracts/src + ``` + +5. स्मार्ट कॉन्ट्रॅक्ट्सवर जा आणि `anvil` ब्लॉकचेन वापरण्यासाठी पर्यावरण व्हेरिएबल्स सेट करा. + + ```sh + cd ../../smart-contracts + export ETH_RPC_URL=http://localhost:8545 + ETH_PRIVATE_KEY=ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 + ``` + +6. `Verifier.sol` तैनात करा आणि ॲड्रेस एका पर्यावरण व्हेरिएबलमध्ये संग्रहित करा. + + ```sh + VERIFIER_ADDRESS=`forge create src/Verifier.sol:HonkVerifier --private-key $ETH_PRIVATE_KEY --optimize --broadcast | awk '/Deployed to:/ {print $3}'` + echo $VERIFIER_ADDRESS + ``` + +7. `ZkBank` कॉन्ट्रॅक्ट तैनात करा. + + ```sh + ZKBANK_ADDRESS=`forge create ZkBank --private-key $ETH_PRIVATE_KEY --broadcast --constructor-args $VERIFIER_ADDRESS 0x199aa62af8c1d562a6ec96e66347bf3240ab2afb5d022c895e6bf6a5e617167b | awk '/Deployed to:/ {print $3}'` + echo $ZKBANK_ADDRESS + ``` + + `0x199..67b` मूल्य `Accounts` च्या प्रारंभिक स्थितीचा पेडरसन हॅश आहे. जर तुम्ही `server/index.mjs` मध्ये ही प्रारंभिक स्थिती बदलली, तर तुम्ही शून्य-ज्ञान पुराव्याद्वारे नोंदवलेला प्रारंभिक हॅश पाहण्यासाठी व्यवहार चालवू शकता. + +8. सर्व्हर चालवा. + + ```sh + cd ../server + npm run start + ``` + +9. एका वेगळ्या कमांड-लाइन विंडोमध्ये क्लायंट चालवा. + + ```sh + cd client + npm run dev + ``` + +10. काही व्यवहार चालवा. + +11. स्थिती ऑनचेन बदलली आहे हे सत्यापित करण्यासाठी, सर्व्हर प्रक्रिया पुन्हा सुरू करा. पहा की `ZkBank` आता व्यवहार स्वीकारत नाही, कारण व्यवहारांमधील मूळ हॅश मूल्य ऑनचेन संग्रहित हॅश मूल्यापेक्षा वेगळे आहे. + + ही अपेक्षित प्रकारची त्रुटी आहे. + + ``` + ori@CryptoDocGuy:~/x/250911-zk-bank/server$ npm run start + + > server@1.0.0 start + > node --experimental-json-modules index.mjs + + Listening on port 3000 + Verification error: ContractFunctionExecutionError: The contract function "processTransaction" reverted with the following reason: + Wrong old state hash + + Contract Call: + address: 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 + function: processTransaction(bytes _proof, bytes32[] _publicInputs) + args: (0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf00000000000000000000000000000000000000000000000b75c020998797da7800000000000000000000000000000000000000000000000 + ``` + +#### `server/index.mjs` {#server-index-mjs-2} + +या फाइलमधील बदल बहुतेक करून वास्तविक पुरावा तयार करणे आणि तो ऑनचेन सबमिट करणे यासंबंधी आहेत. + +```js +import { exec } from 'child_process' +import util from 'util' + +const execPromise = util.promisify(exec) +``` + +ऑनचेन पाठवण्यासाठी वास्तविक पुरावा तयार करण्यासाठी आम्हाला [बॅरेटेंबर्ग पॅकेज](https://github.com/AztecProtocol/aztec-packages/tree/next/barretenberg) वापरण्याची आवश्यकता आहे. आम्ही हे पॅकेज कमांड-लाइन इंटरफेस (`bb`) चालवून किंवा [JavaScript लायब्ररी, `bb.js`](https://www.npmjs.com/package/@aztec/bb.js) वापरून वापरू शकतो. JavaScript लायब्ररी मूळ कोड चालवण्यापेक्षा खूपच मंद आहे, म्हणून आम्ही कमांड-लाइन वापरण्यासाठी येथे [`exec`](https://nodejs.org/api/child_process.html#child_processexeccommand-options-callback) वापरतो. + +लक्षात घ्या की जर तुम्ही `bb.js` वापरण्याचा निर्णय घेतला, तर तुम्हाला Noir च्या आवृत्तीशी सुसंगत असलेली आवृत्ती वापरणे आवश्यक आहे. लेखनाच्या वेळी, सध्याची Noir आवृत्ती (1.0.0-beta.11) `bb.js` आवृत्ती 0.87 वापरते. + +```js +const zkBankAddress = process.env.ZKBANK_ADDRESS || "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512" +``` + +येथील ॲड्रेस तो आहे जो तुम्हाला स्वच्छ `anvil` सह सुरुवात केल्यावर आणि वरील निर्देशांचे पालन केल्यावर मिळतो. + +```js +const walletClient = createWalletClient({ + chain: anvil, + transport: http(), + account: privateKeyToAccount("0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6") +}) +``` + +ही खाजगी की `anvil` मधील डीफॉल्ट पूर्व-अनुदानित खात्यांपैकी एक आहे. + +```js +const generateProof = async (witness, fileID) => { +``` + +`bb` एक्झिक्युटेबल वापरून पुरावा तयार करा. + +```js + const fname = `witness-${fileID}.gz` + await fs.writeFile(fname, witness) +``` + +साक्षीदार एका फाईलमध्ये लिहा. + +```js + await execPromise(`bb prove -b ./noir/target/zkBank.json -w ${fname} -o ${fileID} --oracle_hash keccak --output_format fields`) +``` + +प्रत्यक्षात पुरावा तयार करा. या पायरीमुळे सार्वजनिक व्हेरिएबल्ससह एक फाईल देखील तयार होते, परंतु आम्हाला त्याची आवश्यकता नाही. आम्हाला ते व्हेरिएबल्स `noir.execute` मधून आधीच मिळाले आहेत. + +```js + const proof = "0x" + JSON.parse(await fs.readFile(`./${fileID}/proof_fields.json`)).reduce((a,b) => a+b, "").replace(/0x/g, "") +``` + +पुरावा हा `Field` मूल्यांचा एक JSON ॲरे आहे, प्रत्येक हेक्साडेसिमल मूल्य म्हणून दर्शविला जातो. तथापि, आम्हाला ते व्यवहारात एकल `bytes` मूल्य म्हणून पाठवणे आवश्यक आहे, जे Viem मोठ्या हेक्साडेसिमल स्ट्रिंगद्वारे दर्शवते. येथे आम्ही सर्व मूल्यांना एकत्र जोडून, सर्व `0x` काढून टाकून, आणि शेवटी एक जोडून स्वरूप बदलतो. + +```js + await execPromise(`rm -r ${fname} ${fileID}`) + + return proof +} +``` + +स्वच्छता करा आणि पुरावा परत करा. + +```js +const processMessage = async (message, signature) => { + . + . + . + + const publicFields = noirResult.returnValue.map(x=>'0x' + x.slice(2).padStart(64, "0")) +``` + +सार्वजनिक फील्ड 32-बाइट मूल्यांचा ॲरे असणे आवश्यक आहे. तथापि, आम्हाला व्यवहार हॅश दोन `Field` मूल्यांमध्ये विभागण्याची आवश्यकता असल्याने, ते 16-बाइट मूल्य म्हणून दिसते. येथे आम्ही शून्य जोडतो जेणेकरून Viem ला समजेल की ते प्रत्यक्षात 32 बाइट्स आहे. + +```js + const proof = await generateProof(noirResult.witness, `${fromAddress}-${nonce}`) +``` + +प्रत्येक ॲड्रेस प्रत्येक नॉन्स एकदाच वापरतो जेणेकरून आपण साक्षीदार फाईल आणि आउटपुट डिरेक्टरीसाठी एक अद्वितीय ओळखकर्ता म्हणून `fromAddress` आणि `nonce` यांचे संयोजन वापरू शकू. + +```js + try { + await zkBank.write.processTransaction([ + proof, publicFields]) + } catch (err) { + console.log(`Verification error: ${err}`) + throw Error("Can't verify the transaction onchain") + } + . + . + . +} +``` + +व्यवहार चेनवर पाठवा. + +#### `smart-contracts/src/ZkBank.sol` {#smart-contracts-src-zkbank-sol} + +हा ऑनचेन कोड आहे जो व्यवहार प्राप्त करतो. + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity >=0.8.21; + +import {HonkVerifier} from "./Verifier.sol"; + +contract ZkBank { + HonkVerifier immutable myVerifier; + bytes32 currentStateHash; + + constructor(address _verifierAddress, bytes32 _initialStateHash) { + currentStateHash = _initialStateHash; + myVerifier = HonkVerifier(_verifierAddress); + } +``` + +ऑनचेन कोडला दोन व्हेरिएबल्सचा मागोवा ठेवण्याची आवश्यकता आहे: व्हेरिफायर (`nargo` द्वारे तयार केलेला एक वेगळा कॉन्ट्रॅक्ट) आणि वर्तमान स्टेट हॅश. + +```solidity + event TransactionProcessed( + bytes32 indexed transactionHash, + bytes32 oldStateHash, + bytes32 newStateHash + ); +``` + +प्रत्येक वेळी स्थिती बदलल्यावर, आम्ही `TransactionProcessed` इव्हेंट प्रसारित करतो. + +```solidity + function processTransaction( + bytes calldata _proof, + bytes32[] calldata _publicFields + ) public { +``` + +हे फंक्शन व्यवहारांवर प्रक्रिया करते. हे पुरावा (`bytes` म्हणून) आणि सार्वजनिक इनपुट (`bytes32` ॲरे म्हणून) व्हेरिफायरला आवश्यक असलेल्या स्वरूपात मिळवते (ऑनचेन प्रक्रिया आणि त्यामुळे गॅस खर्च कमी करण्यासाठी). + +```solidity + require(_publicInputs[0] == currentStateHash, + "Wrong old state hash"); +``` + +शून्य-ज्ञान पुरावा असा असावा की व्यवहार आमच्या वर्तमान हॅशमधून नवीन हॅशमध्ये बदलतो. + +```solidity + myVerifier.verify(_proof, _publicFields); +``` + +शून्य-ज्ञान पुरावा सत्यापित करण्यासाठी व्हेरिफायर कॉन्ट्रॅक्टला कॉल करा. ही पायरी शून्य-ज्ञान पुरावा चुकीचा असल्यास व्यवहार उलटवते. + +```solidity + currentStateHash = _publicFields[1]; + + emit TransactionProcessed( + _publicFields[2]<<128 | _publicFields[3], + _publicFields[0], + _publicFields[1] + ); + } +} +``` + +जर सर्वकाही ठीक झाले, तर स्टेट हॅशला नवीन मूल्यावर अपडेट करा आणि `TransactionProcessed` इव्हेंट प्रसारित करा. + +## केंद्रीकृत घटकाद्वारे होणारे गैरवापर {#abuses} + +माहिती सुरक्षेमध्ये तीन गुणधर्म आहेत: + +- _गोपनीयता_, वापरकर्ते ज्या माहितीला वाचण्यासाठी अधिकृत नाहीत ती वाचू शकत नाहीत. +- _अखंडता_, अधिकृत वापरकर्त्यांद्वारे अधिकृत पद्धतीनेच माहिती बदलली जाऊ शकते. +- _उपलब्धता_, अधिकृत वापरकर्ते प्रणाली वापरू शकतात. + +या प्रणालीवर, अखंडता शून्य-ज्ञान पुराव्यांद्वारे प्रदान केली जाते. उपलब्धतेची हमी देणे खूपच कठीण आहे, आणि गोपनीयता अशक्य आहे, कारण बँकेला प्रत्येक खात्याची शिल्लक आणि सर्व व्यवहार माहित असणे आवश्यक आहे. माहिती असलेल्या घटकाला ती माहिती शेअर करण्यापासून रोखण्याचा कोणताही मार्ग नाही. + +[स्टेल्थ ॲड्रेस](https://vitalik.eth.limo/general/2023/01/20/stealth.html) वापरून खऱ्या अर्थाने गोपनीय बँक तयार करणे शक्य आहे, परंतु ते या लेखाच्या व्याप्तीबाहेर आहे. + +### खोटी माहिती {#false-info} + +सर्व्हर ज्या प्रकारे अखंडतेचे उल्लंघन करू शकतो त्यापैकी एक म्हणजे [डेटाची विनंती केल्यावर](https://github.com/qbzzt/250911-zk-bank/blob/03-smart-contracts/server/index.mjs#L278-L291) खोटी माहिती प्रदान करणे. + +यावर उपाय म्हणून, आपण एक दुसरा Noir प्रोग्राम लिहू शकतो जो खात्यांना खाजगी इनपुट म्हणून आणि माहितीसाठी विनंती केलेल्या ॲड्रेसला सार्वजनिक इनपुट म्हणून प्राप्त करतो. आउटपुट त्या ॲड्रेसची शिल्लक आणि नॉन्स, आणि खात्यांचा हॅश आहे. + +अर्थात, हा पुरावा ऑनचेन सत्यापित केला जाऊ शकत नाही, कारण आम्हाला ऑनचेन नॉन्स आणि शिल्लक पोस्ट करायची नाही. तथापि, तो ब्राउझरमध्ये चालणाऱ्या क्लायंट कोडद्वारे सत्यापित केला जाऊ शकतो. + +### सक्तीचे व्यवहार {#forced-txns} + +L2s वर उपलब्धता सुनिश्चित करण्यासाठी आणि सेन्सॉरशिप रोखण्यासाठी सामान्य यंत्रणा [सक्तीचे व्यवहार](https://docs.optimism.io/stack/transactions/forced-transaction) आहे. परंतु सक्तीचे व्यवहार शून्य-ज्ञान पुराव्यांसह एकत्रित होत नाहीत. सर्व्हर हा एकमेव घटक आहे जो व्यवहार सत्यापित करू शकतो. + +आम्ही `smart-contracts/src/ZkBank.sol` मध्ये बदल करून सक्तीचे व्यवहार स्वीकारू शकतो आणि सर्व्हरला स्थिती बदलण्यापासून रोखू शकतो जोपर्यंत त्यावर प्रक्रिया होत नाही. तथापि, यामुळे आपल्याला एका सोप्या डिनायल-ऑफ-सर्व्हिस हल्ल्यासाठी उघडे पडते. जर सक्तीचा व्यवहार अवैध असेल आणि त्यामुळे त्यावर प्रक्रिया करणे अशक्य असेल तर काय? + +यावरील उपाय म्हणजे सक्तीचा व्यवहार अवैध असल्याचा शून्य-ज्ञान पुरावा असणे. हे सर्व्हरला तीन पर्याय देते: + +- सक्तीच्या व्यवहारावर प्रक्रिया करणे, त्यावर प्रक्रिया झाल्याचा शून्य-ज्ञान पुरावा आणि नवीन स्थिती हॅश प्रदान करणे. +- सक्तीचा व्यवहार नाकारणे, आणि कॉन्ट्रॅक्टला शून्य-ज्ञान पुरावा प्रदान करणे की व्यवहार अवैध आहे (अज्ञात ॲड्रेस, चुकीचा नॉन्स, किंवा अपुरी शिल्लक). +- सक्तीच्या व्यवहाराकडे दुर्लक्ष करणे. सर्व्हरला प्रत्यक्षात व्यवहारावर प्रक्रिया करण्यास भाग पाडण्याचा कोणताही मार्ग नाही, परंतु याचा अर्थ संपूर्ण प्रणाली अनुपलब्ध आहे. + +#### उपलब्धता बाँड्स {#avail-bonds} + +वास्तविक जीवनातील अंमलबजावणीमध्ये, सर्व्हर चालू ठेवण्यासाठी कदाचित काही प्रकारचा नफ्याचा हेतू असेल. आम्ही या प्रोत्साहनाला बळकट करण्यासाठी सर्व्हरला एक उपलब्धता बाँड पोस्ट करायला लावू शकतो जो कोणीही जाळू शकतो जर सक्तीचा व्यवहार एका विशिष्ट कालावधीत प्रक्रिया केला गेला नाही. + +### खराब Noir कोड {#bad-noir-code} + +सामान्यतः, लोकांना स्मार्ट कॉन्ट्रॅक्टवर विश्वास ठेवण्यासाठी आम्ही स्त्रोत कोड एका [ब्लॉक एक्सप्लोरर](https://eth.blockscout.com/address/0x7D16d2c4e96BCFC8f815E15b771aC847EcbDB48b?tab=contract) वर अपलोड करतो. तथापि, शून्य-ज्ञान पुराव्यांच्या बाबतीत, ते अपुरे आहे. + +`Verifier.sol` मध्ये पडताळणी की असते, जी Noir प्रोग्रामचे एक फंक्शन आहे. तथापि, ती की आपल्याला Noir प्रोग्राम काय होता हे सांगत नाही. खऱ्या अर्थाने विश्वसनीय उपाययोजना करण्यासाठी, तुम्हाला Noir प्रोग्राम (आणि ज्या आवृत्तीने तो तयार केला आहे) अपलोड करणे आवश्यक आहे. अन्यथा, शून्य-ज्ञान पुरावे एका वेगळ्या प्रोग्रामला प्रतिबिंबित करू शकतात, ज्यामध्ये एक बॅक डोअर असेल. + +जोपर्यंत ब्लॉक एक्सप्लोरर्स आम्हाला Noir प्रोग्राम्स अपलोड आणि सत्यापित करण्याची परवानगी देत नाहीत, तोपर्यंत तुम्ही ते स्वतः करावे (शक्यतो [IPFS](/developers/tutorials/ipfs-decentralized-ui/) वर). मग प्रगत वापरकर्ते स्त्रोत कोड डाउनलोड करू शकतील, तो स्वतः संकलित करू शकतील, `Verifier.sol` तयार करू शकतील, आणि तो ऑनचेन असलेल्या कोडसारखाच आहे हे सत्यापित करू शकतील. + +## निष्कर्ष {#conclusion} + +प्लाझ्मा-प्रकारच्या ॲप्लिकेशन्सना माहिती साठवणुकीसाठी एका केंद्रीकृत घटकाची आवश्यकता असते. यामुळे संभाव्य असुरक्षितता निर्माण होते परंतु, बदल्यात, आम्हाला ब्लॉकचेनवरच उपलब्ध नसलेल्या मार्गांनी गोपनीयतेचे संरक्षण करण्यास अनुमती देते. शून्य-ज्ञान पुराव्यांसह आम्ही अखंडता सुनिश्चित करू शकतो आणि शक्यतो केंद्रीकृत घटक चालवणाऱ्या कोणालाही उपलब्धतेची देखभाल करणे आर्थिकदृष्ट्या फायदेशीर बनवू शकतो. + +[माझ्या कामाबद्दल अधिक माहितीसाठी येथे पहा](https://cryptodocguy.pro/). + +## पोचपावती {#acknowledgements} + +- जोश क्राइट्सने या लेखाचा मसुदा वाचला आणि मला एका काटेरी Noir समस्येवर मदत केली. + +कोणत्याही उर्वरित चुका माझ्या जबाबदारी आहेत. diff --git a/public/content/translations/mr/developers/tutorials/calling-a-smart-contract-from-javascript/index.md b/public/content/translations/mr/developers/tutorials/calling-a-smart-contract-from-javascript/index.md new file mode 100644 index 00000000000..8d7adff8963 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/calling-a-smart-contract-from-javascript/index.md @@ -0,0 +1,131 @@ +--- +title: "JavaScript मधून स्मार्ट कॉन्ट्रॅक्टला कॉल करणे" +description: "Dai टोकनच्या उदाहरणाचा वापर करून JavaScript मधून स्मार्ट कॉन्ट्रॅक्ट फंक्शनला कसे कॉल करावे" +author: jdourlens +tags: [ "व्यवहार", "frontend", "JavaScript", "web3.js" ] +skill: beginner +lang: mr +published: 2020-04-19 +source: EthereumDev +sourceUrl: https://ethereumdev.io/calling-a-smart-contract-from-javascript/ +address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" +--- + +या ट्युटोरियलमध्ये आपण JavaScript मधून [स्मार्ट कॉन्ट्रॅक्ट](/developers/docs/smart-contracts/) फंक्शनला कसे कॉल करायचे ते पाहू. पहिले म्हणजे स्मार्ट कॉन्ट्रॅक्टची स्थिती वाचणे (उदा., ERC20 धारकाची शिल्लक), त्यानंतर आपण टोकन हस्तांतरण करून ब्लॉकचेनची स्थिती सुधारित करू. तुम्ही आधीच [ब्लॉकचेनशी संवाद साधण्यासाठी JS पर्यावरण सेट करण्याशी](/developers/tutorials/set-up-web3js-to-use-ethereum-in-javascript/) परिचित असले पाहिजे. + +या उदाहरणासाठी आपण DAI टोकन वापरणार आहोत, चाचणीच्या उद्देशाने आपण ganache-cli वापरून ब्लॉकचेन फोर्क करू आणि असा ॲड्रेस अनलॉक करू ज्यात आधीच खूप DAI आहेत: + +```bash +ganache-cli -f https://mainnet.infura.io/v3/[तुमची इन्फ्युरा की] -d -i 66 1 --unlock 0x4d10ae710Bd8D1C31bd7465c8CBC3add6F279E81 +``` + +स्मार्ट कॉन्ट्रॅक्टशी संवाद साधण्यासाठी आपल्याला त्याचा ॲड्रेस आणि ABI लागेल: + +```js +const ERC20TransferABI = [ + { + constant: false, + inputs: [ + { + name: "_to", + type: "address", + }, + { + name: "_value", + type: "uint256", + }, + ], + name: "transfer", + outputs: [ + { + name: "", + type: "bool", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [ + { + name: "_owner", + type: "address", + }, + ], + name: "balanceOf", + outputs: [ + { + name: "balance", + type: "uint256", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, +] + +const DAI_ADDRESS = "0x6b175474e89094c44da98b954eedeac495271d0f" +``` + +या प्रोजेक्टसाठी आम्ही फक्त `balanceOf` आणि `transfer` फंक्शन ठेवण्यासाठी संपूर्ण ERC20 ABI मधून अनावश्यक भाग काढला आहे पण तुम्ही [संपूर्ण ERC20 ABI येथे](https://ethereumdev.io/abi-for-erc20-contract-on-ethereum/) शोधू शकता. + +त्यानंतर आपल्याला आपला स्मार्ट कॉन्ट्रॅक्ट सुरू करण्याची गरज आहे: + +```js +const web3 = new Web3("http://localhost:8545") + +const daiToken = new web3.eth.Contract(ERC20TransferABI, DAI_ADDRESS) +``` + +आपण दोन ॲड्रेस देखील सेट करू: + +- ज्याला हस्तांतरण मिळेल तो आणि +- आपण आधीच अनलॉक केलेला जो ते पाठवेल: + +```js +const senderAddress = "0x4d10ae710Bd8D1C31bd7465c8CBC3add6F279E81" +const receiverAddress = "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" +``` + +पुढील भागात आपण दोन्ही ॲड्रेसकडे असलेल्या टोकन्सची सध्याची रक्कम मिळवण्यासाठी `balanceOf` फंक्शनला कॉल करू. + +## कॉल: स्मार्ट कॉन्ट्रॅक्टमधून मूल्य वाचणे {#call-reading-value-from-a-smart-contract} + +पहिले उदाहरण कोणतेही ट्रान्झॅक्शन न पाठवता एक “कॉन्स्टन्ट” मेथड कॉल करेल आणि EVM मध्ये त्याचे स्मार्ट कॉन्ट्रॅक्ट मेथड कार्यान्वित करेल. यासाठी आपण एका ॲड्रेसची ERC20 शिल्लक वाचू. [ERC20 टोकन्सबद्दल आमचा लेख वाचा](/developers/tutorials/understand-the-erc-20-token-smart-contract/). + +तुम्ही `yourContract.methods.methodname` अशाप्रकारे इन्स्टन्शिएट केलेल्या स्मार्ट कॉन्ट्रॅक्टच्या मेथड्समध्ये प्रवेश करू शकता ज्यासाठी तुम्ही ABI प्रदान केले आहे. `call` फंक्शन वापरून तुम्हाला फंक्शन कार्यान्वित केल्याचा परिणाम मिळेल. + +```js +daiToken.methods.balanceOf(senderAddress).call(function (err, res) { + if (err) { + console.log("एक त्रुटी आली", err) + return + } + console.log("शिल्लक आहे: ", res) +}) +``` + +लक्षात ठेवा की DAI ERC20 मध्ये 18 दशांश स्थळे आहेत, याचा अर्थ योग्य रक्कम मिळवण्यासाठी तुम्हाला 18 शून्य काढावे लागतील. JavaScript मोठ्या अंकीय मूल्यांना हाताळू शकत नसल्यामुळे uint256 स्ट्रिंग म्हणून परत केले जातात. तुम्हाला खात्री नसेल तर [JS मध्ये मोठ्या संख्या कशा हाताळायच्या याबद्दल आमचे bignumber.js वरील ट्युटोरियल पहा](https://ethereumdev.io/how-to-deal-with-big-numbers-in-javascript/). + +## पाठवा: स्मार्ट कॉन्ट्रॅक्ट फंक्शनला ट्रान्झॅक्शन पाठवणे {#send-sending-a-transaction-to-a-smart-contract-function} + +दुसऱ्या उदाहरणासाठी, आपण आपल्या दुसऱ्या ॲड्रेसवर 10 DAI पाठवण्यासाठी DAI स्मार्ट कॉन्ट्रॅक्टच्या ट्रान्स्फर फंक्शनला कॉल करू. ट्रान्स्फर फंक्शन दोन पॅरामीटर्स स्वीकारते: प्राप्तकर्त्याचा ॲड्रेस आणि हस्तांतरित करायच्या टोकनची रक्कम: + +```js +daiToken.methods + .transfer(receiverAddress, "100000000000000000000") + .send({ from: senderAddress }, function (err, res) { + if (err) { + console.log("एक त्रुटी आली", err) + return + } + console.log("ट्रान्झॅक्शनचा हॅश: " + res) + }) +``` + +कॉल फंक्शन त्या ट्रान्झॅक्शनचा हॅश परत करतो जे ब्लॉकचेनमध्ये माइन केले जाईल. Ethereum वर, ट्रान्झॅक्शन हॅश अंदाजित असतात - म्हणूनच आपण ट्रान्झॅक्शन कार्यान्वित होण्यापूर्वी त्याचा हॅश मिळवू शकतो ([हॅश कसे मोजले जातात ते येथे शिका](https://ethereum.stackexchange.com/questions/45648/how-to-calculate-the-assigned-txhash-of-a-transaction)). + +हे फंक्शन फक्त ब्लॉकचेनवर ट्रान्झॅक्शन सबमिट करत असल्यामुळे, ते माइन होऊन ब्लॉकचेनमध्ये समाविष्ट होईपर्यंत आपण निकाल पाहू शकत नाही. पुढील ट्युटोरियलमध्ये आपण [ब्लॉकचेनवर ट्रान्झॅक्शन कार्यान्वित होण्याची वाट कशी पाहायची, त्याचा हॅश जाणून घेऊन शिकू](https://ethereumdev.io/waiting-for-a-transaction-to-be-mined-on-ethereum-with-js/). diff --git a/public/content/translations/mr/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md b/public/content/translations/mr/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md new file mode 100644 index 00000000000..36b54d2676b --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/creating-a-wagmi-ui-for-your-contract/index.md @@ -0,0 +1,585 @@ +--- +title: "तुमच्या काँट्रॅक्टसाठी युझर इंटरफेस तयार करणे" +description: "TypeScript, React, Vite आणि Wagmi सारख्या आधुनिक घटकांचा वापर करून, आम्ही एक आधुनिक, पण किमान, युझर इंटरफेस पाहणार आहोत आणि युझर इंटरफेसशी वॉलेट कसे कनेक्ट करावे, माहिती वाचण्यासाठी स्मार्ट काँट्रॅक्टला कॉल कसा करावा, स्मार्ट काँट्रॅक्टला व्यवहार कसा पाठवावा, आणि बदल ओळखण्यासाठी स्मार्ट काँट्रॅक्टमधील इव्हेंटचे निरीक्षण कसे करावे हे शिकणार आहोत." +author: Ori Pomerantz +tags: [ "typescript", "react", "vite", "wagmi", "frontend" ] +skill: beginner +published: 2023-11-01 +lang: mr +sidebarDepth: 3 +--- + +तुम्हाला Ethereum इकोसिस्टीममध्ये एक आवश्यक वैशिष्ट्य आढळले आहे. तुम्ही ते लागू करण्यासाठी स्मार्ट काँट्रॅक्ट्स लिहिले आणि कदाचित ऑफचेन चालणारा काही संबंधित कोड देखील लिहिला असेल. हे उत्तम आहे! दुर्दैवाने, युझर इंटरफेसशिवाय तुम्हाला कोणतेही युझर मिळणार नाहीत, आणि मागच्या वेळी जेव्हा तुम्ही वेबसाइट लिहिली होती तेव्हा लोक डायल-अप मोडेम वापरत होते आणि JavaScript नवीन होते. + +हा लेख तुमच्यासाठी आहे. मी गृहीत धरतो की तुम्हाला प्रोग्रामिंग माहित आहे, आणि कदाचित थोडे JavaScript आणि HTML देखील माहित आहे, परंतु तुमची युझर इंटरफेस कौशल्ये गंजलेली आणि कालबाह्य झाली आहेत. एकत्रितपणे आपण एका सोप्या आधुनिक ऍप्लिकेशनवर नजर टाकू जेणेकरून तुम्हाला दिसेल की आजकाल हे कसे केले जाते. + +## हे महत्त्वाचे का आहे {#why-important} + +सिद्धांतानुसार, तुम्ही लोकांना तुमच्या काँट्रॅक्ट्सशी संवाद साधण्यासाठी फक्त [Etherscan](https://holesky.etherscan.io/address/0x432d810484add7454ddb3b5311f0ac2e95cecea8#writeContract) किंवा [Blockscout](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=write_contract) वापरण्यास सांगू शकता. अनुभवी Ethereans साठी ते उत्तम असेल. परंतु आम्ही [आणखी एक अब्ज लोकांना](https://blog.ethereum.org/2021/05/07/ethereum-for-the-next-billion) सेवा देण्याचा प्रयत्न करत आहोत. एका उत्तम वापरकर्ता अनुभवाशिवाय हे घडणार नाही आणि एक अनुकूल वापरकर्ता इंटरफेस हा त्याचा एक मोठा भाग आहे. + +## Greeter ऍप्लिकेशन {#greeter-app} + +आधुनिक UI कसे कार्य करते यामागे बराच सिद्धांत आहे, आणि [बर्‍याच चांगल्या साइट्स](https://react.dev/learn/thinking-in-react) [आहेत ज्या ते स्पष्ट करतात](https://wagmi.sh/core/getting-started). त्या साइट्सनी केलेले उत्तम काम पुन्हा करण्याऐवजी, मी असे गृहीत धरणार आहे की तुम्ही करून शिकण्यास प्राधान्य देता आणि अशा ऍप्लिकेशनने सुरुवात करता ज्यासोबत तुम्ही खेळू शकता. गोष्टी पूर्ण करण्यासाठी तुम्हाला अजूनही सिद्धांताची आवश्यकता आहे, आणि आम्ही त्यावर येऊ - आम्ही फक्त सोर्स फाइलनुसार जाऊ, आणि गोष्टी जशा येतील तशा त्यावर चर्चा करू. + +### इन्स्टॉलेशन {#installation} + +1. आवश्यक असल्यास, तुमच्या वॉलेटमध्ये [Holesky ब्लॉकचेन](https://chainlist.org/?search=holesky&testnets=true) जोडा आणि [चाचणी ETH मिळवा](https://www.holeskyfaucet.io/). + +2. github रेपॉजिटरी क्लोन करा. + + ```sh + git clone https://github.com/qbzzt/20230801-modern-ui.git + ``` + +3. आवश्यक पॅकेजेस इंस्टॉल करा. + + ```sh + cd 20230801-modern-ui + pnpm install + ``` + +4. ऍप्लिकेशन सुरू करा. + + ```sh + pnpm dev + ``` + +5. ऍप्लिकेशनने दाखवलेल्या URL वर ब्राउझ करा. बहुतेक प्रकरणांमध्ये, ते [http://localhost:5173/](http://localhost:5173/) आहे. + +6. तुम्ही काँट्रॅक्ट सोर्स कोड, Hardhat च्या Greeter ची थोडी सुधारित आवृत्ती, [ब्लॉकचेन एक्सप्लोररवर](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=contract) पाहू शकता. + +### फाइल वॉक थ्रू {#file-walk-through} + +#### `index.html` {#index-html} + +ही फाईल मानक HTML बॉयलरप्लेट आहे, फक्त ही ओळ वगळता, जी स्क्रिप्ट फाइल आयात करते. + +```html + +``` + +#### `src/main.tsx` {#main-tsx} + +फाइल एक्सटेंशन आम्हाला सांगते की ही फाईल [TypeScript](https://www.typescriptlang.org/) मध्ये लिहिलेला एक [React घटक](https://www.w3schools.com/react/react_components.asp) आहे, जो JavaScript चा एक विस्तार आहे जो [टाइप चेकिंग](https://en.wikipedia.org/wiki/Type_system#Type_checking) ला समर्थन देतो. TypeScript हे JavaScript मध्ये संकलित (compiled) केले जाते, म्हणून आम्ही ते क्लायंट-साइड एक्झिक्यूशनसाठी वापरू शकतो. + +```tsx +import '@rainbow-me/rainbowkit/styles.css' +import { RainbowKitProvider } from '@rainbow-me/rainbowkit' +import * as React from 'react' +import * as ReactDOM from 'react-dom/client' +import { WagmiConfig } from 'wagmi' +import { chains, config } from './wagmi' +``` + +आम्हाला आवश्यक असलेला लायब्ररी कोड आयात करा. + +```tsx +import { App } from './App' +``` + +ऍप्लिकेशन लागू करणारा React घटक आयात करा (खाली पहा). + +```tsx +ReactDOM.createRoot(document.getElementById('root')!).render( +``` + +रूट React घटक तयार करा. `render` चा पॅरामीटर [JSX](https://www.w3schools.com/react/react_jsx.asp) आहे, एक विस्तार भाषा जी HTML आणि JavaScript/TypeScript दोन्ही वापरते. येथील उद्गारवाचक चिन्ह TypeScript घटकाला सांगते: "तुम्हाला माहित नाही की `document.getElementById('root')` हे `ReactDOM.createRoot` साठी एक वैध पॅरामीटर असेल, पण काळजी करू नका - मी डेव्हलपर आहे आणि मी तुम्हाला सांगत आहे की ते असेल". + +```tsx + +``` + +ऍप्लिकेशन [एका `React.StrictMode` घटकात](https://react.dev/reference/react/StrictMode) जात आहे. हा घटक React लायब्ररीला अतिरिक्त डीबगिंग तपासण्या घालण्यास सांगतो, जे डेव्हलपमेंट दरम्यान उपयुक्त आहे. + +```tsx + +``` + +ऍप्लिकेशन [एका `WagmiConfig` घटकात](https://wagmi.sh/react/api/WagmiProvider) देखील आहे. [wagmi (we are going to make it) लायब्ररी](https://wagmi.sh/) Ethereum विकेंद्रित ऍप्लिकेशन लिहिण्यासाठी React UI व्याख्यांना [viem लायब्ररीसह](https://viem.sh/) जोडते. + +```tsx + +``` + +आणि शेवटी, [एक `RainbowKitProvider` घटक](https://www.rainbowkit.com/). हा घटक लॉग ऑन करणे आणि वॉलेट आणि ऍप्लिकेशनमधील संवाद हाताळतो. + +```tsx + +``` + +आता आमच्याकडे ऍप्लिकेशनसाठी घटक असू शकतो, जो प्रत्यक्षात UI लागू करतो. घटकाच्या शेवटी असलेले `/>` React ला सांगते की या घटकामध्ये XML मानकानुसार कोणतीही व्याख्या नाही. + +```tsx + + + , +) +``` + +अर्थात, आम्हाला इतर घटक बंद करावे लागतील. + +#### `src/App.tsx` {#app-tsx} + +```tsx +import { ConnectButton } from '@rainbow-me/rainbowkit' +import { useAccount } from 'wagmi' +import { Greeter } from './components/Greeter' + +export function App() { +``` + +React घटक तयार करण्याचा हा मानक मार्ग आहे - एक फंक्शन परिभाषित करा जे प्रत्येक वेळी रेंडर करण्याची आवश्यकता असताना कॉल केले जाते. या फंक्शनमध्ये सामान्यतः शीर्षस्थानी काही TypeScript किंवा JavaScript कोड असतो, त्यानंतर `return` स्टेटमेंट असते जे JSX कोड परत करते. + +```tsx + const { isConnected } = useAccount() +``` + +येथे आपण वॉलेटद्वारे ब्लॉकचेनशी कनेक्ट आहोत की नाही हे तपासण्यासाठी [`useAccount`](https://wagmi.sh/react/api/hooks/useAccount) वापरतो. + +परंपरेनुसार, React मध्ये `use...` नावाची फंक्शन्स [hooks](https://www.w3schools.com/react/react_hooks.asp) असतात जी काही प्रकारचा डेटा परत करतात. जेव्हा तुम्ही असे हुक वापरता, तेव्हा तुमच्या घटकाला केवळ डेटा मिळत नाही, तर जेव्हा तो डेटा बदलतो तेव्हा घटक अद्यतनित माहितीसह पुन्हा रेंडर केला जातो. + +```tsx + return ( + <> +``` + +React घटकाच्या JSX ने एक घटक परत करणे _आवश्यक_ आहे. जेव्हा आमच्याकडे एकापेक्षा जास्त घटक असतात आणि आमच्याकडे "नैसर्गिकरित्या" गुंडाळण्यासाठी काहीही नसते, तेव्हा आम्ही एक रिकामा घटक (`<> ...` वापरतो `) त्यांना एकाच घटकात बनवण्यासाठी. + +```tsx +

Greeter

+ +``` + +आम्हाला RainbowKit कडून [`ConnectButton` घटक](https://www.rainbowkit.com/docs/connect-button) मिळतो. जेव्हा आम्ही कनेक्ट नसतो, तेव्हा ते आम्हाला `Connect Wallet` बटण देते जे एक मोडल उघडते जे वॉलेट्सबद्दल स्पष्ट करते आणि तुम्हाला कोणते वापरायचे आहे ते निवडू देते. जेव्हा आम्ही कनेक्ट असतो, तेव्हा ते आम्ही वापरत असलेले ब्लॉकचेन, आमचा खाते पत्ता आणि आमची ETH शिल्लक दर्शवते. आम्ही नेटवर्क स्विच करण्यासाठी किंवा डिस्कनेक्ट करण्यासाठी हे डिस्प्ले वापरू शकतो. + +```tsx + {isConnected && ( +``` + +जेव्हा आम्हाला JSX मध्ये प्रत्यक्ष JavaScript (किंवा JavaScript मध्ये संकलित केले जाणारे TypeScript) घालण्याची आवश्यकता असते, तेव्हा आम्ही कंस (`{}`) वापरतो. + +`a && b` हे सिंटॅक्स [`a ?` साठी लहान आहे. b : a`](https://www.w3schools.com/react/react_es6_ternary.asp). म्हणजे, जर `a`सत्य असेल तर त्याचे मूल्य`b`होते आणि अन्यथा त्याचे मूल्य`a`होते (जे`false`, `0`, इत्यादी असू शकते). React ला हे सांगण्याचा हा एक सोपा मार्ग आहे की एखादा घटक केवळ तेव्हाच प्रदर्शित केला पाहिजे जेव्हा एखादी विशिष्ट अट पूर्ण होते. + +या प्रकरणात, वापरकर्ता ब्लॉकचेनशी कनेक्ट असल्यास आम्ही फक्त वापरकर्त्याला `Greeter` दाखवू इच्छितो. + +```tsx + + )} + + ) +} +``` + +#### `src/components/Greeter.tsx` {#greeter-tsx} + +या फाइलमध्ये बहुतेक UI कार्यक्षमता आहे. यात अशा व्याख्यांचा समावेश आहे ज्या सामान्यतः एकाधिक फाईल्समध्ये असतील, परंतु हे एक ट्यूटोरियल असल्याने, प्रोग्राम कामगिरी किंवा देखभालीच्या सुलभतेऐवजी पहिल्यांदा समजण्यास सोपे होण्यासाठी ऑप्टिमाइझ केला आहे. + +```tsx +import { useState, ChangeEventHandler } from 'react' +import { useNetwork, + useReadContract, + usePrepareContractWrite, + useContractWrite, + useContractEvent + } from 'wagmi' +``` + +आम्ही ही लायब्ररी फंक्शन्स वापरतो. पुन्हा, ते कुठे वापरले जातात हे खाली स्पष्ट केले आहे. + +```tsx +import { AddressType } from 'abitype' +``` + +[`abitype` लायब्ररी](https://abitype.dev/) आम्हाला विविध Ethereum डेटा प्रकारांसाठी TypeScript व्याख्या प्रदान करते, जसे की [`AddressType`](https://abitype.dev/config#addresstype). + +```tsx +let greeterABI = [ + . + . + . +] as const // greeterABI +``` + +`Greeter` करारासाठी ABI. +जर तुम्ही काँट्रॅक्ट आणि UI एकाच वेळी विकसित करत असाल तर तुम्ही सामान्यतः त्यांना एकाच रेपॉजिटरीमध्ये ठेवाल आणि तुमच्या ऍप्लिकेशनमधील फाइल म्हणून Solidity कंपाइलरद्वारे व्युत्पन्न केलेला ABI वापराल. तथापि, येथे हे आवश्यक नाही कारण करार आधीच विकसित झाला आहे आणि बदलणार नाही. + +```tsx +type AddressPerBlockchainType = { + [key: number]: AddressType +} +``` + +TypeScript स्ट्राँगली टाईप आहे. आम्ही या व्याख्येचा वापर विविध चेन्सवर `Greeter` काँट्रॅक्ट तैनात केलेला पत्ता निर्दिष्ट करण्यासाठी करतो. की ही एक संख्या आहे (chainId), आणि मूल्य एक `AddressType` (एक पत्ता) आहे. + +```tsx +const contractAddrs: AddressPerBlockchainType = { + // Holesky + 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8', + + // Sepolia + 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0' +} +``` + +दोन समर्थित नेटवर्क्सवर कराराचा पत्ता: [Holesky](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=contact_code) आणि [Sepolia](https://eth-sepolia.blockscout.com/address/0x7143d5c190F048C8d19fe325b748b081903E3BF0?tab=contact_code). + +टीप: प्रत्यक्षात तिसरी व्याख्या आहे, Redstone Holesky साठी, ती खाली स्पष्ट केली जाईल. + +```tsx +type ShowObjectAttrsType = { + name: string, + object: any +} +``` + +हा प्रकार `ShowObject` घटकासाठी पॅरामीटर म्हणून वापरला जातो (नंतर स्पष्ट केला आहे). यात ऑब्जेक्टचे नाव आणि त्याचे मूल्य समाविष्ट आहे, जे डीबगिंगच्या उद्देशाने प्रदर्शित केले जातात. + +```tsx +type ShowGreetingAttrsType = { + greeting: string | undefined +} +``` + +कोणत्याही क्षणी आम्हाला एकतर अभिवादन काय आहे हे माहित असू शकते (कारण आम्ही ते ब्लॉकचेनवरून वाचले आहे) किंवा माहित नाही (कारण आम्हाला ते अद्याप मिळालेले नाही). म्हणून असा प्रकार असणे उपयुक्त आहे जो एकतर स्ट्रिंग किंवा काहीही असू शकतो. + +##### `Greeter` घटक {#greeter-component} + +```tsx +const Greeter = () => { +``` + +शेवटी, आम्ही घटक परिभाषित करतो. + +```tsx + const { chain } = useNetwork() +``` + +आपण वापरत असलेल्या चेनबद्दल माहिती, [wagmi](https://wagmi.sh/react/hooks/useNetwork) च्या सौजन्याने. +कारण हा एक हुक (`use...`) आहे, प्रत्येक वेळी ही माहिती बदलल्यावर घटक पुन्हा काढला जातो. + +```tsx + const greeterAddr = chain && contractAddrs[chain.id] +``` + +Greeter काँट्रॅक्टचा पत्ता, जो चेननुसार बदलतो (आणि जर आमच्याकडे चेन माहिती नसेल किंवा आम्ही त्या काँट्रॅक्टशिवाय चेनवर असू तर तो `undefined` असतो). + +```tsx + const readResults = useReadContract({ + address: greeterAddr, + abi: greeterABI, + functionName: "greet" , // No arguments + watch: true + }) +``` + +[`useReadContract` हुक](https://wagmi.sh/react/api/hooks/useReadContract) एका काँट्रॅक्टमधून माहिती वाचतो. UI मध्ये `readResults` विस्तारून ते नक्की कोणती माहिती परत करते हे तुम्ही पाहू शकता. या प्रकरणात आम्हाला ते शोधत रहायचे आहे जेणेकरून अभिवादन बदलल्यावर आम्हाला सूचित केले जाईल. + +**टीप:** अभिवादन कधी बदलते हे जाणून घेण्यासाठी आणि त्या मार्गाने अपडेट करण्यासाठी आम्ही [`setGreeting` इव्हेंट](https://eth-holesky.blockscout.com/address/0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8?tab=logs) ऐकू शकतो. तथापि, ते अधिक कार्यक्षम असले तरी, ते सर्व बाबतीत लागू होणार नाही. जेव्हा वापरकर्ता वेगळ्या चेनवर स्विच करतो, तेव्हा अभिवादन देखील बदलते, परंतु त्या बदलासोबत इव्हेंट नसतो. आमच्याकडे कोडचा एक भाग इव्हेंट ऐकत असू शकतो आणि दुसरा चेन बदल ओळखण्यासाठी असू शकतो, परंतु ते फक्त [`watch` पॅरामीटर](https://wagmi.sh/react/api/hooks/useReadContract#watch-optional) सेट करण्यापेक्षा अधिक क्लिष्ट असेल. + +```tsx + const [ newGreeting, setNewGreeting ] = useState("") +``` + +React चा [`useState` हुक](https://www.w3schools.com/react/react_usestate.asp) आम्हाला एक स्टेट व्हेरिएबल निर्दिष्ट करू देतो, ज्याचे मूल्य घटकाच्या एका रेंडरिंगपासून दुसऱ्या रेंडरिंगपर्यंत टिकून राहते. प्रारंभिक मूल्य हे पॅरामीटर आहे, या प्रकरणात रिक्त स्ट्रिंग. + +`useState` हुक दोन मूल्यांसह एक सूची परत करतो: + +1. स्टेट व्हेरिएबलचे वर्तमान मूल्य. +2. आवश्यकतेनुसार स्टेट व्हेरिएबलमध्ये बदल करण्यासाठी एक फंक्शन. हा एक हुक असल्याने, प्रत्येक वेळी तो कॉल केल्यावर घटक पुन्हा रेंडर होतो. + +या प्रकरणात, आम्ही वापरकर्त्याने सेट करू इच्छित असलेल्या नवीन अभिवादनासाठी स्टेट व्हेरिएबल वापरत आहोत. + +```tsx + const greetingChange : ChangeEventHandler = (evt) => + setNewGreeting(evt.target.value) +``` + +नवीन अभिवादन इनपुट फील्ड बदलल्यावर हा इव्हेंट हँडलर आहे. प्रकार, [`ChangeEventHandler`](https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/forms_and_events/), निर्दिष्ट करतो की हा HTML इनपुट घटकाच्या मूल्याच्या बदलासाठी हँडलर आहे. `` भाग वापरला जातो कारण हा एक [जेनेरिक प्रकार](https://www.w3schools.com/typescript/typescript_basic_generics.php) आहे. + +```tsx + const preparedTx = usePrepareContractWrite({ + address: greeterAddr, + abi: greeterABI, + functionName: 'setGreeting', + args: [ newGreeting ] + }) + const workingTx = useContractWrite(preparedTx.config) +``` + +क्लायंटच्या दृष्टिकोनातून ब्लॉकचेन व्यवहार सबमिट करण्याची ही प्रक्रिया आहे: + +1. [`eth_estimateGas`](https://docs.alchemy.com/reference/eth-estimategas) वापरून ब्लॉकचेनमधील नोडला व्यवहार पाठवा. +2. नोडकडून प्रतिसादाची प्रतीक्षा करा. +3. जेव्हा प्रतिसाद प्राप्त होतो, तेव्हा वापरकर्त्याला वॉलेटद्वारे व्यवहार साइन करण्यास सांगा. ही पायरी नोड प्रतिसाद मिळाल्यानंतर _घडायलाच हवी_ कारण वापरकर्त्याला साइन करण्यापूर्वी व्यवहाराची गॅस किंमत दर्शविली जाते. +4. वापरकर्त्याच्या मंजुरीची प्रतीक्षा करा. +5. यावेळी [`eth_sendRawTransaction`](https://docs.alchemy.com/reference/eth-sendrawtransaction) वापरून व्यवहार पुन्हा पाठवा. + +पायरी 2 मध्ये लक्षात येण्याजोगा वेळ लागण्याची शक्यता आहे, ज्या दरम्यान वापरकर्त्यांना आश्चर्य वाटेल की त्यांची कमांड खरोखरच युझर इंटरफेसद्वारे प्राप्त झाली आहे की नाही आणि त्यांना आधीच व्यवहार साइन करण्यास का सांगितले जात नाही. त्यामुळे वापरकर्ता अनुभव (UX) वाईट होतो. + +यावरील उपाय म्हणजे [प्रिपेअर हुक्स](https://wagmi.sh/react/prepare-hooks) वापरणे. प्रत्येक वेळी जेव्हा पॅरामीटर बदलतो, तेव्हा लगेच नोडला `eth_estimateGas` विनंती पाठवा. मग, जेव्हा वापरकर्त्याला प्रत्यक्षात व्यवहार पाठवायचा असतो (या प्रकरणात **अपडेट ग्रीटिंग** दाबून), तेव्हा गॅसची किंमत ज्ञात असते आणि वापरकर्ता लगेच वॉलेट पृष्ठ पाहू शकतो. + +```tsx + return ( +``` + +आता आपण शेवटी परत करण्यासाठी वास्तविक HTML तयार करू शकतो. + +```tsx + <> +

Greeter

+ { + !readResults.isError && !readResults.isLoading && + + } +
+``` + +`ShowGreeting` घटक तयार करा (खाली स्पष्ट केले आहे), परंतु फक्त जर अभिवादन ब्लॉकचेनमधून यशस्वीरित्या वाचले गेले असेल तरच. + +```tsx + +``` + +हे इनपुट टेक्स्ट फील्ड आहे जिथे वापरकर्ता नवीन अभिवादन सेट करू शकतो. प्रत्येक वेळी जेव्हा वापरकर्ता की दाबतो, तेव्हा आम्ही `greetingChange` ला कॉल करतो जे `setNewGreeting` ला कॉल करते. `setNewGreeting` हे `useState` हुक मधून येत असल्यामुळे, ते `Greeter` घटकाला पुन्हा रेंडर करण्यास प्रवृत्त करते. याचा अर्थ असा: + +- आम्हाला नवीन अभिवादनाचे मूल्य ठेवण्यासाठी `value` निर्दिष्ट करणे आवश्यक आहे, कारण अन्यथा ते डीफॉल्ट, रिक्त स्ट्रिंगमध्ये परत येईल. +- `usePrepareContractWrite` प्रत्येक वेळी `newGreeting` बदलल्यावर कॉल केले जाते, याचा अर्थ असा की तयार केलेल्या व्यवहारामध्ये नेहमीच नवीनतम `newGreeting` असेल. + +```tsx + +``` + +जर `workingTx.write` नसेल तर आम्ही अद्याप अभिवादन अपडेट पाठवण्यासाठी आवश्यक असलेल्या माहितीची वाट पाहत आहोत, म्हणून बटण अक्षम आहे. जर `workingTx.write` मूल्य असेल तर ते व्यवहार पाठवण्यासाठी कॉल करण्याचे फंक्शन आहे. + +```tsx +
+ + + + + ) +} +``` + +शेवटी, आम्ही काय करत आहोत हे पाहण्यात तुम्हाला मदत करण्यासाठी, आम्ही वापरत असलेल्या तीन वस्तू दाखवा: + +- `readResults` +- `preparedTx` +- `workingTx` + +##### `ShowGreeting` घटक {#showgreeting-component} + +हा घटक दाखवतो + +```tsx +const ShowGreeting = (attrs : ShowGreetingAttrsType) => { +``` + +घटक फंक्शनला घटकाच्या सर्व गुणधर्मांसह एक पॅरामीटर मिळतो. + +```tsx + return {attrs.greeting} +} +``` + +##### `ShowObject` घटक {#showobject-component} + +माहितीच्या उद्देशांसाठी, आम्ही महत्त्वाच्या वस्तू (`readResults` अभिवादन वाचण्यासाठी आणि `preparedTx` आणि `workingTx` आपण तयार केलेल्या व्यवहारांसाठी) दाखवण्यासाठी `ShowObject` घटक वापरतो. + +```tsx +const ShowObject = (attrs: ShowObjectAttrsType ) => { + const keys = Object.keys(attrs.object) + const funs = keys.filter(k => typeof attrs.object[k] == "function") + return <> +
+``` + +आम्हाला सर्व माहितीने UI ला अव्यवस्थित करायचे नाही, म्हणून त्यांना पाहणे किंवा बंद करणे शक्य करण्यासाठी, आम्ही [`details`](https://www.w3schools.com/tags/tag_details.asp) टॅग वापरतो. + +```tsx + {attrs.name} +
+        {JSON.stringify(attrs.object, null, 2)}
+```
+
+बहुतेक फील्ड [`JSON.stringify`](https://www.w3schools.com/js/js_json_stringify.asp) वापरून प्रदर्शित केले जातात.
+
+```tsx
+      
+ { funs.length > 0 && + <> + Functions: +
    +``` + +अपवाद फंक्शन्स आहेत, जे [JSON मानकाचा](https://www.json.org/json-en.html) भाग नाहीत, म्हणून ते स्वतंत्रपणे प्रदर्शित करावे लागतील. + +```tsx + {funs.map((f, i) => +``` + +JSX मध्ये, `{` कर्ली ब्रॅकेट्स `}` मधील कोड JavaScript म्हणून अर्थ लावला जातो. मग, `(` रेग्युलर ब्रॅकेट्स `)` मधील कोडचा पुन्हा JSX म्हणून अर्थ लावला जातो. + +```tsx + (
  • {f}
  • ) + )} +``` + +React ला [DOM ट्री](https://www.w3schools.com/js/js_htmldom.asp) मधील टॅगसाठी वेगळे आयडेंटिफायर असणे आवश्यक आहे. याचा अर्थ असा की एकाच टॅगच्या चाइल्ड्सना (या प्रकरणात, [अनऑर्डर्ड लिस्ट](https://www.w3schools.com/tags/tag_ul.asp)), वेगळ्या `key` अॅट्रिब्युट्सची आवश्यकता असते. + +```tsx +
+ + } +
+ +} +``` + +विविध HTML टॅग्ज संपवा. + +##### अंतिम `export` {#the-final-export} + +```tsx +export { Greeter } +``` + +`Greeter` घटक हा आहे जो आम्हाला ऍप्लिकेशनसाठी निर्यात करणे आवश्यक आहे. + +#### `src/wagmi.ts` {#wagmi-ts} + +शेवटी, WAGMI शी संबंधित विविध व्याख्या `src/wagmi.ts` मध्ये आहेत. मी येथे सर्व काही स्पष्ट करणार नाही, कारण त्यातील बहुतेक बॉयलरप्लेट आहे जी तुम्हाला बदलण्याची शक्यता नाही. + +येथील कोड [github](https://github.com/qbzzt/20230801-modern-ui/blob/main/src/wagmi.ts) वरील कोड सारखाच नाही कारण नंतर लेखात आम्ही आणखी एक चेन ([Redstone Holesky](https://redstone.xyz/docs/network-info)) जोडतो. + +```ts +import { getDefaultWallets } from '@rainbow-me/rainbowkit' +import { configureChains, createConfig } from 'wagmi' +import { holesky, sepolia } from 'wagmi/chains' +``` + +ऍप्लिकेशनला समर्थन देणारे ब्लॉकचेन आयात करा. तुम्ही [viem github](https://github.com/wagmi-dev/viem/tree/main/src/chains/definitions) मध्ये समर्थित चेन्सची सूची पाहू शकता. + +```ts +import { publicProvider } from 'wagmi/providers/public' + +const walletConnectProjectId = 'c96e690bb92b6311e8e9b2a6a22df575' +``` + +[WalletConnect](https://walletconnect.com/) वापरण्यास सक्षम होण्यासाठी तुम्हाला तुमच्या ऍप्लिकेशनसाठी प्रोजेक्ट आयडी आवश्यक आहे. तुम्ही ते [cloud.walletconnect.com](https://cloud.walletconnect.com/sign-in) वर मिळवू शकता. + +```ts +const { chains, publicClient, webSocketPublicClient } = configureChains( + [ holesky, sepolia ], + [ + publicProvider(), + ], +) + +const { connectors } = getDefaultWallets({ + appName: 'My wagmi + RainbowKit App', + chains, + projectId: walletConnectProjectId, +}) + +export const config = createConfig({ + autoConnect: true, + connectors, + publicClient, + webSocketPublicClient, +}) + +export { chains } +``` + +### दुसरे ब्लॉकचेन जोडणे {#add-blockchain} + +आजकाल बरेच [L2 स्केलिंग सोल्यूशन](/layer-2/) आहेत, आणि तुम्ही काहींना समर्थन देऊ इच्छित असाल जे viem अद्याप समर्थन देत नाही. ते करण्यासाठी, तुम्ही `src/wagmi.ts` मध्ये बदल करा. या सूचना [Redstone Holesky](https://redstone.xyz/docs/network-info) कसे जोडायचे हे स्पष्ट करतात. + +1. viem वरून `defineChain` प्रकार आयात करा. + + ```ts + import { defineChain } from 'viem' + ``` + +2. नेटवर्क व्याख्या जोडा. + + ```ts + const redstoneHolesky = defineChain({ + id: 17_001, + name: 'Redstone Holesky', + network: 'redstone-holesky', + nativeCurrency: { + decimals: 18, + name: 'Ether', + symbol: 'ETH', + }, + rpcUrls: { + default: { + http: ['https://rpc.holesky.redstone.xyz'], + webSocket: ['wss://rpc.holesky.redstone.xyz/ws'], + }, + public: { + http: ['https://rpc.holesky.redstone.xyz'], + webSocket: ['wss://rpc.holesky.redstone.xyz/ws'], + }, + }, + blockExplorers: { + default: { name: 'Explorer', url: 'https://explorer.holesky.redstone.xyz' }, + }, + }) + ``` + +3. `configureChains` कॉलमध्ये नवीन चेन जोडा. + + ```ts + const { chains, publicClient, webSocketPublicClient } = configureChains( + [ holesky, sepolia, redstoneHolesky ], + [ publicProvider(), ], + ) + ``` + +4. ऍप्लिकेशनला नवीन नेटवर्कवर तुमच्या काँट्रॅक्ट्सचा पत्ता माहित असल्याची खात्री करा. या प्रकरणात, आम्ही `src/components/Greeter.tsx` मध्ये बदल करतो: + + ```ts + const contractAddrs : AddressPerBlockchainType = { + // Holesky + 17000: '0x432d810484AdD7454ddb3b5311f0Ac2E95CeceA8', + + // Redstone Holesky + 17001: '0x4919517f82a1B89a32392E1BF72ec827ba9986D3', + + // Sepolia + 11155111: '0x7143d5c190F048C8d19fe325b748b081903E3BF0' + } + ``` + +## निष्कर्ष {#conclusion} + +अर्थात, तुम्हाला `Greeter` साठी युझर इंटरफेस प्रदान करण्याची खरोखर काळजी नाही. तुम्हाला तुमच्या स्वतःच्या काँट्रॅक्ट्ससाठी युझर इंटरफेस तयार करायचा आहे. तुमचे स्वतःचे ऍप्लिकेशन तयार करण्यासाठी, या पायऱ्या चालवा: + +1. wagmi ऍप्लिकेशन तयार करण्यासाठी निर्दिष्ट करा. + + ```sh copy + pnpm create wagmi + ``` + +2. ऍप्लिकेशनला नाव द्या. + +3. **React** फ्रेमवर्क निवडा. + +4. **Vite** व्हेरिएंट निवडा. + +5. तुम्ही [Rainbow kit जोडू शकता](https://www.rainbowkit.com/docs/installation#manual-setup). + +आता जा आणि तुमचे काँट्रॅक्ट्स व्यापक जगासाठी वापरण्यायोग्य बनवा. + +[माझ्या कामाबद्दल अधिक माहितीसाठी येथे पहा](https://cryptodocguy.pro/). + diff --git a/public/content/translations/mr/developers/tutorials/deploying-your-first-smart-contract/index.md b/public/content/translations/mr/developers/tutorials/deploying-your-first-smart-contract/index.md new file mode 100644 index 00000000000..56f0da82b3b --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/deploying-your-first-smart-contract/index.md @@ -0,0 +1,101 @@ +--- +title: "तुमचा पहिला स्मार्ट कॉन्ट्रॅक्ट तैनात करणे" +description: "इथेरियम चाचणी नेटवर्कवर तुमचा पहिला स्मार्ट कॉन्ट्रॅक्ट तैनात करण्याची ओळख" +author: "jdourlens" +tags: + [ + "स्मार्ट कॉन्ट्रॅक्ट", + "रीमिक्स", + "सॉलिडिटी", + "डिप्लॉयिंग" + ] +skill: beginner +lang: mr +published: 2020-04-03 +source: EthereumDev +sourceUrl: https://ethereumdev.io/deploying-your-first-smart-contract/ +address: "0x19dE91Af973F404EDF5B4c093983a7c6E3EC8ccE" +--- + +मला वाटते की तुम्ही इथेरियम ब्लॉकचेनवर तुमच्या पहिल्या [स्मार्ट कॉन्ट्रॅक्टसोबत](/developers/docs/smart-contracts/) संवाद साधण्यासाठी आणि [तैनात करण्यासाठी](/developers/docs/smart-contracts/deploying/) आमच्याइतकेच उत्सुक आहात. + +काळजी करू नका, कारण हा आपला पहिला स्मार्ट कॉन्ट्रॅक्ट आहे, आम्ही तो [स्थानिक चाचणी नेटवर्कवर](/developers/docs/networks/) तैनात करू, त्यामुळे तुम्हाला तो तैनात करण्यासाठी आणि त्याच्यासोबत हवा तितका खेळण्यासाठी काहीही खर्च येणार नाही. + +## आपला कॉन्ट्रॅक्ट लिहिणे {#writing-our-contract} + +पहिली पायरी म्हणजे [Remix ला भेट देणे](https://remix.ethereum.org/) आणि एक नवीन फाईल तयार करणे. Remix इंटरफेसच्या वरच्या डाव्या भागात एक नवीन फाईल जोडा आणि तुम्हाला हवं असलेलं फाईल नाव टाका. + +![Remix इंटरफेसमध्ये एक नवीन फाईल जोडणे](./remix.png) + +नवीन फाईलमध्ये, आम्ही खालील कोड पेस्ट करू. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity >=0.5.17; + +contract Counter { + + // गणनेची संख्या ठेवण्यासाठी unsigned int प्रकाराचे सार्वजनिक व्हेरिएबल + uint256 public count = 0; + + // आमचा काउंटर वाढवणारे फंक्शन + function increment() public { + count += 1; + } + + // गणनेचे मूल्य मिळवण्यासाठी अनावश्यक गेटर + function getCount() public view returns (uint256) { + return count; + } + +} +``` + +तुम्हाला प्रोग्रामिंगची सवय असल्यास, हा प्रोग्राम काय करतो याचा तुम्ही सहज अंदाज लावू शकता. येथे ओळीनुसार स्पष्टीकरण दिले आहे: + +- ओळ 4: आम्ही `Counter` नावाने एक कॉन्ट्रॅक्ट परिभाषित करतो. +- ओळ 7: आमचा कॉन्ट्रॅक्ट 0 पासून सुरू होणारा `count` नावाचा एक अनसाईंड इंटिजर संग्रहित करतो. +- ओळ 10: पहिले फंक्शन कॉन्ट्रॅक्टच्या स्टेटमध्ये बदल करेल आणि आमचे `count` व्हेरिएबल `increment()` करेल. +- दुसरे फंक्शन फक्त एक गेटर आहे जे स्मार्ट कॉन्ट्रॅक्टच्या बाहेर `count` व्हेरिएबलचे मूल्य वाचण्यास सक्षम करते. लक्षात घ्या की, आम्ही आमचे `count` व्हेरिएबल सार्वजनिक म्हणून परिभाषित केल्यामुळे हे आवश्यक नाही परंतु ते उदाहरण म्हणून दाखवले आहे. + +आमच्या पहिल्या सोप्या स्मार्ट कॉन्ट्रॅक्टसाठी एवढेच आहे. तुम्हाला माहीत असेलच, हे Java किंवा C++ सारख्या OOP (ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग) भाषांमधील क्लाससारखे दिसते. आता आमच्या कॉन्ट्रॅक्टसोबत खेळण्याची वेळ आली आहे. + +## आपला कॉन्ट्रॅक्ट तैनात करणे {#deploying-our-contract} + +आपण आपला पहिला स्मार्ट कॉन्ट्रॅक्ट लिहिला असल्यामुळे, आता आपण त्याच्यासोबत खेळण्यासाठी तो ब्लॉकचेनवर तैनात करू. + +[ब्लॉकचेनवर स्मार्ट कॉन्ट्रॅक्ट तैनात करणे](/developers/docs/smart-contracts/deploying/) म्हणजे प्रत्यक्षात कोणतेही प्राप्तकर्ते निर्दिष्ट न करता संकलित स्मार्ट कॉन्ट्रॅक्टचा कोड असलेला व्यवहार पाठवणे. + +आपण प्रथम डाव्या बाजूला असलेल्या कंपाइल आयकॉनवर क्लिक करून [कॉन्ट्रॅक्ट कंपाइल करू](/developers/docs/smart-contracts/compiling/): + +![Remix टूलबारमधील कंपाइल आयकॉन](./remix-compile-button.png) + +नंतर कंपाइल बटणावर क्लिक करा: + +![Remix सॉलिडिटी कंपाइलरमधील कंपाइल बटण](./remix-compile.png) + +तुम्ही "ऑटो कंपाइल" पर्याय निवडू शकता जेणेकरून तुम्ही टेक्स्ट एडिटरवर सामग्री सेव्ह करता तेव्हा कॉन्ट्रॅक्ट नेहमी कंपाइल होईल. + +नंतर "तैनात करा आणि व्यवहार चालवा" स्क्रीनवर नेव्हिगेट करा: + +![Remix टूलबारमधील तैनात आयकॉन](./remix-deploy.png) + +एकदा तुम्ही "तैनात करा आणि व्यवहार चालवा" स्क्रीनवर आलात की, तुमच्या कॉन्ट्रॅक्टचे नाव दिसत असल्याची खात्री करा आणि तैनात करा वर क्लिक करा. तुम्ही पृष्ठाच्या शीर्षस्थानी पाहू शकता की, सध्याचे वातावरण "JavaScript VM" आहे, याचा अर्थ असा की जलद आणि कोणत्याही शुल्काशिवाय चाचणी घेण्यासाठी आम्ही स्थानिक चाचणी ब्लॉकचेनवर आपला स्मार्ट कॉन्ट्रॅक्ट तैनात करू आणि त्याच्याशी संवाद साधू. + +![Remix सॉलिडिटी कंपाइलरमधील तैनात बटण](./remix-deploy-button.png) + +एकदा तुम्ही "तैनात करा" बटणावर क्लिक केल्यावर, तुम्हाला तुमचा कॉन्ट्रॅक्ट तळाशी दिसेल. त्याचा विस्तार करण्यासाठी डावीकडील बाणावर क्लिक करा जेणेकरून आम्हाला आमच्या कॉन्ट्रॅक्टची सामग्री दिसेल. हे आमचे व्हेरिएबल `counter`, आमचे `increment()` फंक्शन आणि गेटर `getCounter()` आहे. + +तुम्ही `count` किंवा `getCount` बटणावर क्लिक केल्यास, ते प्रत्यक्षात कॉन्ट्रॅक्टच्या `count` व्हेरिएबलची सामग्री प्राप्त करेल आणि प्रदर्शित करेल. आपण अद्याप `increment` फंक्शनला कॉल केलेला नसल्यामुळे, ते 0 प्रदर्शित करेल. + +![Remix सॉलिडिटी कंपाइलरमधील फंक्शन बटण](./remix-function-button.png) + +आता बटणावर क्लिक करून `increment` फंक्शनला कॉल करूया. तुम्हाला विंडोच्या तळाशी झालेल्या व्यवहारांचे लॉग दिसतील. तुम्ही `increment` बटणाऐवजी डेटा पुनर्प्राप्त करण्यासाठी बटण दाबत असाल तेव्हा लॉग वेगळे असल्याचे तुम्हाला दिसेल. कारण ब्लॉकचेनवर डेटा वाचण्यासाठी कोणत्याही व्यवहारांची (लिखाण) किंवा शुल्काची आवश्यकता नसते. कारण फक्त ब्लॉकचेनच्या स्टेटमध्ये बदल करण्यासाठी व्यवहार करणे आवश्यक आहे: + +![व्यवहारांचा लॉग](./transaction-log.png) + +आपल्या `increment()` फंक्शनला कॉल करण्यासाठी व्यवहार निर्माण करणारे इंक्रीमेंट बटण दाबल्यानंतर, आपण काउंट किंवा गेटकाउंट बटणावर परत क्लिक केल्यास, आपल्याला आपल्या स्मार्ट कॉन्ट्रॅक्टची नवीन अपडेटेड स्टेट वाचायला मिळेल, ज्यात काउंट व्हेरिएबल 0 पेक्षा मोठे असेल. + +![स्मार्ट कॉन्ट्रॅक्टची नवीन अपडेटेड स्टेट](./updated-state.png) + +पुढील ट्युटोरियलमध्ये, आपण [आपल्या स्मार्ट कॉन्ट्रॅक्टमध्ये इव्हेंट्स कसे जोडू शकता](/developers/tutorials/logging-events-smart-contracts/) हे पाहू. लॉगिंग इव्हेंट्स हा तुमचा स्मार्ट कॉन्ट्रॅक्ट डीबग करण्याचा आणि फंक्शन कॉल करताना काय होत आहे हे समजून घेण्याचा एक सोयीस्कर मार्ग आहे. diff --git a/public/content/translations/mr/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md b/public/content/translations/mr/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md new file mode 100644 index 00000000000..5e53eaf3cfc --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/develop-and-test-dapps-with-a-multi-client-local-eth-testnet/index.md @@ -0,0 +1,372 @@ +--- +title: "स्थानिक, मल्टी-क्लायंट टेस्टनेटवर dApp कसे विकसित आणि चाचणी करावे" +description: "हे मार्गदर्शक तुम्हाला dApp तैनात आणि चाचणी करण्यासाठी टेस्टनेट वापरण्यापूर्वी, मल्टी-क्लायंट स्थानिक Ethereum टेस्टनेट कसे इन्स्टॅन्शिएट आणि कॉन्फिगर करावे यासाठी मार्गदर्शन करेल." +author: "Tedi Mitiku" +tags: + [ + "क्लायंट्स", + "नोड्स", + "स्मार्ट कॉन्ट्रॅक्ट", + "कंपोझेबिलिटी", + "कन्सेंसस लेयर", + "एक्झिक्यूशन लेयर", + "चाचणी" + ] +skill: intermediate +lang: mr +published: 2023-04-11 +--- + +## प्रस्तावना {#introduction} + +हे मार्गदर्शक तुम्हाला कॉन्फिगर करण्यायोग्य स्थानिक Ethereum टेस्टनेट इन्स्टॅन्शिएट करणे, त्यावर एक स्मार्ट कॉन्ट्रॅक्ट तैनात करणे आणि तुमच्या dApp विरुद्ध चाचण्या चालवण्यासाठी टेस्टनेट वापरण्याच्या प्रक्रियेत मार्गदर्शन करते. हे मार्गदर्शक अशा dApp डेव्हलपर्ससाठी डिझाइन केले आहे ज्यांना लाइव्ह टेस्टनेट किंवा मेननेटवर तैनात करण्यापूर्वी त्यांचे dApps स्थानिक पातळीवर वेगवेगळ्या नेटवर्क कॉन्फिगरेशनवर विकसित आणि चाचणी करायचे आहेत. + +या मार्गदर्शकामध्ये, तुम्ही हे कराल: + +- [Kurtosis](https://www.kurtosis.com/) वापरून [`eth-network-package`](https://github.com/kurtosis-tech/eth-network-package) सह स्थानिक Ethereum टेस्टनेट इन्स्टॅन्शिएट करा, +- dApp कंपाईल, तैनात आणि चाचणी करण्यासाठी तुमचे Hardhat dApp डेव्हलपमेंट एन्व्हायर्नमेंट स्थानिक टेस्टनेटशी कनेक्ट करा, आणि +- विविध नेटवर्क कॉन्फिगरेशनवर डेव्हलपमेंट आणि टेस्टिंग वर्कफ्लो सक्षम करण्यासाठी, नोड्सची संख्या आणि विशिष्ट EL/CL क्लायंट पेअरिंग्ज यासारख्या पॅरामीटर्ससह स्थानिक टेस्टनेट कॉन्फिगर करा. + +### Kurtosis काय आहे? {#what-is-kurtosis} + +[Kurtosis](https://www.kurtosis.com/) ही मल्टी-कंटेनर चाचणी एन्व्हायर्नमेंट कॉन्फिगर करण्यासाठी डिझाइन केलेली एक कंपोझेबल बिल्ड सिस्टीम आहे. हे विशेषतः डेव्हलपर्सना पुनरुत्पादक एन्व्हायर्नमेंट तयार करण्यास सक्षम करते ज्यांना डायनॅमिक सेटअप लॉजिकची आवश्यकता असते, जसे की ब्लॉकचेन टेस्टनेट्स. + +या मार्गदर्शकामध्ये, Kurtosis eth-network-package [`geth`](https://geth.ethereum.org/) एक्झिक्यूशन लेअर (EL) क्लायंट, तसेच [`teku`](https://consensys.io/teku), [`lighthouse`](https://lighthouse.sigmaprime.io/), आणि [`lodestar`](https://lodestar.chainsafe.io/) कन्सेंसस लेअर (CL) क्लायंट्सच्या सपोर्टसह एक स्थानिक Ethereum टेस्टनेट सुरू करतो. हे पॅकेज Hardhat Network, Ganache, आणि Anvil सारख्या फ्रेमवर्कमधील नेटवर्क्ससाठी एक कॉन्फिगर करण्यायोग्य आणि कंपोझेबल पर्याय म्हणून काम करते. Kurtosis डेव्हलपर्सना ते वापरत असलेल्या टेस्टनेट्सवर अधिक नियंत्रण आणि लवचिकता देते, आणि हे एक प्रमुख कारण आहे की [Ethereum फाउंडेशनने द मर्जची चाचणी घेण्यासाठी Kurtosis चा वापर केला](https://www.kurtosis.com/blog/testing-the-ethereum-merge) आणि नेटवर्क अपग्रेडच्या चाचणीसाठी त्याचा वापर सुरू ठेवला आहे. + +## Kurtosis सेटअप करणे {#setting-up-kurtosis} + +पुढे जाण्यापूर्वी, तुमच्याकडे हे असल्याची खात्री करा: + +- तुमच्या स्थानिक मशीनवर [डॉकर इंजिन इंस्टॉल आणि सुरू केले आहे](https://docs.kurtosis.com/install/#i-install--start-docker) +- [Kurtosis CLI इंस्टॉल केले आहे](https://docs.kurtosis.com/install#ii-install-the-cli) (किंवा तुमच्याकडे आधीच CLI इंस्टॉल असल्यास, ते नवीनतम रिलीझवर अपग्रेड केले आहे) +- [Node.js](https://nodejs.org/en), [yarn](https://classic.yarnpkg.com/lang/en/docs/install/#mac-stable), आणि [npx](https://www.npmjs.com/package/npx) (तुमच्या dApp एन्व्हायर्नमेंटसाठी) इंस्टॉल केले आहे + +## स्थानिक Ethereum टेस्टनेट इन्स्टॅन्शिएट करणे {#instantiate-testnet} + +स्थानिक Ethereum टेस्टनेट सुरू करण्यासाठी, चालवा: + +```python +kurtosis --enclave local-eth-testnet run github.com/kurtosis-tech/eth-network-package +``` + +टीप: ही कमांड `--enclave` फ्लॅग वापरून तुमच्या नेटवर्कला नाव देते: "local-eth-testnet". + +Kurtosis सूचनांचा अर्थ लावणे, प्रमाणित करणे आणि नंतर कार्यान्वित करण्याचे काम करत असताना पडद्यामागे घेत असलेले टप्पे प्रिंट करेल. शेवटी, तुम्हाला खालीलप्रमाणे दिसणारे आउटपुट दिसेल: + +```python +INFO[2023-04-04T18:09:44-04:00] ====================================================== +INFO[2023-04-04T18:09:44-04:00] || Created enclave: local-eth-testnet || +INFO[2023-04-04T18:09:44-04:00] ====================================================== +Name: local-eth-testnet +UUID: 39372d756ae8 +Status: RUNNING +Creation Time: Tue, 04 Apr 2023 18:09:03 EDT + +========================================= Files Artifacts ========================================= +UUID Name +d4085a064230 cl-genesis-data +1c62cb792e4c el-genesis-data +bd60489b73a7 genesis-generation-config-cl +b2e593fe5228 genesis-generation-config-el +d552a54acf78 geth-prefunded-keys +5f7e661eb838 prysm-password +054e7338bb59 validator-keystore-0 + +========================================== User Services ========================================== +UUID Name Ports Status +e20f129ee0c5 cl-client-0-beacon http: 4000/tcp -> RUNNING + metrics: 5054/tcp -> + tcp-discovery: 9000/tcp -> 127.0.0.1:54263 + udp-discovery: 9000/udp -> 127.0.0.1:60470 +a8b6c926cdb4 cl-client-0-validator http: 5042/tcp -> 127.0.0.1:54267 RUNNING + metrics: 5064/tcp -> +d7b802f623e8 el-client-0 engine-rpc: 8551/tcp -> 127.0.0.1:54253 RUNNING + rpc: 8545/tcp -> 127.0.0.1:54251 + tcp-discovery: 30303/tcp -> 127.0.0.1:54254 + udp-discovery: 30303/udp -> 127.0.0.1:53834 + ws: 8546/tcp -> 127.0.0.1:54252 +514a829c0a84 prelaunch-data-generator-1680646157905431468 STOPPED +62bd62d0aa7a prelaunch-data-generator-1680646157915424301 STOPPED +05e9619e0e90 prelaunch-data-generator-1680646157922872635 STOPPED + +``` + +अभिनंदन! तुम्ही Docker वर, एका CL (`lighthouse`) आणि EL क्लायंट (`geth`) सह स्थानिक Ethereum टेस्टनेट इन्स्टॅन्शिएट करण्यासाठी Kurtosis वापरले. + +### पुनरावलोकन {#review-instantiate-testnet} + +या विभागात, तुम्ही एक कमांड कार्यान्वित केली जी Kurtosis [Enclave](https://docs.kurtosis.com/advanced-concepts/enclaves/) मध्ये स्थानिक Ethereum टेस्टनेट सुरू करण्यासाठी GitHub वर दूरस्थपणे होस्ट केलेल्या [`eth-network-package`](https://github.com/kurtosis-tech/eth-network-package) चा वापर करण्यास निर्देशित करते. तुमच्या एन्क्लेव्हमध्ये, तुम्हाला "फाइल आर्टिफॅक्ट्स" आणि "यूझर सर्व्हिसेस" दोन्ही आढळतील. + +तुमच्या एन्क्लेव्हमधील [फाइल आर्टिफॅक्ट्स](https://docs.kurtosis.com/advanced-concepts/files-artifacts/) मध्ये EL आणि CL क्लायंट बूटस्ट्रॅप करण्यासाठी तयार केलेला आणि वापरलेला सर्व डेटा समाविष्ट आहे. हा डेटा या [डॉकर इमेज](https://github.com/ethpandaops/ethereum-genesis-generator) पासून बनवलेल्या `prelaunch-data-generator` सेवेचा वापर करून तयार केला गेला आहे. + +यूझर सर्व्हिसेस तुमच्या एन्क्लेव्हमध्ये कार्यरत असलेल्या सर्व कंटेनराइज्ड सेवा प्रदर्शित करतात. तुमच्या लक्षात येईल की एकच नोड, ज्यामध्ये EL क्लायंट आणि CL क्लायंट दोन्ही आहेत, तयार केला गेला आहे. + +## तुमचे dApp डेव्हलपमेंट एन्व्हायर्नमेंट स्थानिक Ethereum टेस्टनेटशी कनेक्ट करा {#connect-your-dapp} + +### dApp डेव्हलपमेंट एन्व्हायर्नमेंट सेटअप करा {#set-up-dapp-env} + +आता तुमच्याकडे एक चालू स्थानिक टेस्टनेट असल्यामुळे, तुम्ही तुमचा स्थानिक टेस्टनेट वापरण्यासाठी तुमचे dApp डेव्हलपमेंट एन्व्हायर्नमेंट कनेक्ट करू शकता. या मार्गदर्शकामध्ये तुमच्या स्थानिक टेस्टनेटवर एक ब्लॅकजॅक dApp तैनात करण्यासाठी Hardhat फ्रेमवर्कचा वापर केला जाईल. + +तुमचे dApp डेव्हलपमेंट एन्व्हायर्नमेंट सेटअप करण्यासाठी, आमचे सॅम्पल dApp असलेल्या रिपॉझिटरीला क्लोन करा आणि त्याच्या डिपेन्डन्सीज इंस्टॉल करा, चालवा: + +```python +git clone https://github.com/kurtosis-tech/awesome-kurtosis.git && cd awesome-kurtosis/smart-contract-example && yarn +``` + +येथे वापरलेल्या [smart-contract-example](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example) फोल्डरमध्ये [Hardhat](https://hardhat.org/) फ्रेमवर्क वापरणाऱ्या dApp डेव्हलपरसाठी एक सामान्य सेटअप आहे: + +- [`contracts/`](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example/contracts) मध्ये ब्लॅकजॅक dApp साठी काही सोपे स्मार्ट कॉन्ट्रॅक्ट्स आहेत +- [`scripts/`](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example/scripts) मध्ये तुमच्या स्थानिक Ethereum नेटवर्कवर टोकन कॉन्ट्रॅक्ट तैनात करण्यासाठी एक स्क्रिप्ट आहे +- [`test/`](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/smart-contract-example/test) मध्ये तुमच्या टोकन कॉन्ट्रॅक्टसाठी एक सोपी .js चाचणी आहे, जी निश्चित करते की आमच्या ब्लॅकजॅक dApp मधील प्रत्येक खेळाडूसाठी 1000 मिंट केले आहेत +- [`hardhat.config.ts`](https://github.com/kurtosis-tech/awesome-kurtosis/blob/main/smart-contract-example/hardhat.config.ts) तुमचा Hardhat सेटअप कॉन्फिगर करते + +### स्थानिक टेस्टनेट वापरण्यासाठी Hardhat कॉन्फिगर करा {#configure-hardhat} + +तुमचे dApp डेव्हलपमेंट एन्व्हायर्नमेंट सेटअप झाल्यावर, तुम्ही आता Kurtosis वापरून तयार केलेला स्थानिक Ethereum टेस्टनेट वापरण्यासाठी Hardhat कनेक्ट कराल. हे पूर्ण करण्यासाठी, तुमच्या `hardhat.config.ts` कॉन्फिग फाइलमधील `localnet` स्ट्रक्टमध्ये `<$YOUR_PORT>` च्या जागी कोणत्याही `el-client-` सेवेच्या rpc uri आउटपुटचा पोर्ट टाका. या नमुना केसमध्ये, पोर्ट `64248` असेल. तुमचा पोर्ट वेगळा असेल. + +`hardhat.config.ts` मधील उदाहरण: + +```js +localnet: { +url: 'http://127.0.0.1:<$YOUR_PORT>',// TODO: $YOUR_PORT च्या जागी ETH नेटवर्क KURTOSIS पॅकेजद्वारे तयार केलेल्या नोड URI चा पोर्ट टाका + +// हे eth-network-package द्वारे तयार केलेल्या प्रीफंडेड टेस्ट अकाउंट्सशी संबंधित प्रायव्हेट की आहेत +// +accounts: [ + "ef5177cd0b6b21c87db5a0bf35d4084a8a57a9d6a064f86d51ac85f2b873a4e2", + "48fcc39ae27a0e8bf0274021ae6ebd8fe4a0e12623d61464c498900b28feb567", + "7988b3a148716ff800414935b305436493e1f25237a2a03e5eebc343735e2f31", + "b3c409b6b0b3aa5e65ab2dc1930534608239a478106acf6f3d9178e9f9b00b35", + "df9bb6de5d3dc59595bcaa676397d837ff49441d211878c024eabda2cd067c9f", + "7da08f856b5956d40a72968f93396f6acff17193f013e8053f6fbb6c08c194d6", + ], +}, +``` + +एकदा तुम्ही तुमची फाइल सेव्ह केली की, तुमचे Hardhat dApp डेव्हलपमेंट एन्व्हायर्नमेंट आता तुमच्या स्थानिक Ethereum टेस्टनेटशी कनेक्ट झाले आहे! तुम्ही हे चालवून तुमचा टेस्टनेट कार्यरत असल्याची खात्री करू शकता: + +```python +npx hardhat balances --network localnet +``` + +आउटपुट काहीसे असे दिसेल: + +```python +0x878705ba3f8Bc32FCf7F4CAa1A35E72AF65CF766 has balance 10000000000000000000000000 +0x4E9A3d9D1cd2A2b2371b8b3F489aE72259886f1A has balance 10000000000000000000000000 +0xdF8466f277964Bb7a0FFD819403302C34DCD530A has balance 10000000000000000000000000 +0x5c613e39Fc0Ad91AfDA24587e6f52192d75FBA50 has balance 10000000000000000000000000 +0x375ae6107f8cC4cF34842B71C6F746a362Ad8EAc has balance 10000000000000000000000000 +0x1F6298457C5d76270325B724Da5d1953923a6B88 has balance 10000000000000000000000000 +``` + +हे निश्चित करते की Hardhat तुमचा स्थानिक टेस्टनेट वापरत आहे आणि `eth-network-package` द्वारे तयार केलेली प्री-फंडेड अकाउंट्स शोधत आहे. + +### तुमचे dApp स्थानिक पातळीवर तैनात आणि चाचणी करा {#deploy-and-test-dapp} + +dApp डेव्हलपमेंट एन्व्हायर्नमेंट स्थानिक Ethereum टेस्टनेटशी पूर्णपणे कनेक्ट झाल्यावर, तुम्ही आता स्थानिक टेस्टनेट वापरून तुमच्या dApp वर डेव्हलपमेंट आणि टेस्टिंग वर्कफ्लो चालवू शकता. + +`ChipToken.sol` स्मार्ट कॉन्ट्रॅक्ट स्थानिक प्रोटोटाइपिंग आणि डेव्हलपमेंटसाठी कंपाईल आणि तैनात करण्यासाठी, चालवा: + +```python +npx hardhat compile +npx hardhat run scripts/deploy.ts --network localnet +``` + +आउटपुट काहीसे असे दिसेल: + +```python +ChipToken deployed to: 0xAb2A01BC351770D09611Ac80f1DE076D56E0487d +``` + +आता तुमच्या स्थानिक dApp वर `simple.js` चाचणी चालवून हे निश्चित करा की आमच्या ब्लॅकजॅक dApp मधील प्रत्येक खेळाडूसाठी 1000 मिंट केले आहेत: + +आउटपुट काहीसे असे दिसेल: + +```python +npx hardhat test --network localnet +``` + +आउटपुट काहीसे असे दिसेल: + +```python +ChipToken + mint + ✔ PLAYER ONE साठी 1000 चिप्स मिंट केले पाहिजेत + + 1 उत्तीर्ण (654ms) +``` + +### पुनरावलोकन {#review-dapp-workflows} + +या टप्प्यावर, तुम्ही आता एक dApp डेव्हलपमेंट एन्व्हायर्नमेंट सेटअप केले आहे, ते Kurtosis द्वारे तयार केलेल्या स्थानिक Ethereum नेटवर्कशी कनेक्ट केले आहे, आणि तुमच्या dApp वर एक सोपी चाचणी कंपाईल, तैनात आणि चालवली आहे. + +आता आपण पाहूया की वेगवेगळ्या नेटवर्क कॉन्फिगरेशनमध्ये आमचे dApps चाचणीसाठी तुम्ही मूळ नेटवर्क कसे कॉन्फिगर करू शकता. + +## स्थानिक Ethereum टेस्टनेट कॉन्फिगर करणे {#configure-testnet} + +### क्लायंट कॉन्फिगरेशन आणि नोड्सची संख्या बदलणे {#configure-client-config-and-num-nodes} + +तुमचा स्थानिक Ethereum टेस्टनेट तुम्ही कोणत्या परिस्थितीत आणि कोणत्या विशिष्ट नेटवर्क कॉन्फिगरेशनवर विकसित किंवा चाचणी करू इच्छिता यावर अवलंबून, वेगवेगळे EL आणि CL क्लायंट पेअर्स तसेच वेगवेगळ्या संख्येने नोड्स वापरण्यासाठी कॉन्फिगर केला जाऊ शकतो. याचा अर्थ, एकदा सेटअप झाल्यावर, तुम्ही एक सानुकूलित स्थानिक टेस्टनेट सुरू करू शकता आणि तेच वर्कफ्लो (तैनाती, चाचण्या, इत्यादी) चालवण्यासाठी त्याचा वापर करू शकता. सर्वकाही अपेक्षेप्रमाणे कार्य करते याची खात्री करण्यासाठी विविध नेटवर्क कॉन्फिगरेशन अंतर्गत. तुम्ही सुधारित करू शकता अशा इतर पॅरामीटर्सबद्दल अधिक जाणून घेण्यासाठी, या लिंकला भेट द्या. + +प्रयत्न करून पहा! तुम्ही एका JSON फाइलद्वारे `eth-network-package` ला विविध कॉन्फिगरेशन पर्याय पास करू शकता. ही नेटवर्क पॅराम्स JSON फाइल विशिष्ट कॉन्फिगरेशन्स प्रदान करते जे Kurtosis स्थानिक Ethereum नेटवर्क सेटअप करण्यासाठी वापरेल. + +डीफॉल्ट कॉन्फिगरेशन फाइल घ्या आणि ती वेगवेगळ्या EL/CL पेअर्ससह तीन नोड्स सुरू करण्यासाठी संपादित करा: + +- नोड 1 `geth`/`lighthouse` सह +- नोड 2 `geth`/`lodestar` सह +- नोड 3 `geth`/`teku` सह + +हे कॉन्फिगरेशन तुमच्या dApp च्या चाचणीसाठी Ethereum नोड अंमलबजावणीचे एक विषम नेटवर्क तयार करते. तुमची कॉन्फिगरेशन फाइल आता अशी दिसली पाहिजे: + +```yaml +{ + "participants": + [ + { + "el_client_type": "geth", + "el_client_image": "", + "el_client_log_level": "", + "cl_client_type": "lighthouse", + "cl_client_image": "", + "cl_client_log_level": "", + "beacon_extra_params": [], + "el_extra_params": [], + "validator_extra_params": [], + "builder_network_params": null, + }, + { + "el_client_type": "geth", + "el_client_image": "", + "el_client_log_level": "", + "cl_client_type": "lodestar", + "cl_client_image": "", + "cl_client_log_level": "", + "beacon_extra_params": [], + "el_extra_params": [], + "validator_extra_params": [], + "builder_network_params": null, + }, + { + "el_client_type": "geth", + "el_client_image": "", + "el_client_log_level": "", + "cl_client_type": "teku", + "cl_client_image": "", + "cl_client_log_level": "", + "beacon_extra_params": [], + "el_extra_params": [], + "validator_extra_params": [], + "builder_network_params": null, + }, + ], + "network_params": + { + "preregistered_validator_keys_mnemonic": "giant issue aisle success illegal bike spike question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy very lucky have athlete", + "num_validator_keys_per_node": 64, + "network_id": "3151908", + "deposit_contract_address": "0x4242424242424242424242424242424242424242", + "seconds_per_slot": 12, + "genesis_delay": 120, + "capella_fork_epoch": 5, + }, +} +``` + +प्रत्येक `participants` स्ट्रक्ट नेटवर्कमधील एका नोडला मॅप करतो, म्हणून 3 `participants` स्ट्रक्ट्स Kurtosis ला तुमच्या नेटवर्कमध्ये 3 नोड्स सुरू करण्यास सांगतील. प्रत्येक `participants` स्ट्रक्ट तुम्हाला त्या विशिष्ट नोडसाठी वापरलेली EL आणि CL जोडी निर्दिष्ट करण्याची परवानगी देईल. + +`network_params` स्ट्रक्ट नेटवर्क सेटिंग्ज कॉन्फिगर करतो ज्या प्रत्येक नोडसाठी जेनेसिस फाइल्स तयार करण्यासाठी वापरल्या जातात, तसेच नेटवर्कच्या प्रति स्लॉट सेकंद यासारख्या इतर सेटिंग्ज. + +तुमची संपादित पॅराम्स फाइल तुम्हाला पाहिजे त्या डिरेक्टरीमध्ये सेव्ह करा (खालील उदाहरणात, ती डेस्कटॉपवर सेव्ह केली आहे) आणि नंतर तुमचे Kurtosis पॅकेज चालवण्यासाठी खालील कमांड चालवून त्याचा वापर करा: + +```python +kurtosis clean -a && kurtosis run --enclave local-eth-testnet github.com/kurtosis-tech/eth-network-package "$(cat ~/eth-network-params.json)" +``` + +टीप: `kurtosis clean -a` कमांड येथे Kurtosis ला नवीन टेस्टनेट सुरू करण्यापूर्वी जुने टेस्टनेट आणि त्यातील सामग्री नष्ट करण्याचा निर्देश देण्यासाठी वापरली आहे. + +पुन्हा, Kurtosis थोडा वेळ काम करेल आणि होत असलेले वैयक्तिक टप्पे प्रिंट करेल. अखेरीस, आउटपुट काहीसे असे दिसेल: + +```python +Starlark कोड यशस्वीरित्या चालला. कोणतेही आउटपुट परत आले नाही. +INFO[2023-04-07T11:43:16-04:00] ========================================================== +INFO[2023-04-07T11:43:16-04:00] || Created enclave: local-eth-testnet || +INFO[2023-04-07T11:43:16-04:00] ========================================================== +Name: local-eth-testnet +UUID: bef8c192008e +Status: RUNNING +Creation Time: Fri, 07 Apr 2023 11:41:58 EDT + +========================================= Files Artifacts ========================================= +UUID Name +cc495a8e364a cl-genesis-data +7033fcdb5471 el-genesis-data +a3aef43fc738 genesis-generation-config-cl +8e968005fc9d genesis-generation-config-el +3182cca9d3cd geth-prefunded-keys +8421166e234f prysm-password +d9e6e8d44d99 validator-keystore-0 +23f5ba517394 validator-keystore-1 +4d28dea40b5c validator-keystore-2 + +========================================== User Services ========================================== +UUID Name Ports Status +485e6fde55ae cl-client-0-beacon http: 4000/tcp -> http://127.0.0.1:65010 RUNNING + metrics: 5054/tcp -> http://127.0.0.1:65011 + tcp-discovery: 9000/tcp -> 127.0.0.1:65012 + udp-discovery: 9000/udp -> 127.0.0.1:54455 +73739bd158b2 cl-client-0-validator http: 5042/tcp -> 127.0.0.1:65016 RUNNING + metrics: 5064/tcp -> http://127.0.0.1:65017 +1b0a233cd011 cl-client-1-beacon http: 4000/tcp -> 127.0.0.1:65021 RUNNING + metrics: 8008/tcp -> 127.0.0.1:65023 + tcp-discovery: 9000/tcp -> 127.0.0.1:65024 + udp-discovery: 9000/udp -> 127.0.0.1:56031 + validator-metrics: 5064/tcp -> 127.0.0.1:65022 +949b8220cd53 cl-client-1-validator http: 4000/tcp -> 127.0.0.1:65028 RUNNING + metrics: 8008/tcp -> 127.0.0.1:65030 + tcp-discovery: 9000/tcp -> 127.0.0.1:65031 + udp-discovery: 9000/udp -> 127.0.0.1:60784 + validator-metrics: 5064/tcp -> 127.0.0.1:65029 +c34417bea5fa cl-client-2 http: 4000/tcp -> 127.0.0.1:65037 RUNNING + metrics: 8008/tcp -> 127.0.0.1:65035 + tcp-discovery: 9000/tcp -> 127.0.0.1:65036 + udp-discovery: 9000/udp -> 127.0.0.1:63581 +e19738e6329d el-client-0 engine-rpc: 8551/tcp -> 127.0.0.1:64986 RUNNING + rpc: 8545/tcp -> 127.0.0.1:64988 + tcp-discovery: 30303/tcp -> 127.0.0.1:64987 + udp-discovery: 30303/udp -> 127.0.0.1:55706 + ws: 8546/tcp -> 127.0.0.1:64989 +e904687449d9 el-client-1 engine-rpc: 8551/tcp -> 127.0.0.1:64993 RUNNING + rpc: 8545/tcp -> 127.0.0.1:64995 + tcp-discovery: 30303/tcp -> 127.0.0.1:64994 + udp-discovery: 30303/udp -> 127.0.0.1:58096 + ws: 8546/tcp -> 127.0.0.1:64996 +ad6f401126fa el-client-2 engine-rpc: 8551/tcp -> 127.0.0.1:65003 RUNNING + rpc: 8545/tcp -> 127.0.0.1:65001 + tcp-discovery: 30303/tcp -> 127.0.0.1:65000 + udp-discovery: 30303/udp -> 127.0.0.1:57269 + ws: 8546/tcp -> 127.0.0.1:65002 +12d04a9dbb69 prelaunch-data-generator-1680882122181135513 STOPPED +5b45f9c0504b prelaunch-data-generator-1680882122192182847 STOPPED +3d4aaa75e218 prelaunch-data-generator-1680882122201668972 STOPPED +``` + +अभिनंदन! तुम्ही तुमचे स्थानिक टेस्टनेट 1 ऐवजी 3 नोड्स ठेवण्यासाठी यशस्वीरित्या कॉन्फिगर केले आहे. तुमच्या dApp वर तुम्ही पूर्वी केलेले तेच वर्कफ्लो (तैनात आणि चाचणी) चालवण्यासाठी, तुमच्या `hardhat.config.ts` कॉन्फिग फाइलमधील `localnet` स्ट्रक्टमध्ये `<$YOUR_PORT>` च्या जागी तुमच्या नवीन, 3-नोड स्थानिक टेस्टनेटमधील कोणत्याही `el-client-` सेवेच्या rpc uri आउटपुटचा पोर्ट टाकून आम्ही पूर्वी केलेल्या त्याच क्रिया करा. + +## निष्कर्ष {#conclusion} + +आणि झाले! या छोट्या मार्गदर्शकाचा सारांश, तुम्ही: + +- Kurtosis वापरून Docker वर एक स्थानिक Ethereum टेस्टनेट तयार केले +- तुमचे स्थानिक dApp डेव्हलपमेंट एन्व्हायर्नमेंट स्थानिक Ethereum नेटवर्कशी कनेक्ट केले +- स्थानिक Ethereum नेटवर्कवर एक dApp तैनात केले आणि त्यावर एक सोपी चाचणी चालवली +- मूळ Ethereum नेटवर्कला 3 नोड्स ठेवण्यासाठी कॉन्फिगर केले + +तुमच्यासाठी काय चांगले झाले, काय सुधारले जाऊ शकते, यावर आम्हाला तुमच्याकडून ऐकायला आवडेल, किंवा तुमच्या कोणत्याही प्रश्नांची उत्तरे द्यायला आवडेल. [GitHub](https://github.com/kurtosis-tech/kurtosis/issues/new/choose) द्वारे किंवा [आम्हाला ईमेल करा](mailto:feedback@kurtosistech.com) यावर संपर्क साधण्यास संकोच करू नका! + +### इतर उदाहरणे आणि मार्गदर्शक {#other-examples-guides} + +आम्ही तुम्हाला आमचे [क्विकस्टार्ट](https://docs.kurtosis.com/quickstart) (जिथे तुम्ही एक Postgres डेटाबेस आणि API तयार कराल) आणि आमच्या [awesome-kurtosis रिपॉझिटरी](https://github.com/kurtosis-tech/awesome-kurtosis) मधील आमची इतर उदाहरणे तपासण्यासाठी प्रोत्साहित करतो, जिथे तुम्हाला काही उत्तम उदाहरणे मिळतील, ज्यात यांसाठी पॅकेजेस आहेत: + +- [तेच स्थानिक Ethereum टेस्टनेट सुरू करणे](https://github.com/kurtosis-tech/eth2-package), परंतु ट्रान्झॅक्शन स्पॅमर (ट्रान्झॅक्शन सिम्युलेट करण्यासाठी), एक फोर्क मॉनिटर, आणि एक कनेक्टेड Grafana आणि Prometheus इन्स्टन्स यासारख्या अतिरिक्त सेवा कनेक्ट केलेल्या. +- त्याच स्थानिक Ethereum नेटवर्कवर [सब-नेटवर्किंग चाचणी](https://github.com/kurtosis-tech/awesome-kurtosis/tree/main/ethereum-network-partition-test) करणे diff --git a/public/content/translations/mr/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md b/public/content/translations/mr/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md new file mode 100644 index 00000000000..b45c9e7f91e --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/downsizing-contracts-to-fight-the-contract-size-limit/index.md @@ -0,0 +1,144 @@ +--- +title: "कंत्राटाच्या आकाराच्या मर्यादेला सामोरे जाण्यासाठी कंत्राटे लहान करणे" +description: "तुमचे स्मार्ट कंत्राट खूप मोठे होण्यापासून रोखण्यासाठी तुम्ही काय करू शकता?" +author: Markus Waas +lang: mr +tags: [ "सॉलिडिटी", "स्मार्ट कॉन्ट्रॅक्ट", "स्टोरेज" ] +skill: intermediate +published: 2020-06-26 +source: soliditydeveloper.com +sourceUrl: https://soliditydeveloper.com/max-contract-size +--- + +## मर्यादा का आहे? {#why-is-there-a-limit} + +[22 नोव्हेंबर, 2016](https://blog.ethereum.org/2016/11/18/hard-fork-no-4-spurious-dragon/) रोजी Spurious Dragon हार्ड-फोर्कने [EIP-170](https://eips.ethereum.org/EIPS/eip-170) सादर केले, ज्याने 24.576 kb ची स्मार्ट कंत्राट आकार मर्यादा जोडली. एक Solidity विकसक म्हणून तुमच्यासाठी याचा अर्थ असा आहे की, जेव्हा तुम्ही तुमच्या कंत्राटात अधिकाधिक कार्यक्षमता जोडता, तेव्हा एका क्षणी तुम्ही मर्यादेपर्यंत पोहोचता आणि तैनात करताना तुम्हाला खालील त्रुटी दिसेल: + +`चेतावणी: कंत्राट कोडचा आकार 24576 बाइट्सपेक्षा जास्त आहे (Spurious Dragon मध्ये सादर केलेली मर्यादा). हे कंत्राट कदाचित Mainnet वर तैनात करण्यायोग्य नसेल. ऑप्टिमायझर सक्षम करण्याचा विचार करा (कमी "runs" मूल्यांसह!), रिव्हर्ट स्ट्रिंग बंद करा, किंवा लायब्ररी वापरा.` + +ही मर्यादा डिनायल-ऑफ-सर्व्हिस (DOS) हल्ले रोखण्यासाठी सुरू करण्यात आली. गॅसच्या दृष्टीने कंत्राटाला कोणताही कॉल तुलनेने स्वस्त असतो. तथापि, Ethereum नोड्ससाठी कंत्राट कॉलचा परिणाम, कॉल केलेल्या कंत्राट कोडच्या आकारावर अवलंबून (डिस्कवरून कोड वाचणे, कोडवर पूर्व-प्रक्रिया करणे, मर्केल प्रूफमध्ये डेटा जोडणे) अवाजवी प्रमाणात वाढतो. जेव्हाही अशी परिस्थिती येते की आक्रमणकर्त्याला इतरांसाठी खूप काम निर्माण करण्यासाठी कमी संसाधनांची आवश्यकता असते, तेव्हा DOS हल्ल्यांची शक्यता निर्माण होते. + +मूळतः ही समस्या कमी होती कारण एक नैसर्गिक कंत्राट आकार मर्यादा म्हणजे ब्लॉक गॅस मर्यादा. अर्थात, कंत्राटाचा सर्व बायटकोड असलेल्या व्यवहारामध्ये कंत्राट तैनात करणे आवश्यक आहे. जर तुम्ही तो एकच व्यवहार एका ब्लॉकमध्ये समाविष्ट केला, तर तुम्ही तो सर्व गॅस वापरू शकता, पण तो अमर्याद नाही. [लंडन अपग्रेड](/ethereum-forks/#london) पासून, नेटवर्कच्या मागणीनुसार ब्लॉक गॅस मर्यादा 15M आणि 30M युनिट्स दरम्यान बदलू शकते. + +पुढे आपण त्यांच्या संभाव्य परिणामांनुसार क्रमाने मांडलेल्या काही पद्धती पाहू. याचा विचार वजन कमी करण्याच्या संदर्भात करा. एखाद्याला त्याचे लक्ष्य वजन (आपल्या बाबतीत 24kb) गाठण्यासाठी सर्वोत्तम धोरण म्हणजे प्रथम मोठ्या परिणामांच्या पद्धतींवर लक्ष केंद्रित करणे. बहुतेक प्रकरणांमध्ये फक्त तुमचा आहार सुधारल्याने तुम्ही तिथे पोहोचू शकता, पण कधीकधी तुम्हाला थोडे अधिक काहीतरी करण्याची गरज असते. मग तुम्ही काही व्यायाम (मध्यम परिणाम) किंवा अगदी पूरक आहार (लहान परिणाम) जोडू शकता. + +## मोठा परिणाम {#big-impact} + +### तुमची कंत्राटे वेगळी करा {#separate-your-contracts} + +हा नेहमीच तुमचा पहिला दृष्टिकोन असावा. तुम्ही कंत्राट अनेक लहान कंत्राटांमध्ये कसे वेगळे करू शकता? हे सामान्यतः तुम्हाला तुमच्या कंत्राटांसाठी एक चांगली रचना तयार करण्यास भाग पाडते. कोड वाचनीयतेच्या दृष्टिकोनातून लहान कंत्राटांना नेहमीच प्राधान्य दिले जाते. कंत्राटे विभागण्यासाठी, स्वतःला विचारा: + +- कोणती कार्ये एकत्र आहेत? प्रत्येक कार्यांचा संच त्याच्या स्वतःच्या कंत्राटात सर्वोत्तम असू शकतो. +- कोणत्या कार्यांना कंत्राट स्थिती वाचण्याची किंवा फक्त स्थितीचा एक विशिष्ट उपसंच वाचण्याची आवश्यकता नाही? +- तुम्ही स्टोरेज आणि कार्यक्षमता विभागू शकता का? + +### लायब्ररी {#libraries} + +कार्यक्षमता कोड स्टोरेजपासून दूर हलवण्याचा एक सोपा मार्ग म्हणजे [लायब्ररी](https://solidity.readthedocs.io/en/v0.6.10/contracts.html#libraries) वापरणे. लायब्ररीची कार्ये अंतर्गत म्हणून घोषित करू नका कारण ती संकलनादरम्यान थेट [कंत्राटात जोडली जातील](https://ethereum.stackexchange.com/questions/12975/are-internal-functions-in-libraries-not-covered-by-linking). परंतु जर तुम्ही सार्वजनिक कार्ये वापरली, तर ती प्रत्यक्षात एका वेगळ्या लायब्ररी कंत्राटात असतील. लायब्ररींचा वापर अधिक सोयीस्कर करण्यासाठी [`using for`](https://solidity.readthedocs.io/en/v0.6.10/contracts.html#using-for) चा वापर करण्याचा विचार करा. + +### प्रॉक्सी {#proxies} + +एक अधिक प्रगत धोरण म्हणजे प्रॉक्सी प्रणाली. लायब्ररी पार्श्वभूमीत `DELEGATECALL` वापरतात, जे फक्त कॉल करणाऱ्या कंत्राटाच्या स्थितीसह दुसऱ्या कंत्राटाचे कार्य कार्यान्वित करते. प्रॉक्सी प्रणालींबद्दल अधिक जाणून घेण्यासाठी [हा ब्लॉग पोस्ट](https://hackernoon.com/how-to-make-smart-contracts-upgradable-2612e771d5a2) पहा. त्या तुम्हाला अधिक कार्यक्षमता देतात, उदा., त्या अपग्रेडिबिलिटी सक्षम करतात, परंतु त्या खूप गुंतागुंत देखील वाढवतात. मी त्या फक्त कंत्राटाचा आकार कमी करण्यासाठी जोडणार नाही, जोपर्यंत कोणत्याही कारणास्तव तो तुमचा एकमेव पर्याय नसेल. + +## मध्यम परिणाम {#medium-impact} + +### कार्ये काढा {#remove-functions} + +हे स्पष्ट असले पाहिजे. कार्ये कंत्राटाचा आकार बऱ्यापैकी वाढवतात. + +- **बाह्य**: बऱ्याच वेळा आपण सोयीसाठी अनेक व्ह्यू कार्ये जोडतो. जोपर्यंत तुम्ही आकाराच्या मर्यादेपर्यंत पोहोचत नाही तोपर्यंत ते अगदी ठीक आहे. मग तुम्हाला अत्यंत आवश्यक कार्ये वगळता सर्व काढून टाकण्याचा खरोखर विचार करायला हवा. +- **अंतर्गत**: जोपर्यंत कार्य फक्त एकदाच कॉल केले जाते तोपर्यंत तुम्ही अंतर्गत/खाजगी कार्ये देखील काढू शकता आणि फक्त कोड इनलाइन करू शकता. + +### अतिरिक्त व्हेरिएबल्स टाळा {#avoid-additional-variables} + +```solidity +function get(uint id) returns (address,address) { + MyStruct memory myStruct = myStructs[id]; + return (myStruct.addr1, myStruct.addr2); +} +``` + +```solidity +function get(uint id) returns (address,address) { + return (myStructs[id].addr1, myStructs[id].addr2); +} +``` + +यासारखा एक साधा बदल **0.28kb** चा फरक करतो. तुम्हाला तुमच्या कंत्राटांमध्ये अशा अनेक समान परिस्थिती सापडतील आणि त्या खरोखरच लक्षणीय प्रमाणात भर घालू शकतात. + +### त्रुटी संदेश लहान करा {#shorten-error-message} + +लांब रिव्हर्ट संदेश आणि विशेषतः अनेक भिन्न रिव्हर्ट संदेश कंत्राट फुगवू शकतात. त्याऐवजी लहान त्रुटी कोड वापरा आणि ते तुमच्या कंत्राटात डीकोड करा. एक लांब संदेश खूपच लहान होऊ शकतो: + +```solidity +require(msg.sender == owner, "फक्त या कंत्राटाचा मालक हे कार्य कॉल करू शकतो"); +``` + +```solidity +require(msg.sender == owner, "OW1"); +``` + +### त्रुटी संदेशांऐवजी कस्टम त्रुटी वापरा + +कस्टम त्रुटी [Solidity 0.8.4](https://blog.soliditylang.org/2021/04/21/custom-errors/) मध्ये सादर करण्यात आल्या आहेत. तुमच्या कंत्राटांचा आकार कमी करण्याचा हा एक उत्तम मार्ग आहे, कारण ते निवडक (selectors) म्हणून ABI-एनकोड केलेले आहेत (जसे कार्ये असतात). + +```solidity +error Unauthorized(); + +if (msg.sender != owner) { + revert Unauthorized(); +} +``` + +### ऑप्टिमायझरमध्ये कमी रन मूल्याचा विचार करा {#consider-a-low-run-value-in-the-optimizer} + +तुम्ही ऑप्टिमायझर सेटिंग्ज देखील बदलू शकता. 200 चे डीफॉल्ट मूल्य म्हणजे ते बायटकोडला असे ऑप्टिमाइझ करण्याचा प्रयत्न करत आहे जसे की एखादे कार्य 200 वेळा कॉल केले जाते. जर तुम्ही ते 1 मध्ये बदलले, तर तुम्ही मुळात ऑप्टिमायझरला प्रत्येक कार्य फक्त एकदाच चालवण्याच्या केससाठी ऑप्टिमाइझ करण्यास सांगता. फक्त एकदाच चालण्यासाठी ऑप्टिमाइझ केलेले कार्य म्हणजे ते स्वतःच तैनात करण्यासाठी ऑप्टिमाइझ केलेले आहे. लक्षात ठेवा की **यामुळे कार्ये चालवण्यासाठीचा [गॅस खर्च](/developers/docs/gas/) वाढतो**, त्यामुळे तुम्हाला हे करायचे नसेल. + +## लहान परिणाम {#small-impact} + +### कार्यांना स्ट्रक्ट पास करणे टाळा {#avoid-passing-structs-to-functions} + +जर तुम्ही [ABIEncoderV2](https://solidity.readthedocs.io/en/v0.6.10/layout-of-source-files.html#abiencoderv2) वापरत असाल, तर कार्यांना स्ट्रक्ट पास न करणे उपयुक्त ठरू शकते. पॅरामीटरला स्ट्रक्ट म्हणून पास करण्याऐवजी, आवश्यक पॅरामीटर्स थेट पास करा. या उदाहरणात आपण आणखी **0.1kb** वाचवले. + +```solidity +function get(uint id) returns (address,address) { + return _get(myStruct); +} + +function _get(MyStruct memory myStruct) private view returns(address,address) { + return (myStruct.addr1, myStruct.addr2); +} +``` + +```solidity +function get(uint id) returns(address,address) { + return _get(myStructs[id].addr1, myStructs[id].addr2); +} + +function _get(address addr1, address addr2) private view returns(address,address) { + return (addr1, addr2); +} +``` + +### कार्ये आणि व्हेरिएबल्ससाठी योग्य दृश्यमानता घोषित करा {#declare-correct-visibility-for-functions-and-variables} + +- फक्त बाहेरून कॉल केली जाणारी कार्ये किंवा व्हेरिएबल्स? त्यांना `public` ऐवजी `external` म्हणून घोषित करा. +- फक्त कंत्राटातूनच कॉल केली जाणारी कार्ये किंवा व्हेरिएबल्स? त्यांना `public` ऐवजी `private` किंवा `internal` म्हणून घोषित करा. + +### मॉडिफायर्स काढा {#remove-modifiers} + +मॉडिफायर्स, विशेषतः जेव्हा ते जास्त प्रमाणात वापरले जातात, तेव्हा कंत्राटाच्या आकारावर महत्त्वपूर्ण परिणाम करू शकतात. त्यांना काढण्याचा विचार करा आणि त्याऐवजी कार्ये वापरा. + +```solidity +modifier checkStuff() {} + +function doSomething() checkStuff {} +``` + +```solidity +function checkStuff() private {} + +function doSomething() { checkStuff(); } +``` + +या टिप्स तुम्हाला कंत्राटाचा आकार लक्षणीयरीत्या कमी करण्यास मदत करतील. पुन्हा एकदा, मी हे पुरेसे जोर देऊन सांगू इच्छितो की, सर्वात मोठ्या परिणामासाठी शक्य असल्यास नेहमी कंत्राटे विभागण्यावर लक्ष केंद्रित करा. diff --git a/public/content/translations/mr/developers/tutorials/eip-1271-smart-contract-signatures/index.md b/public/content/translations/mr/developers/tutorials/eip-1271-smart-contract-signatures/index.md new file mode 100644 index 00000000000..29b0329c22d --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/eip-1271-smart-contract-signatures/index.md @@ -0,0 +1,129 @@ +--- +title: "EIP-1271: स्मार्ट कॉन्ट्रॅक्ट सह्यांवर सही करणे आणि त्या सत्यापित करणे" +description: "EIP-1271 सह स्मार्ट कॉन्ट्रॅक्ट सही निर्मिती आणि सत्यापनाचा आढावा. स्मार्ट कॉन्ट्रॅक्ट डेव्हलपर्सना त्यावर आधारित काम करण्यासाठी एक ठोस उदाहरण म्हणून, आम्ही Safe (पूर्वीचे Gnosis Safe) मध्ये वापरलेल्या EIP-1271 अंमलबजावणीचे देखील मार्गदर्शन करतो." +author: Nathan H. Leung +lang: mr +tags: + [ + "eip-1271", + "स्मार्ट कॉन्ट्रॅक्ट", + "सत्यापित करणे", + "सही करणे" + ] +skill: intermediate +published: 2023-01-12 +--- + +[EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) मानक स्मार्ट कॉन्ट्रॅक्ट्सना सह्या सत्यापित करण्याची परवानगी देते. + +या ट्युटोरियलमध्ये, आम्ही डिजिटल सह्या, EIP-1271 ची पार्श्वभूमी आणि [Safe](https://safe.global/) (पूर्वीचे Gnosis Safe) द्वारे वापरलेल्या EIP-1271 च्या विशिष्ट अंमलबजावणीचा आढावा देतो. एकत्रितपणे, हे तुमच्या स्वतःच्या कॉन्ट्रॅक्टमध्ये EIP-1271 लागू करण्यासाठी एक प्रारंभ बिंदू म्हणून काम करू शकते. + +## सही म्हणजे काय? + +या संदर्भात, सही (अधिक अचूकपणे सांगायचे तर, “डिजिटल सही”) म्हणजे एक संदेश आणि तो संदेश एका विशिष्ट व्यक्ती/प्रेषक/ॲड्रेसकडून आला आहे याचा काही प्रकारचा पुरावा. + +उदाहरणार्थ, डिजिटल सही अशी दिसू शकते: + +1. संदेश: “मला माझ्या Ethereum वॉलेटने या वेबसाइटवर लॉग इन करायचे आहे.” +2. सही करणारा: माझा ॲड्रेस `0x000…` आहे +3. पुरावा: हा काही पुरावा आहे की मी, `0x000…`, हा संपूर्ण संदेश खरोखर तयार केला आहे (हे सहसा काहीतरी क्रिप्टोग्राफिक असते). + +हे लक्षात घेणे महत्त्वाचे आहे की डिजिटल सहीमध्ये "संदेश" आणि "सही" दोन्ही समाविष्ट असतात. + +का? उदाहरणार्थ, जर तुम्ही मला सही करण्यासाठी एखादा कॉन्ट्रॅक्ट दिला आणि मी त्यातील सहीचे पान कापून बाकीच्या कॉन्ट्रॅक्टशिवाय केवळ माझ्या सह्या तुम्हाला परत दिल्या, तर तो कॉन्ट्रॅक्ट वैध ठरणार नाही. + +त्याचप्रमाणे, संबंधित संदेशाशिवाय डिजिटल सहीला काहीही अर्थ नाही! + +## EIP-1271 का अस्तित्वात आहे? + +Ethereum-आधारित ब्लॉकचेनवर वापरण्यासाठी डिजिटल सही तयार करण्याकरिता, तुम्हाला सामान्यतः एका गुप्त प्रायव्हेट की ची आवश्यकता असते, जी इतर कोणालाही माहीत नसते. यामुळेच तुमची सही ही तुमचीच असते (गुप्त की च्या माहितीशिवाय इतर कोणीही तीच सही तयार करू शकत नाही). + +तुमच्या Ethereum अकाउंटशी (म्हणजे, तुमच्या एक्सटर्नली-ओन्ड अकाउंट/EOA) एक प्रायव्हेट की जोडलेली असते, आणि हीच ती प्रायव्हेट की आहे जी सामान्यतः एखादी वेबसाइट किंवा dapp तुम्हाला सहीसाठी विचारते तेव्हा वापरली जाते (उदा., "Ethereum ने लॉग इन करा" साठी). + +एखादे ॲप ethers.js सारख्या थर्ड-पार्टी लायब्ररीचा वापर करून, तुम्ही तयार केलेली [सही सत्यापित करू शकते](https://www.alchemy.com/docs/how-to-verify-a-message-signature-on-ethereum), आणि तेही [तुमची प्रायव्हेट की माहीत नसताना](https://en.wikipedia.org/wiki/Public-key_cryptography), आणि _तुम्हीच_ ती सही तयार केली आहे याची खात्री बाळगू शकते. + +> खरं तर, EOA डिजिटल सह्या पब्लिक-की क्रिप्टोग्राफी वापरत असल्यामुळे, त्या **ऑफचेन** तयार आणि सत्यापित केल्या जाऊ शकतात! गॅसलेस DAO मतदान असेच कार्य करते — ऑनचेन मते सबमिट करण्याऐवजी, क्रिप्टोग्राफिक लायब्ररी वापरून डिजिटल सह्या ऑफचेन तयार आणि सत्यापित केल्या जाऊ शकतात. + +EOA अकाउंट्सकडे प्रायव्हेट की असली तरी, स्मार्ट कॉन्ट्रॅक्ट अकाउंट्सकडे कोणत्याही प्रकारची प्रायव्हेट किंवा गुप्त की नसते (त्यामुळे "Ethereum ने लॉग इन करा", इत्यादी स्मार्ट कॉन्ट्रॅक्ट अकाउंट्ससोबत मूळतः काम करू शकत नाहीत). + +EIP-1271 ज्या समस्येचे निराकरण करण्याचे उद्दिष्ट ठेवते ती ही आहे: जर स्मार्ट कॉन्ट्रॅक्टकडे सहीमध्ये समाविष्ट करण्यासाठी कोणतेही “गुपित” नसेल, तर स्मार्ट कॉन्ट्रॅक्टची सही वैध आहे हे आपण कसे ओळखू शकतो? + +## EIP-1271 कसे कार्य करते? + +स्मार्ट कॉन्ट्रॅक्ट्सकडे प्रायव्हेट की नसतात ज्यांचा वापर संदेशांवर सही करण्यासाठी केला जाऊ शकतो. मग एखादी सही अस्सल आहे की नाही हे आपण कसे ओळखू शकतो? + +तर, एक कल्पना अशी आहे की आपण थेट स्मार्ट कॉन्ट्रॅक्टलाच _विचारू_ शकतो की एखादी सही अस्सल आहे की नाही! + +EIP-1271 हेच करते की, दिलेली सही वैध आहे की नाही हे स्मार्ट कॉन्ट्रॅक्टला “विचारण्याच्या” या कल्पनेला ते प्रमाणित करते. + +EIP-1271 लागू करणाऱ्या कॉन्ट्रॅक्टमध्ये `isValidSignature` नावाचे फंक्शन असणे आवश्यक आहे, जे एक संदेश आणि एक सही इनपुट म्हणून घेते. त्यानंतर कॉन्ट्रॅक्ट काही व्हॅलिडेशन लॉजिक चालवू शकतो (स्पेक येथे काहीही विशिष्ट लागू करत नाही) आणि मग सही वैध आहे की नाही हे दर्शवणारे एक मूल्य परत करू शकतो. + +जर `isValidSignature` ने वैध निकाल परत केला, तर त्याचा अर्थ असा होतो की कॉन्ट्रॅक्ट म्हणत आहे, “होय, मी या सही + संदेशाला मान्यता देतो!” + +### इंटरफेस + +EIP-1271 स्पेक मधील अचूक इंटरफेस येथे आहे (आपण खाली `_hash` पॅरामीटरबद्दल बोलू, पण आतासाठी, त्याचा विचार सत्यापित केला जाणारा संदेश म्हणून करा): + +```jsx +pragma solidity ^0.5.0; + +contract ERC1271 { + + // bytes4(keccak256("isValidSignature(bytes32,bytes)") + bytes4 constant internal MAGICVALUE = 0x1626ba7e; + + /** + * @dev प्रदान केलेली सही, प्रदान केलेल्या हॅशसाठी वैध आहे की नाही हे परत करावे + * @param _hash सही करायच्या डेटाचा हॅश + * @param _signature _hash शी संबंधित सही बाइट ॲरे + * + * फंक्शन पास झाल्यावर bytes4 मॅजिक व्हॅल्यू 0x1626ba7e परत करणे आवश्यक आहे. + * स्टेटमध्ये बदल करणे आवश्यक नाही (solc < 0.5 साठी STATICCALL वापरून, solc > 0.5 साठी व्ह्यू मॉडिफायर वापरून) + * एक्सटर्नल कॉल्सना परवानगी देणे आवश्यक आहे + */ + function isValidSignature( + bytes32 _hash, + bytes memory _signature) + public + view + returns (bytes4 magicValue); +} +``` + +## EIP-1271 अंमलबजावणीचे उदाहरण: Safe + +कॉन्ट्रॅक्ट्स `isValidSignature` अनेक प्रकारे लागू करू शकतात — स्पेक अचूक अंमलबजावणीबद्दल फारसे काही सांगत नाही. + +EIP-1271 लागू करणारा एक उल्लेखनीय कॉन्ट्रॅक्ट म्हणजे Safe (पूर्वीचा Gnosis Safe). + +Safe च्या कोडमध्ये, `isValidSignature` [अंमलात आणले आहे](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol) जेणेकरून सह्या [दोन प्रकारे](https://ethereum.stackexchange.com/questions/122635/signing-messages-as-a-gnosis-safe-eip1271-support) तयार आणि सत्यापित केल्या जाऊ शकतात: + +1. ऑनचेन संदेश + 1. निर्मिती: एक safe मालक संदेशावर “सही” करण्यासाठी एक नवीन safe व्यवहार तयार करतो, आणि संदेशाला डेटा म्हणून त्या व्यवहारात पास करतो. एकदा मल्टिसिग थ्रेशोल्डपर्यंत पोहोचण्यासाठी पुरेसे मालक व्यवहारावर सही करतात, तेव्हा तो व्यवहार प्रसारित केला जातो आणि चालवला जातो. त्या व्यवहारामध्ये, (`signMessage(bytes calldata _data)`) नावाचे एक सेफ फंक्शन आहे जे संदेशाला “मान्यताप्राप्त” संदेशांच्या यादीत जोडते. + 2. सत्यापन: Safe कॉन्ट्रॅक्टवर `isValidSignature` कॉल करा आणि सत्यापित करायचा संदेश हा संदेश पॅरामीटर म्हणून पास करा आणि [सही पॅरामीटरसाठी एक रिकामे मूल्य पास करा](https://github.com/safe-global/safe-contracts/blob/main/contracts/handler/CompatibilityFallbackHandler.sol#L32) (म्हणजे, `0x`). Safe बघेल की सही पॅरामीटर रिकामा आहे आणि सहीचे क्रिप्टोग्राफिकली सत्यापन करण्याऐवजी, तो संदेश “मान्यताप्राप्त” संदेशांच्या यादीत आहे की नाही हे तपासेल. +2. ऑफचेन संदेश: + 1. निर्मिती: एक safe मालक ऑफचेन एक संदेश तयार करतो, आणि मल्टिसिग मान्यता थ्रेशोल्ड पार करण्यासाठी पुरेशा सह्या मिळेपर्यंत इतर safe मालकांकडून त्या संदेशावर वैयक्तिकरित्या सही घेतो. + 2. सत्यापन: `isValidSignature` कॉल करा. संदेश पॅरामीटरमध्ये, सत्यापित करायचा संदेश पास करा. सही पॅरामीटरमध्ये, प्रत्येक safe मालकाच्या वैयक्तिक सह्या एकामागोमाग एक जोडून पास करा. Safe हे तपासेल की थ्रेशोल्ड पूर्ण करण्यासाठी पुरेशा सह्या आहेत **आणि** प्रत्येक सही वैध आहे. तसे असल्यास, ते यशस्वी सही सत्यापनाचे सूचक मूल्य परत करेल. + +## `_hash` पॅरामीटर नेमके काय आहे? संपूर्ण संदेश का पास करू नये? + +तुमच्या लक्षात आले असेल की [EIP-1271 इंटरफेस](https://eips.ethereum.org/EIPS/eip-1271) मधील `isValidSignature` फंक्शन संदेश स्वतः न घेता, त्याऐवजी एक `_hash` पॅरामीटर घेते. याचा अर्थ असा आहे की, `isValidSignature` ला संपूर्ण अनियंत्रित-लांबीचा संदेश पास करण्याऐवजी, आपण त्याऐवजी संदेशाचा ३२-बाइट हॅश (सामान्यतः keccak256) पास करतो. + +calldata च्या प्रत्येक बाइटला — म्हणजे, स्मार्ट कॉन्ट्रॅक्ट फंक्शनला पास केलेल्या फंक्शन पॅरामीटर डेटाला — [१६ गॅस (शून्य बाइट असल्यास ४ गॅस) खर्च येतो](https://eips.ethereum.org/EIPS/eip-2028), त्यामुळे संदेश मोठा असल्यास भरपूर गॅस वाचू शकतो. + +### मागील EIP-1271 स्पेसिफिकेशन्स + +वापरात अशी EIP-1271 स्पेसिफिकेशन्स आहेत ज्यात `isValidSignature` फंक्शन आहे, ज्याचा पहिला पॅरामीटर `bytes` प्रकाराचा (निश्चित-लांबीच्या `bytes32` ऐवजी अनिश्चित-लांबीचा) आहे आणि पॅरामीटरचे नाव `message` आहे. ही EIP-1271 मानकाची [एक जुनी आवृत्ती](https://github.com/safe-global/safe-contracts/issues/391#issuecomment-1075427206) आहे. + +## माझ्या स्वतःच्या कॉन्ट्रॅक्ट्समध्ये EIP-1271 कसे लागू करावे? + +येथे स्पेक खूपच लवचिक आहे. Safe अंमलबजावणीमध्ये काही चांगल्या कल्पना आहेत: + +- तुम्ही कॉन्ट्रॅक्टच्या "मालका"कडून आलेल्या EOA सह्या वैध मानू शकता. +- तुम्ही मान्यताप्राप्त संदेशांची यादी संग्रहित करू शकता आणि केवळ त्यांनाच वैध मानू शकता. + +शेवटी, कॉन्ट्रॅक्ट डेव्हलपर म्हणून हे तुमच्यावर अवलंबून आहे! + +## निष्कर्ष + +[EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) हे एक बहुउपयोगी मानक आहे जे स्मार्ट कॉन्ट्रॅक्ट्सना सह्या सत्यापित करण्याची परवानगी देते. हे स्मार्ट कॉन्ट्रॅक्ट्सना EOA सारखे अधिक वागण्यासाठी मार्ग खुले करते — उदाहरणार्थ, "Ethereum ने लॉग इन करा" ला स्मार्ट कॉन्ट्रॅक्ट्ससोबत काम करण्याचा मार्ग प्रदान करणे — आणि ते अनेक प्रकारे लागू केले जाऊ शकते (Safe कडे विचारात घेण्यासारखी एक गुंतागुंतीची, मनोरंजक अंमलबजावणी आहे). diff --git a/public/content/translations/mr/developers/tutorials/erc-721-vyper-annotated-code/index.md b/public/content/translations/mr/developers/tutorials/erc-721-vyper-annotated-code/index.md new file mode 100644 index 00000000000..e765c3bb84f --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/erc-721-vyper-annotated-code/index.md @@ -0,0 +1,644 @@ +--- +title: "Vyper ERC-721 कॉन्ट्रॅक्ट वॉकथ्रू" +description: "Ryuya Nakamura चे ERC-721 कॉन्ट्रॅक्ट आणि ते कसे कार्य करते" +author: Ori Pomerantz +lang: mr +tags: [ "vyper", "erc-721", "python" ] +skill: beginner +published: 2021-04-01 +--- + +## प्रस्तावना {#introduction} + +[ERC-721](/developers/docs/standards/tokens/erc-721/) मानक हे नॉन-फंजिबल टोकन्स (NFT) ची मालकी ठेवण्यासाठी वापरले जाते. +[ERC-20](/developers/docs/standards/tokens/erc-20/) टोकन्स एका वस्तू (कमोडिटी) सारखे वागतात, कारण वैयक्तिक टोकन्समध्ये काहीही फरक नसतो. +याउलट, ERC-721 टोकन्स अशा मालमत्तेसाठी डिझाइन केलेले आहेत जे समान आहेत परंतु एकसारखे नाहीत, जसे की भिन्न मांजर +कार्टून किंवा रिअल इस्टेटच्या वेगवेगळ्या तुकड्यांची मालकी हक्क. + +या लेखात आपण [Ryuya Nakamura च्या ERC-721 कॉन्ट्रॅक्टचे](https://github.com/vyperlang/vyper/blob/master/examples/tokens/ERC721.vy) विश्लेषण करू. +हे कॉन्ट्रॅक्ट [Vyper](https://vyper.readthedocs.io/en/latest/index.html) मध्ये लिहिलेले आहे, जी एक Python-सारखी कॉन्ट्रॅक्ट भाषा आहे, जी Solidity पेक्षा असुरक्षित कोड लिहिणे अधिक कठीण करण्यासाठी डिझाइन केलेली आहे. + +## कॉन्ट्रॅक्ट {#contract} + +```python +# @dev ERC-721 नॉन-फंजिबल टोकन मानकाची अंमलबजावणी. +# @author Ryuya Nakamura (@nrryuya) +# येथून सुधारित: https://github.com/vyperlang/vyper/blob/de74722bf2d8718cca46902be165f9fe0e3641dd/examples/tokens/ERC721.vy +``` + +Vyper मध्ये, Python प्रमाणेच, कमेंट्स हॅश (`#`) ने सुरू होतात आणि ओळीच्या शेवटपर्यंत चालू राहतात. `@` समाविष्ट असलेल्या कमेंट्स [NatSpec](https://vyper.readthedocs.io/en/latest/natspec.html) द्वारे मानवासाठी वाचनीय डॉक्युमेंटेशन तयार करण्यासाठी वापरल्या जातात. + +```python +from vyper.interfaces import ERC721 + +implements: ERC721 +``` + +ERC-721 इंटरफेस Vyper भाषेमध्ये अंगभूत आहे. +[तुम्ही कोडची व्याख्या येथे पाहू शकता](https://github.com/vyperlang/vyper/blob/master/vyper/builtin_interfaces/ERC721.py). +इंटरफेसची व्याख्या Vyper ऐवजी Python मध्ये लिहिलेली आहे, कारण इंटरफेस केवळ ब्लॉकचेनमध्येच नव्हे, तर बाह्य क्लायंटकडून ब्लॉकचेनला व्यवहार पाठवताना देखील वापरले जातात, जे Python मध्ये लिहिलेले असू शकतात. + +पहिली ओळ इंटरफेस इम्पोर्ट करते आणि दुसरी ओळ नमूद करते की आम्ही येथे त्याची अंमलबजावणी करत आहोत. + +### ERC721Receiver इंटरफेस {#receiver-interface} + +```python +# safeTransferFrom() द्वारे कॉल केलेल्या कॉन्ट्रॅक्टसाठी इंटरफेस +interface ERC721Receiver: + def onERC721Received( +``` + +ERC-721 दोन प्रकारच्या ट्रान्सफरला समर्थन देते: + +- `transferFrom`, जे प्रेषकाला (sender) कोणतेही डेस्टिनेशन ॲड्रेस निर्दिष्ट करण्याची परवानगी देते आणि हस्तांतरणाची जबाबदारी प्रेषकावर टाकते. याचा अर्थ असा की आपण अवैध ॲड्रेसवर हस्तांतरण करू शकता, अशा परिस्थितीत NFT कायमचा गमावला जातो. +- `safeTransferFrom`, जे डेस्टिनेशन ॲड्रेस हे कॉन्ट्रॅक्ट आहे की नाही हे तपासते. तसे असल्यास, ERC-721 कॉन्ट्रॅक्ट प्राप्त करणाऱ्या कॉन्ट्रॅक्टला विचारतो की त्याला NFT प्राप्त करायचा आहे का. + +`safeTransferFrom` विनंत्यांना उत्तर देण्यासाठी प्राप्त करणाऱ्या कॉन्ट्रॅक्टला `ERC721Receiver` लागू करावे लागते. + +```python + _operator: address, + _from: address, +``` + +`_from` ॲड्रेस हा टोकनचा सध्याचा मालक आहे. `_operator` ॲड्रेस तो आहे ज्याने हस्तांतरणाची विनंती केली (अलाउन्समुळे हे दोघे समान नसतील). + +```python + _tokenId: uint256, +``` + +ERC-721 टोकन आयडी 256 बिटचे असतात. सामान्यतः टोकन ज्याचे प्रतिनिधित्व करते त्याच्या वर्णनाचे हॅशिंग करून ते तयार केले जातात. + +```python + _data: Bytes[1024] +``` + +विनंतीमध्ये 1024 बाइट्सपर्यंत वापरकर्ता डेटा असू शकतो. + +```python + ) -> bytes32: view +``` + +एखादा कॉन्ट्रॅक्ट चुकून हस्तांतरण स्वीकारतो अशा प्रकरणांना टाळण्यासाठी, रिटर्न व्हॅल्यू बुलियन नसते, तर एका विशिष्ट व्हॅल्यूसह 256 बिट्स असते. + +हे फंक्शन एक `view` आहे, याचा अर्थ ते ब्लॉकचेनची स्थिती (state) वाचू शकते, परंतु त्यात बदल करू शकत नाही. + +### इव्हेंट्स {#events} + +[इव्हेंट्स](https://media.consensys.net/technical-introduction-to-events-and-logs-in-ethereum-a074d65dd61e) हे ब्लॉकचेनच्या बाहेरील वापरकर्त्यांना आणि सर्व्हरना इव्हेंट्सबद्दल माहिती देण्यासाठी उत्सर्जित केले जातात. लक्षात घ्या की इव्हेंट्सची सामग्री ब्लॉकचेनवरील कॉन्ट्रॅक्टसाठी उपलब्ध नसते. + +```python +# @dev कोणत्याही NFT ची मालकी कोणत्याही यंत्रणेद्वारे बदलल्यावर उत्सर्जित होते. हा इव्हेंट NFTs +# तयार झाल्यावर (`from` == 0) आणि नष्ट झाल्यावर (`to` == 0) उत्सर्जित होतो. अपवाद: कॉन्ट्रॅक्ट निर्मिती दरम्यान, कितीही +# NFTs ट्रान्सफर उत्सर्जित न करता तयार आणि नियुक्त केले जाऊ शकतात. कोणत्याही +# हस्तांतरणाच्या वेळी, त्या NFT साठी मंजूर केलेला पत्ता (असल्यास) 'काहीही नाही' वर रीसेट केला जातो. +# @param _from NFT चा प्रेषक (पत्ता शून्य असल्यास तो टोकन निर्मिती दर्शवतो). +# @param _to NFT चा प्राप्तकर्ता (पत्ता शून्य असल्यास तो टोकन नष्ट करणे दर्शवतो). +# @param _tokenId हस्तांतरित झालेला NFT. +event Transfer: + sender: indexed(address) + receiver: indexed(address) + tokenId: indexed(uint256) +``` + +हे ERC-20 ट्रान्सफर इव्हेंटसारखेच आहे, फक्त आपण रकमेऐवजी `tokenId` कळवतो. +कोणीही शून्य पत्त्याचा मालक नाही, म्हणून प्रथेनुसार आपण त्याचा वापर टोकनची निर्मिती आणि नाश कळवण्यासाठी करतो. + +```python +# @dev NFT साठी मंजूर केलेला पत्ता बदलला किंवा पुन्हा निश्चित केल्यावर हे उत्सर्जित होते. शून्य +# पत्ता सूचित करतो की कोणताही मंजूर पत्ता नाही. जेव्हा एखादा ट्रान्सफर इव्हेंट उत्सर्जित होतो, तेव्हा हे देखील +# सूचित करते की त्या NFT साठी मंजूर केलेला पत्ता (असल्यास) 'काहीही नाही' वर रीसेट केला जातो. +# @param _owner NFT चा मालक. +# @param _approved आम्ही मंजूर करत असलेला पत्ता. +# @param _tokenId आम्ही मंजूर करत असलेला NFT. +event Approval: + owner: indexed(address) + approved: indexed(address) + tokenId: indexed(uint256) +``` + +ERC-721 मंजुरी ERC-20 अलाउन्स सारखीच आहे. एका विशिष्ट पत्त्याला एक विशिष्ट टोकन हस्तांतरित करण्याची परवानगी दिली जाते. यामुळे करारांना टोकन स्वीकारल्यावर प्रतिसाद देण्यासाठी एक यंत्रणा मिळते. कॉन्ट्रॅक्ट इव्हेंट ऐकू शकत नाहीत, म्हणून जर तुम्ही फक्त त्यांना टोकन हस्तांतरित केले तर त्यांना त्याबद्दल 'माहित' होत नाही. या प्रकारे मालक प्रथम एक मंजुरी सादर करतो आणि नंतर कॉन्ट्रॅक्टला विनंती पाठवतो: 'मी तुम्हाला टोकन X हस्तांतरित करण्यासाठी मंजूर केले आहे, कृपया ... करा'. + +ERC-721 मानकाला ERC-20 मानकासारखे बनवण्यासाठी ही एक डिझाइन निवड आहे. कारण ERC-721 टोकन फंजिबल नाहीत, एक कॉन्ट्रॅक्ट टोकनच्या मालकीकडे पाहून ओळखू शकतो की त्याला एक विशिष्ट टोकन मिळाले आहे. + +```python +# @dev मालकासाठी ऑपरेटर सक्षम किंवा अक्षम केल्यावर हे उत्सर्जित होते. ऑपरेटर +# मालकाच्या सर्व NFTs चे व्यवस्थापन करू शकतो. +# @param _owner NFT चा मालक. +# @param _operator पत्ता ज्यावर आम्ही ऑपरेटर हक्क सेट करत आहोत. +# @param _approved ऑपरेटर हक्कांची स्थिती (ऑपरेटर हक्क दिल्यास 'true' आणि +# रद्द केल्यास 'false'). +event ApprovalForAll: + owner: indexed(address) + operator: indexed(address) + approved: bool +``` + +कधीकधी एक _ऑपरेटर_ असणे उपयुक्त ठरते जो एखाद्या खात्याच्या विशिष्ट प्रकारच्या सर्व टोकनचे व्यवस्थापन करू शकतो (जे विशिष्ट कॉन्ट्रॅक्टद्वारे व्यवस्थापित केले जातात), मुखत्यारपत्राप्रमाणे. उदाहरणार्थ, मला कदाचित अशा कॉन्ट्रॅक्टला अशी शक्ती द्यायची असेल जो तपासतो की मी सहा महिन्यांपासून त्याच्याशी संपर्क साधला आहे की नाही, आणि तसे असल्यास, माझी मालमत्ता माझ्या वारसांना वितरीत करतो (जर त्यापैकी कोणीतरी विचारले, तर कॉन्ट्रॅक्ट व्यवहाराद्वारे कॉल केल्याशिवाय काहीही करू शकत नाहीत). ERC-20 मध्ये आपण फक्त एका वारसा कॉन्ट्रॅक्टला उच्च अलाउन्स देऊ शकतो, परंतु ते ERC-721 साठी काम करत नाही कारण टोकन फंजिबल नाहीत. हे त्याच्या समकक्ष आहे. + +`approved` मूल्य आपल्याला सांगते की इव्हेंट मंजुरीसाठी आहे की मंजुरी मागे घेण्यासाठी आहे. + +### स्टेट व्हेरिएबल्स {#state-vars} + +या व्हेरिएबल्समध्ये टोकनची सध्याची स्थिती असते: कोणते उपलब्ध आहेत आणि त्यांचे मालक कोण आहेत. यापैकी बहुतेक `HashMap` ऑब्जेक्ट्स आहेत, [दोन प्रकारांमध्ये अस्तित्वात असलेले एकदिशीय मॅपिंग](https://vyper.readthedocs.io/en/latest/types.html#mappings). + +```python +# @dev NFT आयडी वरून त्याच्या मालकाच्या पत्त्यावर मॅपिंग. +idToOwner: HashMap[uint256, address] + +# @dev NFT आयडी वरून मंजूर केलेल्या पत्त्यावर मॅपिंग. +idToApprovals: HashMap[uint256, address] +``` + +Ethereum मध्ये वापरकर्ता आणि कॉन्ट्रॅक्ट ओळख 160-बिट पत्त्यांद्वारे दर्शविली जाते. हे दोन व्हेरिएबल्स टोकन आयडी वरून त्यांच्या मालकांना आणि त्यांना हस्तांतरित करण्यास मंजूर असलेल्यांना (प्रत्येकासाठी जास्तीत जास्त एक) मॅप करतात. Ethereum मध्ये, अनइनिशियलाइज्ड डेटा नेहमी शून्य असतो, म्हणून जर मालक किंवा मंजूर हस्तांतरणकर्ता नसेल तर त्या टोकनसाठी मूल्य शून्य असते. + +```python +# @dev मालकाच्या पत्त्यावरून त्याच्या टोकनच्या संख्येवर मॅपिंग. +ownerToNFTokenCount: HashMap[address, uint256] +``` + +हे व्हेरिएबल प्रत्येक मालकासाठी टोकनची संख्या ठेवते. मालकांकडून टोकनपर्यंत कोणतेही मॅपिंग नाही, म्हणून विशिष्ट मालकाचे टोकन ओळखण्याचा एकमेव मार्ग म्हणजे ब्लॉकचेनच्या इव्हेंट इतिहासात मागे पाहणे आणि योग्य `Transfer` इव्हेंट पाहणे. आपल्याकडे सर्व NFTs आहेत आणि आपल्याला वेळेत आणखी मागे पाहण्याची गरज नाही हे जाणून घेण्यासाठी आपण या व्हेरिएबलचा वापर करू शकतो. + +लक्षात घ्या की हा अल्गोरिदम फक्त वापरकर्ता इंटरफेस आणि बाह्य सर्व्हरसाठी काम करतो. ब्लॉकचेनवर चालणारा कोड स्वतः मागील इव्हेंट वाचू शकत नाही. + +```python +# @dev मालकाच्या पत्त्यावरून ऑपरेटर पत्त्यांच्या मॅपिंगवर मॅपिंग. +ownerToOperators: HashMap[address, HashMap[address, bool]] +``` + +एका खात्यात एकापेक्षा जास्त ऑपरेटर असू शकतात. त्यांचा मागोवा ठेवण्यासाठी एक साधे `HashMap` पुरेसे नाही, कारण प्रत्येक की एकाच मूल्याकडे नेते. त्याऐवजी, तुम्ही मूल्य म्हणून `HashMap[address, bool]` वापरू शकता. डीफॉल्टनुसार प्रत्येक पत्त्यासाठी मूल्य `False` असते, याचा अर्थ तो ऑपरेटर नाही. तुम्ही आवश्यकतेनुसार मूल्ये `True` वर सेट करू शकता. + +```python +# @dev मिन्टरचा पत्ता, जो टोकन मिंट करू शकतो +minter: address +``` + +नवीन टोकन कोणत्यातरी प्रकारे तयार करावे लागतात. या कॉन्ट्रॅक्टमध्ये एकच संस्था आहे जिला तसे करण्याची परवानगी आहे, ती म्हणजे `minter`. उदाहरणार्थ, एका खेळासाठी हे पुरेसे असण्याची शक्यता आहे. इतर उद्देशांसाठी, अधिक क्लिष्ट व्यवसाय तर्क तयार करणे आवश्यक असू शकते. + +```python +# @dev इंटरफेस आयडी वरून ते समर्थित आहे की नाही याबद्दलच्या bool वर मॅपिंग +supportedInterfaces: HashMap[bytes32, bool] + +# @dev ERC165 चा ERC165 इंटरफेस आयडी +ERC165_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000001ffc9a7 + +# @dev ERC721 चा ERC165 इंटरफेस आयडी +ERC721_INTERFACE_ID: constant(bytes32) = 0x0000000000000000000000000000000000000000000000000000000080ac58cd +``` + +[ERC-165](https://eips.ethereum.org/EIPS/eip-165) एक यंत्रणा निर्दिष्ट करते ज्याद्वारे कॉन्ट्रॅक्ट उघड करू शकतो की ॲप्लिकेशन्स त्याच्याशी कसे संवाद साधू शकतात, तो कोणत्या ERCs चे पालन करतो. या प्रकरणात, कॉन्ट्रॅक्ट ERC-165 आणि ERC-721 चे पालन करतो. + +### फंक्शन्स {#functions} + +ही ती फंक्शन्स आहेत जी प्रत्यक्षात ERC-721 ची अंमलबजावणी करतात. + +#### कन्स्ट्रक्टर {#constructor} + +```python +@external +def __init__(): +``` + +Vyper मध्ये, Python प्रमाणेच, कन्स्ट्रक्टर फंक्शनला `__init__` म्हणतात. + +```python + """ + @dev कॉन्ट्रॅक्ट कन्स्ट्रक्टर. + """ +``` + +Python मध्ये, आणि Vyper मध्ये, तुम्ही एक मल्टी-लाइन स्ट्रिंग (जी `"""` ने सुरू होते आणि संपते) निर्दिष्ट करून आणि कोणत्याही प्रकारे तिचा वापर न करून देखील एक कमेंट तयार करू शकता. या कमेंट्समध्ये [NatSpec](https://vyper.readthedocs.io/en/latest/natspec.html) देखील समाविष्ट असू शकते. + +```python + self.supportedInterfaces[ERC165_INTERFACE_ID] = True + self.supportedInterfaces[ERC721_INTERFACE_ID] = True + self.minter = msg.sender +``` + +स्टेट व्हेरिएबल्स ऍक्सेस करण्यासाठी तुम्ही `self.` वापरता` (पुन्हा, Python प्रमाणेच). + +#### व्ह्यू फंक्शन्स {#views} + +ही अशी फंक्शन्स आहेत जी ब्लॉकचेनची स्थिती बदलत नाहीत, आणि म्हणून जर त्यांना बाह्यरित्या कॉल केले तर ते विनामूल्य कार्यान्वित केले जाऊ शकतात. जर व्ह्यू फंक्शन्सना कॉन्ट्रॅक्टद्वारे कॉल केले गेले तर त्यांना अजूनही प्रत्येक नोडवर कार्यान्वित करावे लागते आणि म्हणून गॅस खर्च येतो. + +```python +@view +@external +``` + +फंक्शनच्या व्याख्येपूर्वी हे कीवर्ड जे ऍट चिन्हासह (`@`) सुरू होतात, त्यांना _डेकोरेशन्स_ म्हणतात. ते फंक्शन कोणत्या परिस्थितीत कॉल केले जाऊ शकते हे निर्दिष्ट करतात. + +- `@view` निर्दिष्ट करते की हे फंक्शन एक व्ह्यू आहे. +- `@external` निर्दिष्ट करते की हे विशिष्ट फंक्शन व्यवहार आणि इतर कॉन्ट्रॅक्टद्वारे कॉल केले जाऊ शकते. + +```python +def supportsInterface(_interfaceID: bytes32) -> bool: +``` + +Python च्या उलट, Vyper ही एक [स्टॅटिक टाइप केलेली भाषा](https://wikipedia.org/wiki/Type_system#Static_type_checking) आहे. +तुम्ही [डेटा प्रकार](https://vyper.readthedocs.io/en/latest/types.html) ओळखल्याशिवाय व्हेरिएबल किंवा फंक्शन पॅरामीटर घोषित करू शकत नाही. या प्रकरणात इनपुट पॅरामीटर `bytes32` आहे, जे 256-बिट मूल्य आहे (256 बिट्स हे [Ethereum व्हर्च्युअल मशीन](/developers/docs/evm/) चा मूळ शब्द आकार आहे). आउटपुट एक बुलियन मूल्य आहे. प्रथेनुसार, फंक्शन पॅरामीटर्सची नावे अंडरस्कोर (`_`) ने सुरू होतात. + +```python + """ + @dev इंटरफेस ओळख ERC-165 मध्ये निर्दिष्ट आहे. + @param _interfaceID इंटरफेसचा आयडी + """ + return self.supportedInterfaces[_interfaceID] +``` + +`self.supportedInterfaces` HashMap मधून मूल्य परत करा, जे कन्स्ट्रक्टर (`__init__`) मध्ये सेट केलेले आहे. + +```python +### व्ह्यू फंक्शन्स ### + +``` + +ही व्ह्यू फंक्शन्स आहेत जी टोकनबद्दलची माहिती वापरकर्त्यांना आणि इतर कॉन्ट्रॅक्टसना उपलब्ध करून देतात. + +```python +@view +@external +def balanceOf(_owner: address) -> uint256: + """ + @dev `_owner` च्या मालकीच्या NFTs ची संख्या परत करते. + `_owner` शून्य पत्ता असल्यास थ्रो करते. शून्य पत्त्याला नियुक्त केलेले NFTs अवैध मानले जातात. + @param _owner ज्या पत्त्यासाठी बॅलन्सची चौकशी करायची आहे. + """ + assert _owner != ZERO_ADDRESS +``` + +ही ओळ [asserts](https://vyper.readthedocs.io/en/latest/statements.html#assert) करते की `_owner` शून्य नाही. जर ते असेल, तर एक त्रुटी आहे आणि ऑपरेशन परत घेतले जाते. + +```python + return self.ownerToNFTokenCount[_owner] + +@view +@external +def ownerOf(_tokenId: uint256) -> address: + """ + @dev NFT च्या मालकाचा पत्ता परत करते. + `_tokenId` वैध NFT नसल्यास थ्रो करते. + @param _tokenId NFT साठी ओळखकर्ता. + """ + owner: address = self.idToOwner[_tokenId] + # `_tokenId` वैध NFT नसल्यास थ्रो करते + assert owner != ZERO_ADDRESS + return owner +``` + +Ethereum व्हर्च्युअल मशीनमध्ये (evm) कोणतेही स्टोरेज ज्यामध्ये मूल्य संग्रहित नाही ते शून्य असते. +जर `_tokenId` वर कोणतेही टोकन नसेल तर `self.idToOwner[_tokenId]` चे मूल्य शून्य असते. त्या प्रकरणात फंक्शन परत जाते. + +```python +@view +@external +def getApproved(_tokenId: uint256) -> address: + """ + @dev एकाच NFT साठी मंजूर केलेला पत्ता मिळवा. + `_tokenId` वैध NFT नसल्यास थ्रो करते. + @param _tokenId ज्या NFT च्या मंजुरीची चौकशी करायची आहे त्याचा आयडी. + """ + # `_tokenId` वैध NFT नसल्यास थ्रो करते + assert self.idToOwner[_tokenId] != ZERO_ADDRESS + return self.idToApprovals[_tokenId] +``` + +लक्षात घ्या की `getApproved` _शून्य_ परत करू शकते. जर टोकन वैध असेल तर ते `self.idToApprovals[_tokenId]` परत करते. +जर कोणताही मंजूर करणारा नसेल तर ते मूल्य शून्य असते. + +```python +@view +@external +def isApprovedForAll(_owner: address, _operator: address) -> bool: + """ + @dev `_operator` हा `_owner` साठी मंजूर ऑपरेटर आहे की नाही हे तपासते. + @param _owner NFTs चा मालक असलेला पत्ता. + @param _operator मालकाच्या वतीने काम करणारा पत्ता. + """ + return (self.ownerToOperators[_owner])[_operator] +``` + +हे फंक्शन तपासते की `_operator` ला या कॉन्ट्रॅक्टमधील `_owner` च्या सर्व टोकनचे व्यवस्थापन करण्याची परवानगी आहे की नाही. +कारण एकापेक्षा जास्त ऑपरेटर असू शकतात, हे दोन-स्तरीय HashMap आहे. + +#### हस्तांतरण सहाय्यक फंक्शन्स {#transfer-helpers} + +ही फंक्शन्स टोकन हस्तांतरित करण्याच्या किंवा व्यवस्थापित करण्याच्या भागाच्या क्रियांची अंमलबजावणी करतात. + +```python + +### हस्तांतरण फंक्शन सहाय्यक ### + +@view +@internal +``` + +हे डेकोरेशन, `@internal`, याचा अर्थ असा की फंक्शन फक्त त्याच कॉन्ट्रॅक्टमधील इतर फंक्शन्समधूनच ऍक्सेसिबल आहे. प्रथेनुसार, या फंक्शनची नावे देखील अंडरस्कोर (`_`) ने सुरू होतात. + +```python +def _isApprovedOrOwner(_spender: address, _tokenId: uint256) -> bool: + """ + @dev दिलेला स्पेंडर दिलेला टोकन आयडी हस्तांतरित करू शकतो की नाही हे परत करते + @param spender चौकशी करण्यासाठी स्पेंडरचा पत्ता + @param tokenId हस्तांतरित करायच्या टोकनचा uint256 आयडी + @return bool msg.sender दिलेल्या टोकन आयडीसाठी मंजूर आहे की नाही, + मालकाचा ऑपरेटर आहे की नाही, किंवा टोकनचा मालक आहे की नाही + """ + owner: address = self.idToOwner[_tokenId] + spenderIsOwner: bool = owner == _spender + spenderIsApproved: bool = _spender == self.idToApprovals[_tokenId] + spenderIsApprovedForAll: bool = (self.ownerToOperators[owner])[_spender] + return (spenderIsOwner or spenderIsApproved) or spenderIsApprovedForAll +``` + +एका पत्त्याला टोकन हस्तांतरित करण्याची परवानगी देण्याचे तीन मार्ग आहेत: + +1. पत्ता टोकनचा मालक आहे +2. ते टोकन खर्च करण्यासाठी पत्त्याला मंजुरी आहे +3. पत्ता टोकनच्या मालकासाठी एक ऑपरेटर आहे + +वरील फंक्शन एक व्ह्यू असू शकते कारण ते स्थिती बदलत नाही. कार्य खर्च कमी करण्यासाठी, जे कोणतेही फंक्शन _व्ह्यू_ असू शकते ते _व्ह्यू_ असले पाहिजे. + +```python +@internal +def _addTokenTo(_to: address, _tokenId: uint256): + """ + @dev दिलेल्या पत्त्यावर NFT जोडा + `_tokenId` कोणाच्यातरी मालकीचा असल्यास थ्रो करते. + """ + # `_tokenId` कोणाच्यातरी मालकीचा असल्यास थ्रो करते + assert self.idToOwner[_tokenId] == ZERO_ADDRESS + # मालक बदला + self.idToOwner[_tokenId] = _to + # गणना ट्रॅकिंग बदला + self.ownerToNFTokenCount[_to] += 1 + + +@internal +def _removeTokenFrom(_from: address, _tokenId: uint256): + """ + @dev दिलेल्या पत्त्यावरून NFT काढा + `_from` सध्याचा मालक नसल्यास थ्रो करते. + """ + # `_from` सध्याचा मालक नसल्यास थ्रो करते + assert self.idToOwner[_tokenId] == _from + # मालक बदला + self.idToOwner[_tokenId] = ZERO_ADDRESS + # गणना ट्रॅकिंग बदला + self.ownerToNFTokenCount[_from] -= 1 +``` + +जेव्हा हस्तांतरणामध्ये समस्या येते तेव्हा आम्ही कॉल परत घेतो. + +```python +@internal +def _clearApproval(_owner: address, _tokenId: uint256): + """ + @dev दिलेल्या पत्त्याची मंजुरी साफ करा + `_owner` सध्याचा मालक नसल्यास थ्रो करते. + """ + # `_owner` सध्याचा मालक नसल्यास थ्रो करते + assert self.idToOwner[_tokenId] == _owner + if self.idToApprovals[_tokenId] != ZERO_ADDRESS: + # मंजुरी रीसेट करा + self.idToApprovals[_tokenId] = ZERO_ADDRESS +``` + +आवश्यक असल्यास फक्त मूल्य बदला. स्टेट व्हेरिएबल्स स्टोरेजमध्ये राहतात. स्टोरेजमध्ये लिहिणे ही EVM (Ethereum व्हर्च्युअल मशीन) च्या सर्वात महागड्या क्रियांपैकी एक आहे ([gas](/developers/docs/gas/) च्या बाबतीत). म्हणून, ते कमी करणे ही एक चांगली कल्पना आहे, अगदी विद्यमान मूल्य लिहिण्याचा खर्चही जास्त आहे. + +```python +@internal +def _transferFrom(_from: address, _to: address, _tokenId: uint256, _sender: address): + """ + @dev NFT चे हस्तांतरण कार्यान्वित करा. + `msg.sender` सध्याचा मालक, अधिकृत ऑपरेटर किंवा या NFT साठी मंजूर + पत्ता नसल्यास थ्रो करते. (टीप: खाजगी फंक्शनमध्ये `msg.sender` ला परवानगी नाही म्हणून `_sender` पास करा.) + `_to` शून्य पत्ता असल्यास थ्रो करते. + `_from` सध्याचा मालक नसल्यास थ्रो करते. + `_tokenId` वैध NFT नसल्यास थ्रो करते. + """ +``` + +आपल्याकडे हे अंतर्गत फंक्शन आहे कारण टोकन हस्तांतरित करण्याचे दोन मार्ग आहेत (नियमित आणि सुरक्षित), परंतु आम्हाला कोडमध्ये फक्त एकच स्थान हवे आहे जेथे आपण ते करतो जेणेकरून ऑडिट करणे सोपे होईल. + +```python + # आवश्यकता तपासा + assert self._isApprovedOrOwner(_sender, _tokenId) + # `_to` शून्य पत्ता असल्यास थ्रो करते + assert _to != ZERO_ADDRESS + # मंजुरी साफ करा. `_from` सध्याचा मालक नसल्यास थ्रो करते + self._clearApproval(_from, _tokenId) + # NFT काढा. `_tokenId` वैध NFT नसल्यास थ्रो करते + self._removeTokenFrom(_from, _tokenId) + # NFT जोडा + self._addTokenTo(_to, _tokenId) + # हस्तांतरण लॉग करा + log Transfer(_from, _to, _tokenId) +``` + +Vyper मध्ये इव्हेंट उत्सर्जित करण्यासाठी तुम्ही `log` स्टेटमेंट वापरता ([अधिक तपशिलांसाठी येथे पहा](https://vyper.readthedocs.io/en/latest/event-logging.html#event-logging)). + +#### हस्तांतरण फंक्शन्स {#transfer-funs} + +```python + +### हस्तांतरण फंक्शन्स ### + +@external +def transferFrom(_from: address, _to: address, _tokenId: uint256): + """ + @dev `msg.sender` सध्याचा मालक, अधिकृत ऑपरेटर किंवा या NFT साठी मंजूर + पत्ता नसल्यास थ्रो करते. + `_from` सध्याचा मालक नसल्यास थ्रो करते. + `_to` शून्य पत्ता असल्यास थ्रो करते. + `_tokenId` वैध NFT नसल्यास थ्रो करते. + @notice `_to` NFTs प्राप्त करण्यास सक्षम आहे याची पुष्टी करण्याची जबाबदारी कॉलरची आहे अन्यथा + ते कायमचे गमावले जाऊ शकतात. + @param _from NFT चा सध्याचा मालक. + @param _to नवीन मालक. + @param _tokenId हस्तांतरित करायचा NFT. + """ + self._transferFrom(_from, _to, _tokenId, msg.sender) +``` + +हे फंक्शन तुम्हाला एका अनियंत्रित पत्त्यावर हस्तांतरित करण्याची परवानगी देते. जोपर्यंत पत्ता वापरकर्त्याचा किंवा टोकन कसे हस्तांतरित करायचे हे जाणणाऱ्या कॉन्ट्रॅक्टचा नसेल, तोपर्यंत तुम्ही हस्तांतरित केलेले कोणतेही टोकन त्या पत्त्यात अडकून निरुपयोगी होईल. + +```python +@external +def safeTransferFrom( + _from: address, + _to: address, + _tokenId: uint256, + _data: Bytes[1024]=b"" + ): + """ + @dev एका पत्त्यावरून दुसऱ्या पत्त्यावर NFT ची मालकी हस्तांतरित करते. + `msg.sender` सध्याचा मालक, अधिकृत ऑपरेटर किंवा या NFT साठी मंजूर + पत्ता नसल्यास थ्रो करते. + `_from` सध्याचा मालक नसल्यास थ्रो करते. + `_to` शून्य पत्ता असल्यास थ्रो करते. + `_tokenId` वैध NFT नसल्यास थ्रो करते. + जर `_to` एक स्मार्ट कॉन्ट्रॅक्ट असेल, तर ते `_to` वर `onERC721Received` कॉल करते आणि + परत आलेले मूल्य `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` नसल्यास थ्रो करते. + टीप: bytes4 पॅडिंगसह bytes32 द्वारे दर्शविले जाते + @param _from NFT चा सध्याचा मालक. + @param _to नवीन मालक. + @param _tokenId हस्तांतरित करायचा NFT. + @param _data कोणताही निर्दिष्ट स्वरूप नसलेला अतिरिक्त डेटा, `_to` ला कॉलमध्ये पाठवला जातो. + """ + self._transferFrom(_from, _to, _tokenId, msg.sender) +``` + +प्रथम हस्तांतरण करणे ठीक आहे कारण जर काही समस्या आली तर आपण तरीही परत घेणार आहोत, त्यामुळे कॉलमध्ये केलेले सर्वकाही रद्द होईल. + +```python + if _to.is_contract: # `_to` हा कॉन्ट्रॅक्ट पत्ता आहे की नाही हे तपासा +``` + +प्रथम पत्ता कॉन्ट्रॅक्ट आहे की नाही हे तपासा (त्यात कोड आहे का). नसल्यास, तो वापरकर्त्याचा पत्ता आहे असे समजा आणि वापरकर्ता टोकन वापरू शकेल किंवा हस्तांतरित करू शकेल. पण ते तुम्हाला खोट्या सुरक्षिततेच्या भावनेत अडकू देऊ नका. तुम्ही टोकन गमावू शकता, अगदी `safeTransferFrom` सह देखील, जर तुम्ही त्यांना अशा पत्त्यावर हस्तांतरित केले ज्याची खाजगी की कोणालाही माहित नाही. + +```python + returnValue: bytes32 = ERC721Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) +``` + +लक्ष्य कॉन्ट्रॅक्टला ERC-721 टोकन प्राप्त करू शकतो की नाही हे पाहण्यासाठी कॉल करा. + +```python +# हस्तांतरणाचे गंतव्यस्थान असा कॉन्ट्रॅक्ट असल्यास जो 'onERC721Received' लागू करत नाही, तर थ्रो करते + assert returnValue == method_id("onERC721Received(address,address,uint256,bytes)", output_type=bytes32) +``` + +जर गंतव्यस्थान एक कॉन्ट्रॅक्ट असेल, परंतु जो ERC-721 टोकन स्वीकारत नाही (किंवा ज्याने हे विशिष्ट हस्तांतरण न स्वीकारण्याचा निर्णय घेतला आहे), तर परत घ्या. + +```python +@external +def approve(_approved: address, _tokenId: uint256): + """ + @dev NFT साठी मंजूर केलेला पत्ता सेट करा किंवा पुन्हा निश्चित करा. शून्य पत्ता सूचित करतो की कोणताही मंजूर पत्ता नाही. + `msg.sender` सध्याचा NFT मालक किंवा सध्याच्या मालकाचा अधिकृत ऑपरेटर नसल्यास थ्रो करते. + `_tokenId` वैध NFT नसल्यास थ्रो करते. (टीप: हे EIP मध्ये लिहिलेले नाही) + `_approved` सध्याचा मालक असल्यास थ्रो करते. (टीप: हे EIP मध्ये लिहिलेले नाही) + @param _approved दिलेल्या NFT आयडीसाठी मंजूर करायचा पत्ता. + @param _tokenId मंजूर करायच्या टोकनचा आयडी. + """ + owner: address = self.idToOwner[_tokenId] + # `_tokenId` वैध NFT नसल्यास थ्रो करते + assert owner != ZERO_ADDRESS + # `_approved` सध्याचा मालक असल्यास थ्रो करते + assert _approved != owner +``` + +प्रथेनुसार, जर तुम्हाला मंजूर करणारा नको असेल तर तुम्ही शून्य पत्ता नियुक्त करता, स्वतःला नाही. + +```python + # आवश्यकता तपासा + senderIsOwner: bool = self.idToOwner[_tokenId] == msg.sender + senderIsApprovedForAll: bool = (self.ownerToOperators[owner])[msg.sender] + assert (senderIsOwner or senderIsApprovedForAll) +``` + +मंजुरी सेट करण्यासाठी तुम्ही एकतर मालक असू शकता किंवा मालकाने अधिकृत केलेला ऑपरेटर असू शकता. + +```python + # मंजुरी सेट करा + self.idToApprovals[_tokenId] = _approved + log Approval(owner, _approved, _tokenId) + + +@external +def setApprovalForAll(_operator: address, _approved: bool): + """ + @dev तृतीय पक्षासाठी ('ऑपरेटर') `msg.sender` च्या सर्व मालमत्तेचे व्यवस्थापन + करण्यासाठी मंजुरी सक्षम किंवा अक्षम करते. हे ApprovalForAll इव्हेंट देखील उत्सर्जित करते. + `_operator` हा `msg.sender` असल्यास थ्रो करते. (टीप: हे EIP मध्ये लिहिलेले नाही) + @notice प्रेषकाकडे त्यावेळी कोणतेही टोकन नसले तरीही हे काम करते. + @param _operator अधिकृत ऑपरेटर्सच्या सेटमध्ये जोडायचा पत्ता. + @param _approved ऑपरेटर मंजूर असल्यास True, मंजुरी रद्द करण्यासाठी false. + """ + # `_operator` हा `msg.sender` असल्यास थ्रो करते + assert _operator != msg.sender + self.ownerToOperators[msg.sender][_operator] = _approved + log ApprovalForAll(msg.sender, _operator, _approved) +``` + +#### नवीन टोकन मिंट करणे आणि विद्यमान टोकन नष्ट करणे {#mint-burn} + +ज्या खात्याने कॉन्ट्रॅक्ट तयार केले आहे तो `minter` आहे, जो नवीन NFTs मिंट करण्यासाठी अधिकृत सुपर वापरकर्ता आहे. तथापि, त्यालाही विद्यमान टोकन बर्न करण्याची परवानगी नाही. फक्त मालक, किंवा मालकाने अधिकृत केलेली संस्था, ते करू शकते. + +```python +### मिंट आणि बर्न फंक्शन्स ### + +@external +def mint(_to: address, _tokenId: uint256) -> bool: +``` + +हे फंक्शन नेहमी `True` परत करते, कारण जर ऑपरेशन अयशस्वी झाले तर ते परत घेतले जाते. + +```python + """ + @dev टोकन मिंट करण्यासाठी फंक्शन + `msg.sender` मिन्टर नसल्यास थ्रो करते. + `_to` शून्य पत्ता असल्यास थ्रो करते. + `_tokenId` कोणाच्यातरी मालकीचा असल्यास थ्रो करते. + @param _to मिंट केलेले टोकन प्राप्त करणारा पत्ता. + @param _tokenId मिंट करायचा टोकन आयडी. + @return ऑपरेशन यशस्वी झाले की नाही हे दर्शवणारे बुलियन. + """ + # `msg.sender` मिन्टर नसल्यास थ्रो करते + assert msg.sender == self.minter +``` + +फक्त मिन्टर (ज्या खात्याने ERC-721 कॉन्ट्रॅक्ट तयार केले आहे) नवीन टोकन मिंट करू शकतो. भविष्यात जर आपल्याला मिन्टरची ओळख बदलायची असेल तर ही एक समस्या असू शकते. एका प्रोडक्शन कॉन्ट्रॅक्टमध्ये तुम्हाला कदाचित असे फंक्शन हवे असेल जे मिन्टरला मिन्टरचे विशेषाधिकार दुसऱ्या कोणालातरी हस्तांतरित करण्याची परवानगी देईल. + +```python + # `_to` शून्य पत्ता असल्यास थ्रो करते + assert _to != ZERO_ADDRESS + # NFT जोडा. `_tokenId` कोणाच्यातरी मालकीचा असल्यास थ्रो करते + self._addTokenTo(_to, _tokenId) + log Transfer(ZERO_ADDRESS, _to, _tokenId) + return True +``` + +प्रथेनुसार, नवीन टोकनचे मिंटिंग शून्य पत्त्यावरून हस्तांतरण म्हणून गणले जाते. + +```python + +@external +def burn(_tokenId: uint256): + """ + @dev विशिष्ट ERC721 टोकन बर्न करते. + `msg.sender` सध्याचा मालक, अधिकृत ऑपरेटर किंवा या NFT साठी मंजूर + पत्ता नसल्यास थ्रो करते. + `_tokenId` वैध NFT नसल्यास थ्रो करते. + @param _tokenId बर्न करायच्या ERC721 टोकनचा uint256 आयडी. + """ + # आवश्यकता तपासा + assert self._isApprovedOrOwner(msg.sender, _tokenId) + owner: address = self.idToOwner[_tokenId] + # `_tokenId` वैध NFT नसल्यास थ्रो करते + assert owner != ZERO_ADDRESS + self._clearApproval(owner, _tokenId) + self._removeTokenFrom(owner, _tokenId) + log Transfer(owner, ZERO_ADDRESS, _tokenId) +``` + +ज्यालाही टोकन हस्तांतरित करण्याची परवानगी आहे त्याला ते बर्न करण्याची परवानगी आहे. बर्न हे शून्य पत्त्यावर हस्तांतरणासारखे दिसत असले तरी, शून्य पत्त्याला प्रत्यक्षात टोकन मिळत नाही. हे आपल्याला टोकनसाठी वापरलेले सर्व स्टोरेज मोकळे करण्याची परवानगी देते, ज्यामुळे व्यवहाराचा गॅस खर्च कमी होऊ शकतो. + +## हे कॉन्ट्रॅक्ट वापरणे {#using-contract} + +Solidity च्या उलट, Vyper मध्ये इनहेरिटन्स नाही. कोड अधिक स्पष्ट आणि त्यामुळे सुरक्षित करणे सोपे करण्यासाठी ही एक जाणीवपूर्वक केलेली डिझाइन निवड आहे. म्हणून तुमचा स्वतःचा Vyper ERC-721 कॉन्ट्रॅक्ट तयार करण्यासाठी तुम्ही [हा कॉन्ट्रॅक्ट](https://github.com/vyperlang/vyper/blob/master/examples/tokens/ERC721.vy) घ्या आणि तुम्हाला हव्या असलेल्या व्यवसाय तर्काची अंमलबजावणी करण्यासाठी त्यात बदल करा. + +## निष्कर्ष {#conclusion} + +पुनरावलोकनासाठी, या कॉन्ट्रॅक्टमधील काही सर्वात महत्त्वाचे विचार येथे आहेत: + +- सुरक्षित हस्तांतरणासह ERC-721 टोकन प्राप्त करण्यासाठी, कॉन्ट्रॅक्ट्सना `ERC721Receiver` इंटरफेस लागू करावा लागतो. +- तुम्ही सुरक्षित हस्तांतरण वापरत असलात तरीही, टोकन अडकू शकतात जर तुम्ही त्यांना अशा पत्त्यावर पाठवले ज्याची खाजगी की अज्ञात आहे. +- जेव्हा ऑपरेशनमध्ये समस्या येते तेव्हा फक्त अयशस्वी मूल्य परत करण्याऐवजी कॉल `revert` करणे ही एक चांगली कल्पना आहे. +- ERC-721 टोकन तेव्हा अस्तित्वात असतात जेव्हा त्यांचा मालक असतो. +- NFT हस्तांतरित करण्यासाठी अधिकृत होण्याचे तीन मार्ग आहेत. तुम्ही मालक असू शकता, विशिष्ट टोकनसाठी मंजूर असू शकता, किंवा मालकाच्या सर्व टोकनसाठी ऑपरेटर असू शकता. +- मागील इव्हेंट फक्त ब्लॉकचेनच्या बाहेर दिसतात. ब्लॉकचेनच्या आत चालणारा कोड ते पाहू शकत नाही. + +आता जा आणि सुरक्षित Vyper कॉन्ट्रॅक्ट्स लागू करा. + +[माझ्या कामाबद्दल अधिक माहितीसाठी येथे पहा](https://cryptodocguy.pro/). + diff --git a/public/content/translations/mr/developers/tutorials/erc20-annotated-code/index.md b/public/content/translations/mr/developers/tutorials/erc20-annotated-code/index.md new file mode 100644 index 00000000000..77ded2dfd5c --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/erc20-annotated-code/index.md @@ -0,0 +1,917 @@ +--- +title: "ERC-20 कॉन्ट्रॅक्ट वॉक-थ्रू" +description: "OpenZeppelin ERC-20 कॉन्ट्रॅक्टमध्ये काय आहे आणि ते तिथे का आहे?" +author: Ori Pomerantz +lang: mr +tags: [ "सॉलिडिटी", "erc-20" ] +skill: beginner +published: 2021-03-09 +--- + +## प्रस्तावना {#introduction} + +Ethereum च्या सर्वात सामान्य उपयोगांपैकी एक म्हणजे एखाद्या गटाने एक ट्रेडेबल टोकन तयार करणे, एका अर्थाने त्यांचे स्वतःचे चलन. हे टोकन सामान्यतः एका मानकाचे पालन करतात, +[ERC-20](/developers/docs/standards/tokens/erc-20/). हे मानक लिक्विडिटी पूल आणि वॉलेटसारखी साधने लिहिणे शक्य करते, जे सर्व ERC-20 +टोकनसोबत काम करतात. या लेखात आपण +[OpenZeppelin Solidity ERC20 अंमलबजावणी](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol), तसेच +[इंटरफेस परिभाषा](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) याचे विश्लेषण करू. + +हा भाष्य केलेला सोर्स कोड आहे. तुम्हाला ERC-20 लागू करायचे असल्यास, +[हे ट्यूटोरियल वाचा](https://docs.openzeppelin.com/contracts/2.x/erc20-supply). + +## इंटरफेस {#the-interface} + +ERC-20 सारख्या मानकाचा उद्देश अनेक टोकन अंमलबजावणींना परवानगी देणे आहे जे वॉलेट आणि विकेंद्रित एक्सचेंजेस सारख्या ॲप्लिकेशन्समध्ये इंटरऑपरेबल आहेत. हे साध्य करण्यासाठी, आम्ही एक +[इंटरफेस](https://www.geeksforgeeks.org/solidity/solidity-basics-of-interface/) तयार करतो. ज्या कोणत्याही कोडला टोकन कॉन्ट्रॅक्ट वापरण्याची आवश्यकता आहे, तो +इंटरफेसमधील समान परिभाषा वापरू शकतो आणि ते वापरणाऱ्या सर्व टोकन कॉन्ट्रॅक्टसोबत सुसंगत असू शकतो, मग ते +MetaMask सारखे वॉलेट असो, etherscan.io सारखे dapp असो, किंवा लिक्विडिटी पूल सारखे वेगळे कॉन्ट्रॅक्ट असो. + +![ERC-20 इंटरफेसचे उदाहरण](erc20_interface.png) + +तुम्ही अनुभवी प्रोग्रामर असाल तर, तुम्हाला [Java](https://www.w3schools.com/java/java_interface.asp) मध्ये +किंवा [C हेडर फाइल्स](https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html) मध्ये समान रचना पाहिल्याचे आठवत असेल. + +ही OpenZeppelin कडील [ERC-20 इंटरफेस](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) ची +परिभाषा आहे. हे [मानव वाचनीय मानक](https://eips.ethereum.org/EIPS/eip-20) चे Solidity कोडमधील भाषांतर आहे. अर्थात, इंटरफेस +स्वतः काहीही _कसे_ करायचे हे परिभाषित करत नाही. ते खालील कॉन्ट्रॅक्ट सोर्स कोडमध्ये स्पष्ट केले आहे. + +  + +```solidity +// SPDX-License-Identifier: MIT +``` + +Solidity फाइल्समध्ये परवाना ओळखकर्ता समाविष्ट करणे अपेक्षित आहे. [तुम्ही परवान्यांची यादी येथे पाहू शकता](https://spdx.org/licenses/). तुम्हाला वेगळा परवाना +हवा असल्यास, तो कमेंट्समध्ये स्पष्ट करा. + +  + +```solidity +pragma solidity >=0.6.0 <0.8.0; +``` + +Solidity भाषा अजूनही वेगाने विकसित होत आहे, आणि नवीन आवृत्त्या जुन्या कोडसोबत सुसंगत असू शकत नाहीत +([येथे पहा](https://docs.soliditylang.org/en/v0.7.0/070-breaking-changes.html)). म्हणून, केवळ भाषेची किमान +आवृत्तीच नव्हे, तर कमाल आवृत्ती, ज्या नवीनतम आवृत्तीसह तुम्ही कोडची चाचणी केली आहे, ती देखील निर्दिष्ट करणे एक चांगली कल्पना आहे. + +  + +```solidity +/** + * @dev EIP मध्ये परिभाषित केल्यानुसार ERC20 मानकाचा इंटरफेस. + */ +``` + +कमेंटमधील `@dev` हा [NatSpec फॉरमॅट](https://docs.soliditylang.org/en/develop/natspec-format.html) चा भाग आहे, जो सोर्स कोडमधून +डॉक्युमेंटेशन तयार करण्यासाठी वापरला जातो. + +  + +```solidity +interface IERC20 { +``` + +परंपरेनुसार, इंटरफेसची नावे `I` ने सुरू होतात. + +  + +```solidity + /** + * @dev अस्तित्वात असलेल्या टोकनची संख्या परत करते. + */ + function totalSupply() external view returns (uint256); +``` + +हे फंक्शन `external` आहे, म्हणजे [ते फक्त कॉन्ट्रॅक्टच्या बाहेरूनच कॉल केले जाऊ शकते](https://docs.soliditylang.org/en/v0.7.0/cheatsheet.html#index-2). +ते कॉन्ट्रॅक्टमधील टोकनचा एकूण पुरवठा परत करते. हे मूल्य Ethereum मधील सर्वात सामान्य प्रकार, unsigned 256 bits (256 bits हा EVM चा +नेटिव्ह वर्ड आकार आहे) वापरून परत केले जाते. हे फंक्शन `view` देखील आहे, ज्याचा अर्थ ते स्टेट बदलत नाही, त्यामुळे ते ब्लॉकचेनमधील प्रत्येक +नोडवर चालवण्याऐवजी एकाच नोडवर कार्यान्वित केले जाऊ शकते. या प्रकारचे फंक्शन व्यवहार तयार करत नाही आणि त्याला [gas](/developers/docs/gas/) लागत नाही. + +**टीप:** सैद्धांतिकदृष्ट्या असे दिसू शकते की कॉन्ट्रॅक्टचा निर्माता वास्तविक मूल्यापेक्षा कमी एकूण पुरवठा परत करून फसवणूक करू शकतो, ज्यामुळे प्रत्येक टोकन +प्रत्यक्षात आहे त्यापेक्षा अधिक मौल्यवान दिसेल. तथापि, ती भीती ब्लॉकचेनच्या खऱ्या स्वरूपाकडे दुर्लक्ष करते. ब्लॉकचेनवर जे काही घडते ते प्रत्येक +नोडद्वारे सत्यापित केले जाऊ शकते. हे साध्य करण्यासाठी, प्रत्येक कॉन्ट्रॅक्टचा मशीन लँग्वेज कोड आणि स्टोरेज प्रत्येक नोडवर उपलब्ध आहे. तुम्ही तुमच्या कॉन्ट्रॅक्टसाठी Solidity +कोड प्रकाशित करणे आवश्यक नसले तरी, जोपर्यंत तुम्ही सोर्स कोड आणि ज्या Solidity आवृत्तीसह तो संकलित केला होता ती प्रकाशित करत नाही तोपर्यंत कोणीही तुम्हाला गांभीर्याने घेणार नाही, जेणेकरून +तुम्ही प्रदान केलेल्या मशीन लँग्वेज कोडविरुद्ध ते सत्यापित केले जाऊ शकते. +उदाहरणार्थ, [हा कॉन्ट्रॅक्ट](https://eth.blockscout.com/address/0xa530F85085C6FE2f866E7FdB716849714a89f4CD?tab=contract) पहा. + +  + +```solidity + /** + * @dev `account` च्या मालकीच्या टोकनची संख्या परत करते. + */ + function balanceOf(address account) external view returns (uint256); +``` + +नावाप्रमाणेच, `balanceOf` खात्याची शिल्लक परत करते. Ethereum खाती Solidity मध्ये `address` प्रकार वापरून ओळखली जातात, ज्यात 160 बिट्स असतात. +ते `external` आणि `view` देखील आहे. + +  + +```solidity + /** + * @dev कॉलरच्या खात्यातून `recipient` कडे `amount` टोकन हलवते. + * + * ऑपरेशन यशस्वी झाले की नाही हे दर्शवणारे बुलियन मूल्य परत करते. + * + * एक {Transfer} इव्हेंट उत्सर्जित करते. + */ + function transfer(address recipient, uint256 amount) external returns (bool); +``` + +`transfer` फंक्शन कॉलरकडून दुसऱ्या पत्त्यावर टोकन हस्तांतरित करते. यात स्टेटमध्ये बदल समाविष्ट आहे, म्हणून ते `view` नाही. +जेव्हा वापरकर्ता हे फंक्शन कॉल करतो तेव्हा ते एक व्यवहार तयार करते आणि त्याला गॅस लागतो. ते एक इव्हेंट, `Transfer`, देखील उत्सर्जित करते, ज्यामुळे ब्लॉकचेनवरील +सर्वांना या घटनेची माहिती मिळते. + +फंक्शनमध्ये दोन वेगवेगळ्या प्रकारच्या कॉलर्ससाठी दोन प्रकारचे आउटपुट आहेत: + +- जे वापरकर्ते थेट वापरकर्ता इंटरफेसवरून फंक्शन कॉल करतात. सामान्यतः वापरकर्ता एक व्यवहार + सादर करतो आणि प्रतिसादाची वाट पाहत नाही, ज्याला अनिश्चित कालावधी लागू शकतो. व्यवहाराची पावती (जी व्यवहाराच्या हॅशद्वारे ओळखली जाते) शोधून किंवा + `Transfer` इव्हेंट शोधून वापरकर्ता काय झाले ते पाहू शकतो. +- इतर कॉन्ट्रॅक्ट, जे एकूण व्यवहाराचा भाग म्हणून फंक्शन कॉल करतात. त्या कॉन्ट्रॅक्टना ताबडतोब निकाल मिळतो, + कारण ते त्याच व्यवहारात चालतात, त्यामुळे ते फंक्शन रिटर्न व्हॅल्यू वापरू शकतात. + +कॉन्ट्रॅक्टच्या स्टेटमध्ये बदल करणाऱ्या इतर फंक्शन्सद्वारे समान प्रकारचे आउटपुट तयार केले जाते. + +  + +अलाउन्स एका खात्याला दुसऱ्या मालकाच्या मालकीचे काही टोकन खर्च करण्याची परवानगी देतात. +हे उपयुक्त आहे, उदाहरणार्थ, विक्रेते म्हणून काम करणाऱ्या कॉन्ट्रॅक्टसाठी. कॉन्ट्रॅक्ट इव्हेंट्ससाठी +निरीक्षण करू शकत नाहीत, म्हणून जर खरेदीदाराने थेट विक्रेता कॉन्ट्रॅक्टला टोकन हस्तांतरित केले +तर त्या कॉन्ट्रॅक्टला पैसे भरले गेले आहेत हे कळणार नाही. त्याऐवजी, खरेदीदार विक्रेता +कॉन्ट्रॅक्टला एक निश्चित रक्कम खर्च करण्याची परवानगी देतो, आणि विक्रेता ती रक्कम हस्तांतरित करतो. +हे विक्रेता कॉन्ट्रॅक्ट कॉल करत असलेल्या फंक्शनद्वारे केले जाते, जेणेकरून विक्रेता कॉन्ट्रॅक्टला +ते यशस्वी झाले की नाही हे कळू शकेल. + +```solidity + /** + * @dev `spender` ला {transferFrom} द्वारे `owner` च्या वतीने खर्च करण्याची परवानगी असलेल्या + * टोकनची उर्वरित संख्या परत करते. हे + * डीफॉल्टनुसार शून्य असते. + * + * जेव्हा {approve} किंवा {transferFrom} कॉल केले जाते तेव्हा हे मूल्य बदलते. + */ + function allowance(address owner, address spender) external view returns (uint256); +``` + +`allowance` फंक्शन कोणालाही हे तपासण्याची परवानगी देते की एक +पत्ता (`owner`) दुसऱ्या पत्त्याला (`spender`) किती खर्च करू देतो. + +  + +```solidity + /** + * @dev कॉलरच्या टोकनवर `spender` चा अलाउन्स म्हणून `amount` सेट करते. + * + * ऑपरेशन यशस्वी झाले की नाही हे दर्शवणारे बुलियन मूल्य परत करते. + * + * महत्त्वाचे: सावध रहा की या पद्धतीसह अलाउन्स बदलण्यामुळे + * दुर्दैवी व्यवहार क्रमाने कोणीतरी जुने आणि नवीन दोन्ही अलाउन्स वापरण्याचा धोका + * असतो. या रेस कंडीशनला कमी करण्याचा एक संभाव्य उपाय म्हणजे + * प्रथम स्पेंडरचा अलाउन्स 0 पर्यंत कमी करणे आणि नंतर + * इच्छित मूल्य सेट करणे: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * एक {Approval} इव्हेंट उत्सर्जित करते. + */ + function approve(address spender, uint256 amount) external returns (bool); +``` + +`approve` फंक्शन अलाउन्स तयार करते. त्याचा गैरवापर कसा होऊ शकतो याबद्दलचा +संदेश वाचण्याची खात्री करा. Ethereum मध्ये तुम्ही तुमच्या स्वतःच्या व्यवहारांच्या क्रमावर नियंत्रण ठेवता, +परंतु तुम्ही इतर लोकांचे व्यवहार कोणत्या क्रमाने +पार पाडले जातील यावर नियंत्रण ठेवू शकत नाही, जोपर्यंत तुम्ही दुसऱ्या बाजूचा +व्यवहार झाल्याचे पाहत नाही तोपर्यंत तुम्ही तुमचा स्वतःचा व्यवहार सादर करत नाही. + +  + +```solidity + /** + * @dev अलाउन्स यंत्रणा वापरून `sender` कडून `recipient` कडे `amount` टोकन हलवते. + * `amount` नंतर कॉलरच्या + * अलाउन्स मधून वजा केली जाते. + * + * ऑपरेशन यशस्वी झाले की नाही हे दर्शवणारे बुलियन मूल्य परत करते. + * + * एक {Transfer} इव्हेंट उत्सर्जित करते. + */ + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); +``` + +शेवटी, `transferFrom` चा वापर स्पेंडरद्वारे अलाउन्स प्रत्यक्षात खर्च करण्यासाठी केला जातो. + +  + +```solidity + + /** + * @dev जेव्हा `value` टोकन एका खात्यातून (`from`) दुसऱ्या खात्यात (`to`) हलवले जातात तेव्हा उत्सर्जित होते. + * + * लक्षात घ्या की `value` शून्य असू शकते. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev जेव्हा {approve} ला कॉल करून `owner` साठी `spender` चा अलाउन्स सेट केला जातो तेव्हा उत्सर्जित होते. `value` हा नवीन अलाउन्स आहे. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); +} +``` + +जेव्हा ERC-20 कॉन्ट्रॅक्टची स्टेट बदलते तेव्हा हे इव्हेंट्स उत्सर्जित होतात. + +## वास्तविक कॉन्ट्रॅक्ट {#the-actual-contract} + +हा वास्तविक कॉन्ट्रॅक्ट आहे जो ERC-20 मानकाची अंमलबजावणी करतो, +[येथून घेतला आहे](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol). +तो आहे तसा वापरण्यासाठी नाही, परंतु तुम्ही +त्याचा वापरण्यायोग्य गोष्टीत विस्तार करण्यासाठी त्यातून [इनहेरिट](https://www.tutorialspoint.com/solidity/solidity_inheritance.htm) करू शकता. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity >=0.6.0 <0.8.0; +``` + +  + +### इम्पोर्ट स्टेटमेंट {#import-statements} + +वरील इंटरफेस परिभाषांव्यतिरिक्त, कॉन्ट्रॅक्ट परिभाषा दोन इतर फाइल्स इम्पोर्ट करते: + +```solidity + +import "../../GSN/Context.sol"; +import "./IERC20.sol"; +import "../../math/SafeMath.sol"; +``` + +- `GSN/Context.sol` ही [OpenGSN](https://www.opengsn.org/) वापरण्यासाठी आवश्यक असलेली परिभाषा आहे, ही एक प्रणाली आहे जी इथर नसलेल्या वापरकर्त्यांना + ब्लॉकचेन वापरण्याची परवानगी देते. लक्षात घ्या की ही एक जुनी आवृत्ती आहे, तुम्हाला OpenGSN सोबत एकत्रीकरण करायचे असल्यास + [हे ट्यूटोरियल वापरा](https://docs.opengsn.org/javascript-client/tutorial.html). +- [SafeMath लायब्ररी](https://ethereumdev.io/using-safe-math-library-to-prevent-from-overflows/), जी Solidity आवृत्त्या **<0.8.0** साठी + अंकगणित ओव्हरफ्लो/अंडरफ्लो प्रतिबंधित करते. Solidity ≥0.8.0 मध्ये, अंकगणितीय क्रिया ओव्हरफ्लो/अंडरफ्लोवर आपोआप + रिव्हर्ट होतात, ज्यामुळे SafeMath अनावश्यक बनते. हा कॉन्ट्रॅक्ट जुन्या कंपाइलर आवृत्त्यांसह बॅकवर्ड कंपॅटिबिलिटीसाठी + SafeMath वापरतो. + +  + +ही कमेंट कॉन्ट्रॅक्टचा उद्देश स्पष्ट करते. + +```solidity +/** + * @dev {IERC20} इंटरफेसची अंमलबजावणी. + * + * ही अंमलबजावणी टोकन कसे तयार केले जातात या बाबतीत अनभिज्ञ आहे. याचा अर्थ + * {_mint} वापरून एका साधित कॉन्ट्रॅक्टमध्ये पुरवठा यंत्रणा जोडणे आवश्यक आहे. + * एका सामान्य यंत्रणेसाठी {ERC20PresetMinterPauser} पहा. + * + * टीप: तपशीलवार लेखनासाठी आमचे मार्गदर्शक पहा + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[पुरवठा + * यंत्रणा कशी लागू करावी]. + * + * आम्ही सामान्य OpenZeppelin मार्गदर्शक तत्त्वांचे पालन केले आहे: अयशस्वी झाल्यास `false` परत करण्याऐवजी + * फंक्शन्स रिव्हर्ट होतात. तरीही हे वर्तन पारंपारिक + * आहे आणि ERC20 ॲप्लिकेशन्सच्या अपेक्षांशी संघर्ष करत नाही. + * + * याव्यतिरिक्त, {transferFrom} ला कॉल केल्यावर एक {Approval} इव्हेंट उत्सर्जित होतो. + * हे ॲप्लिकेशन्सना केवळ उक्त इव्हेंट्स ऐकून सर्व खात्यांसाठी + * अलाउन्सची पुनर्रचना करण्यास अनुमती देते. EIP च्या इतर अंमलबजावणी + * हे इव्हेंट्स उत्सर्जित करू शकत नाहीत, कारण स्पेसिफिकेशननुसार ते आवश्यक नाही. + * + * शेवटी, अलाउन्स सेट करण्याच्या + * सुप्रसिद्ध समस्या कमी करण्यासाठी नॉन-स्टँडर्ड {decreaseAllowance} आणि {increaseAllowance} + * फंक्शन्स जोडले गेले आहेत. {IERC20-approve} पहा. + */ + +``` + +### कॉन्ट्रॅक्ट परिभाषा {#contract-definition} + +```solidity +contract ERC20 is Context, IERC20 { +``` + +ही ओळ इनहेरिटन्स निर्दिष्ट करते, या प्रकरणात वरील `IERC20` आणि OpenGSN साठी `Context` मधून. + +  + +```solidity + + using SafeMath for uint256; + +``` + +ही ओळ `SafeMath` लायब्ररीला `uint256` प्रकाराशी जोडते. तुम्ही ही लायब्ररी +[येथे](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol) शोधू शकता. + +### व्हेरिएबल परिभाषा {#variable-definitions} + +या परिभाषा कॉन्ट्रॅक्टचे स्टेट व्हेरिएबल्स निर्दिष्ट करतात. हे व्हेरिएबल्स `private` घोषित केले आहेत, परंतु +त्याचा अर्थ फक्त एवढाच आहे की ब्लॉकचेनवरील इतर कॉन्ट्रॅक्ट ते वाचू शकत नाहीत. _ब्लॉकचेनवर कोणतीही +रहस्ये नाहीत_, प्रत्येक नोडवरील सॉफ्टवेअरमध्ये प्रत्येक ब्लॉकवर प्रत्येक कॉन्ट्रॅक्टची +स्टेट असते. परंपरेनुसार, स्टेट व्हेरिएबल्सना `_` असे नाव दिले जाते. + +पहिले दोन व्हेरिएबल्स [मॅपिंग्स](https://www.tutorialspoint.com/solidity/solidity_mappings.htm) आहेत, +म्हणजे ते साधारणपणे [असोसिएटिव्ह ॲरे](https://wikipedia.org/wiki/Associative_array) सारखेच +वागतात, फक्त कीज संख्यात्मक मूल्ये आहेत. स्टोरेज फक्त त्या नोंदींसाठी वाटप केले जाते ज्यांची मूल्ये डीफॉल्टपेक्षा +(शून्य) वेगळी आहेत. + +```solidity + mapping (address => uint256) private _balances; +``` + +पहिले मॅपिंग, `_balances`, हे पत्ते आणि त्यांचे या टोकनचे संबंधित शिल्लक आहेत. शिल्लक ऍक्सेस करण्यासाठी, +हे सिंटॅक्स वापरा: `_balances[
]`. + +  + +```solidity + mapping (address => mapping (address => uint256)) private _allowances; +``` + +हा व्हेरिएबल, `_allowances`, पूर्वी स्पष्ट केलेले अलाउन्स संग्रहित करतो. पहिला इंडेक्स टोकनचा मालक +आहे, आणि दुसरा अलाउन्स असलेला कॉन्ट्रॅक्ट आहे. पत्ता A पत्ता B च्या खात्यातून किती रक्कम +खर्च करू शकतो हे ऍक्सेस करण्यासाठी, `_allowances[B][A]` वापरा. + +  + +```solidity + uint256 private _totalSupply; +``` + +नावाप्रमाणेच, हा व्हेरिएबल टोकनच्या एकूण पुरवठ्याचा मागोवा ठेवतो. + +  + +```solidity + string private _name; + string private _symbol; + uint8 private _decimals; +``` + +हे तीन व्हेरिएबल्स वाचनीयता सुधारण्यासाठी वापरले जातात. पहिले दोन स्व-स्पष्ट आहेत, परंतु `_decimals` +नाही. + +एकीकडे, Ethereum मध्ये फ्लोटिंग पॉइंट किंवा अपूर्णांक व्हेरिएबल्स नाहीत. दुसरीकडे, +मानवांना टोकन विभाजित करता येणे आवडते. लोकांनी चलनी म्हणून सोन्याचा स्वीकार करण्याचे एक कारण म्हणजे +जेव्हा कोणी गाईच्या मूल्याचे बदक विकत घेऊ इच्छित असेल तेव्हा सुटे पैसे करणे कठीण होते. + +यावर उपाय म्हणजे पूर्णांकांचा मागोवा ठेवणे, परंतु वास्तविक टोकनऐवजी जवळजवळ +निरुपयोगी असलेल्या अपूर्णांक टोकनची गणना करणे. इथरच्या बाबतीत, अपूर्णांक टोकनला wei म्हणतात, आणि 10^18 wei एका +ETH च्या बरोबर आहे. लिहिताना, 10,000,000,000,000 wei अंदाजे एक यूएस किंवा युरो सेंट आहे. + +ॲप्लिकेशन्सना टोकन शिल्लक कशी प्रदर्शित करायची हे माहित असणे आवश्यक आहे. जर वापरकर्त्याकडे 3,141,000,000,000,000,000 wei असतील, तर ते +3.14 ETH आहे का? 31.41 ETH? 3,141 ETH? इथरच्या बाबतीत ते 10^18 wei प्रति ETH असे परिभाषित केले आहे, परंतु तुमच्या +टोकनसाठी तुम्ही वेगळे मूल्य निवडू शकता. जर टोकनचे विभाजन करणे अर्थपूर्ण नसेल, तर तुम्ही +शून्य `_decimals` मूल्य वापरू शकता. तुम्हाला ETH प्रमाणेच मानक वापरायचे असल्यास, **18** हे मूल्य वापरा. + +### कन्स्ट्रक्टर {#the-constructor} + +```solidity + /** + * @dev {name} आणि {symbol} साठी मूल्ये सेट करते, {decimals} ला + * 18 च्या डीफॉल्ट मूल्याने सुरू करते. + * + * {decimals} साठी वेगळे मूल्य निवडण्यासाठी, {_setupDecimals} वापरा. + * + * ही तिन्ही मूल्ये अपरिवर्तनीय आहेत: ती फक्त एकदाच + * बांधकामादरम्यान सेट केली जाऊ शकतात. + */ + constructor (string memory name_, string memory symbol_) public { + // Solidity ≥0.7.0 मध्ये, 'public' अंतर्निहित आहे आणि वगळले जाऊ शकते. + + _name = name_; + _symbol = symbol_; + _decimals = 18; + } +``` + +जेव्हा कॉन्ट्रॅक्ट प्रथम तयार केला जातो तेव्हा कन्स्ट्रक्टर कॉल केला जातो. परंपरेनुसार, फंक्शन पॅरामीटर्सना `_` असे नाव दिले जाते. + +### वापरकर्ता इंटरफेस फंक्शन्स {#user-interface-functions} + +```solidity + /** + * @dev टोकनचे नाव परत करते. + */ + function name() public view returns (string memory) { + return _name; + } + + /** + * @dev टोकनचे चिन्ह परत करते, सहसा नावाचे एक छोटे रूप. + */ + function symbol() public view returns (string memory) { + return _symbol; + } + + /** + * @dev वापरकर्त्याचे प्रतिनिधित्व मिळविण्यासाठी वापरलेल्या दशांशांची संख्या परत करते. + * उदाहरणार्थ, जर `decimals` `2` च्या बरोबर असेल, तर `505` टोकनची शिल्लक वापरकर्त्याला `5,05` (`505 / 10 ** 2`) म्हणून प्रदर्शित केली पाहिजे. + * + * टोकन सहसा 18 चे मूल्य निवडतात, जे इथर आणि wei यांच्यातील संबंधाचे अनुकरण करते. + * हे मूल्य {ERC20} वापरते, जोपर्यंत {_setupDecimals} कॉल केले जात नाही. + * + * टीप: ही माहिती केवळ _प्रदर्शन_ हेतूंसाठी वापरली जाते: ती कोणत्याही प्रकारे कराराच्या अंकगणितावर परिणाम करत नाही, + * {IERC20-balanceOf} आणि {IERC20-transfer} यासह. + */ + function decimals() public view returns (uint8) { + return _decimals; + } +``` + +ही फंक्शन्स, `name`, `symbol`, आणि `decimals` वापरकर्ता इंटरफेसना तुमच्या कॉन्ट्रॅक्टबद्दल माहिती देतात जेणेकरून ते ते योग्यरित्या प्रदर्शित करू शकतील. + +रिटर्न प्रकार `string memory` आहे, म्हणजे मेमरीमध्ये संग्रहित केलेली स्ट्रिंग परत करणे. व्हेरिएबल्स, जसे की +स्ट्रिंग्स, तीन ठिकाणी संग्रहित केले जाऊ शकतात: + +| | आयुष्य | कॉन्ट्रॅक्ट ऍक्सेस | गॅस खर्च | +| ------- | ----------------- | ------------------ | ----------------------------------------------------------------- | +| मेमरी | फंक्शन कॉल | वाचन/लेखन | दहा किंवा शेकडो (उच्च स्थानांसाठी अधिक) | +| कॉलडेटा | फंक्शन कॉल | केवळ वाचनीय | रिटर्न प्रकार म्हणून वापरता येत नाही, केवळ फंक्शन पॅरामीटर प्रकार | +| स्टोरेज | बदलल्या जाईपर्यंत | वाचन/लेखन | उच्च (वाचनासाठी 800, लेखनासाठी 20k) | + +या प्रकरणात, `memory` हा सर्वोत्तम पर्याय आहे. + +### टोकन माहिती वाचा {#read-token-information} + +ही फंक्शन्स आहेत जी टोकनबद्दल माहिती प्रदान करतात, एकतर एकूण पुरवठा किंवा +खात्याची शिल्लक. + +```solidity + /** + * @dev {IERC20-totalSupply} पहा. + */ + function totalSupply() public view override returns (uint256) { + return _totalSupply; + } +``` + +`totalSupply` फंक्शन टोकनचा एकूण पुरवठा परत करते. + +  + +```solidity + /** + * @dev {IERC20-balanceOf} पहा. + */ + function balanceOf(address account) public view override returns (uint256) { + return _balances[account]; + } +``` + +खात्याची शिल्लक वाचा. लक्षात घ्या की कोणालाही दुसऱ्याच्या खात्याची शिल्लक +मिळवण्याची परवानगी आहे. ही माहिती लपवण्याचा प्रयत्न करण्यात काहीच अर्थ नाही, कारण ती प्रत्येक +नोडवर तरीही उपलब्ध आहे. _ब्लॉकचेनवर कोणतीही रहस्ये नाहीत._ + +### टोकन हस्तांतरित करा {#transfer-tokens} + +```solidity + /** + * @dev {IERC20-transfer} पहा. + * + * आवश्यकता: + * + * - `recipient` शून्य पत्ता असू शकत नाही. + * - कॉलरकडे किमान `amount` इतकी शिल्लक असणे आवश्यक आहे. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { +``` + +`transfer` फंक्शन प्रेषकाच्या खात्यातून दुसऱ्या खात्यात टोकन हस्तांतरित करण्यासाठी कॉल केले जाते. लक्षात +घ्या की ते बुलियन मूल्य परत करत असले तरी, ते मूल्य नेहमी **सत्य** असते. जर हस्तांतरण +अयशस्वी झाले तर कॉन्ट्रॅक्ट कॉलला रिव्हर्ट करते. + +  + +```solidity + _transfer(_msgSender(), recipient, amount); + return true; + } +``` + +`_transfer` फंक्शन वास्तविक काम करते. हे एक खाजगी फंक्शन आहे जे केवळ +इतर कॉन्ट्रॅक्ट फंक्शन्सद्वारे कॉल केले जाऊ शकते. परंपरेनुसार खाजगी फंक्शन्सना `_` असे नाव दिले जाते, जसे की स्टेट +व्हेरिएबल्स. + +सामान्यतः Solidity मध्ये आपण संदेश प्रेषकासाठी `msg.sender` वापरतो. तथापि, ते +[OpenGSN](http://opengsn.org/) तोडते. आपल्याला आपल्या टोकनसह इथरलेस व्यवहारांना परवानगी द्यायची असल्यास, आपल्याला +`_msgSender()` वापरण्याची आवश्यकता आहे. ते सामान्य व्यवहारांसाठी `msg.sender` परत करते, परंतु इथरलेस व्यवहारांसाठी +मूळ स्वाक्षरीकर्ता परत करते आणि संदेश रिले करणाऱ्या कॉन्ट्रॅक्टला नाही. + +### अलाउन्स फंक्शन्स {#allowance-functions} + +ही फंक्शन्स आहेत जी अलाउन्स कार्यक्षमता लागू करतात: `allowance`, `approve`, `transferFrom`, +आणि `_approve`. याव्यतिरिक्त, OpenZeppelin अंमलबजावणी मूलभूत मानकांच्या पलीकडे जाऊन सुरक्षा सुधारणारी काही वैशिष्ट्ये समाविष्ट करते: `increaseAllowance` आणि `decreaseAllowance`. + +#### अलाउन्स फंक्शन {#allowance} + +```solidity + /** + * @dev {IERC20-allowance} पहा. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } +``` + +`allowance` फंक्शन प्रत्येकाला कोणताही अलाउन्स तपासण्याची परवानगी देते. + +#### अप्रूव्ह फंक्शन {#approve} + +```solidity + /** + * @dev {IERC20-approve} पहा. + * + * आवश्यकता: + * + * - `spender` शून्य पत्ता असू शकत नाही. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { +``` + +हे फंक्शन अलाउन्स तयार करण्यासाठी कॉल केले जाते. हे वरील `transfer` फंक्शनसारखे आहे: + +- हे फंक्शन फक्त एका अंतर्गत फंक्शनला (या प्रकरणात, `_approve`) कॉल करते जे वास्तविक काम करते. +- हे फंक्शन एकतर `true` (यशस्वी झाल्यास) परत करते किंवा रिव्हर्ट होते (नसल्यास). + +  + +```solidity + _approve(_msgSender(), spender, amount); + return true; + } +``` + +स्टेट बदल होणाऱ्या ठिकाणांची संख्या कमी करण्यासाठी आम्ही अंतर्गत फंक्शन्स वापरतो. स्टेट बदलणारे _कोणतेही_ फंक्शन +एक संभाव्य सुरक्षा धोका आहे ज्याचे सुरक्षेसाठी ऑडिट करणे आवश्यक आहे. यामुळे आम्हाला चूक होण्याची शक्यता कमी होते. + +#### transferFrom फंक्शन {#transferFrom} + +हे फंक्शन आहे जे एक स्पेंडर अलाउन्स खर्च करण्यासाठी कॉल करतो. यासाठी दोन क्रिया आवश्यक आहेत: खर्च केलेली रक्कम +हस्तांतरित करणे आणि त्या रकमेने अलाउन्स कमी करणे. + +```solidity + /** + * @dev {IERC20-transferFrom} पहा. + * + * अद्यतनित अलाउन्स दर्शवणारा एक {Approval} इव्हेंट उत्सर्जित करते. हे + * EIP द्वारे आवश्यक नाही. {ERC20} च्या सुरुवातीला टीप पहा. + * + * आवश्यकता: + * + * - `sender` आणि `recipient` शून्य पत्ता असू शकत नाहीत. + * - `sender` कडे किमान `amount` इतकी शिल्लक असणे आवश्यक आहे. + * - कॉलरकडे किमान + * `amount` च्या ``sender``'च्या टोकनसाठी अलाउन्स असणे आवश्यक आहे. + */ + function transferFrom(address sender, address recipient, uint256 amount) public virtual + override returns (bool) { + _transfer(sender, recipient, amount); +``` + +  + +`a.sub(b, "message")` फंक्शन कॉल दोन गोष्टी करतो. प्रथम, ते `a-b` ची गणना करते, जो नवीन अलाउन्स आहे. +दुसरे, ते तपासते की हा परिणाम नकारात्मक नाही. जर तो नकारात्मक असेल तर कॉल प्रदान केलेल्या संदेशासह रिव्हर्ट होतो. लक्षात घ्या की जेव्हा एखादा कॉल रिव्हर्ट होतो तेव्हा त्या कॉलदरम्यान पूर्वी केलेले कोणतेही प्रक्रिया दुर्लक्षित केले जाते त्यामुळे आम्हाला `_transfer` +पूर्ववत करण्याची आवश्यकता नाही. + +```solidity + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, + "ERC20: transfer amount exceeds allowance")); + return true; + } +``` + +#### OpenZeppelin सुरक्षा जोडणी {#openzeppelin-safety-additions} + +शून्य-नसलेला अलाउन्स दुसऱ्या शून्य-नसलेल्या मूल्यावर सेट करणे धोकादायक आहे, +कारण तुम्ही फक्त तुमच्या स्वतःच्या व्यवहारांच्या क्रमावर नियंत्रण ठेवता, इतर कोणाच्याही नाही. कल्पना करा की तुमच्याकडे +दोन वापरकर्ते आहेत, एलिस जी भोळी आहे आणि बिल जो अप्रामाणिक आहे. एलिसला बिलकडून काही सेवा हवी आहे, जी तिला वाटते की पाच टोकन खर्च करते - म्हणून ती बिलला पाच टोकनचा अलाउन्स देते. + +नंतर काहीतरी बदलते आणि बिलची किंमत दहा टोकनपर्यंत वाढते. एलिस, जिला अजूनही सेवा हवी आहे, +एक व्यवहार पाठवते जो बिलचा अलाउन्स दहावर सेट करतो. ज्या क्षणी बिलला हा नवीन व्यवहार +व्यवहार पूलमध्‍ये दिसतो, तो एलिसचे पाच टोकन खर्च करणारा एक व्यवहार पाठवतो आणि त्याची गॅस किंमत खूप जास्त असते जेणेकरून तो जलद माइन होईल. अशाप्रकारे बिल प्रथम पाच टोकन खर्च करू शकतो आणि नंतर, एकदा एलिसचा नवीन अलाउन्स माइन झाल्यावर, पंधरा टोकनच्या एकूण किंमतीसाठी आणखी दहा खर्च करू शकतो, जे एलिसने +अधिकृत करू इच्छिलेल्या रकमेपेक्षा जास्त आहे. या तंत्राला +[फ्रंट-रनिंग](https://consensysdiligence.github.io/smart-contract-best-practices/attacks/#front-running) म्हणतात + +| एलिस व्यवहार | एलिस नॉन्स | बिल व्यवहार | बिल नॉन्स | बिलचा अलाउन्स | एलिसकडून बिलचे एकूण उत्पन्न | +| ------------------------------------ | ---------- | ------------------------------------------------ | --------- | ------------- | --------------------------- | +| approve(Bill, 5) | 10 | | | 5 | 0 | +| | | transferFrom(Alice, Bill, 5) | 10,123 | 0 | 5 | +| approve(Bill, 10) | 11 | | | 10 | 5 | +| | | transferFrom(Alice, Bill, 10) | 10,124 | 0 | 15 | + +ही समस्या टाळण्यासाठी, ही दोन फंक्शन्स (`increaseAllowance` आणि `decreaseAllowance`) तुम्हाला +एका विशिष्ट रकमेने अलाउन्समध्ये बदल करण्याची परवानगी देतात. त्यामुळे जर बिलने आधीच पाच टोकन खर्च केले असतील, तर तो फक्त +आणखी पाच खर्च करू शकेल. वेळेनुसार, हे काम करण्याचे दोन मार्ग आहेत, जे दोन्ही +बिलला फक्त दहा टोकन मिळवून संपतात: + +अ: + +| एलिस व्यवहार | एलिस नॉन्स | बिल व्यवहार | बिल नॉन्स | बिलचा अलाउन्स | एलिसकडून बिलचे एकूण उत्पन्न | +| --------------------------------------------- | ---------: | ----------------------------------------------- | --------: | ------------: | --------------------------- | +| approve(Bill, 5) | 10 | | | 5 | 0 | +| | | transferFrom(Alice, Bill, 5) | 10,123 | 0 | 5 | +| increaseAllowance(Bill, 5) | 11 | | | 0+5 = 5 | 5 | +| | | transferFrom(Alice, Bill, 5) | 10,124 | 0 | 10 | + +ब: + +| एलिस व्यवहार | एलिस नॉन्स | बिल व्यवहार | बिल नॉन्स | बिलचा अलाउन्स | एलिसकडून बिलचे एकूण उत्पन्न | +| --------------------------------------------- | ---------: | ------------------------------------------------ | --------: | ------------: | --------------------------: | +| approve(Bill, 5) | 10 | | | 5 | 0 | +| increaseAllowance(Bill, 5) | 11 | | | 5+5 = 10 | 0 | +| | | transferFrom(Alice, Bill, 10) | 10,124 | 0 | 10 | + +```solidity + /** + * @dev कॉलरद्वारे `spender` ला दिलेला अलाउन्स अणुप्रायपणे वाढवते. + * + * हा {approve} चा एक पर्याय आहे जो {IERC20-approve} मध्ये वर्णन केलेल्या समस्यांसाठी + * एक कमी करण्याच्या उपायांप्रमाणे वापरला जाऊ शकतो. + * + * अद्यतनित अलाउन्स दर्शवणारा एक {Approval} इव्हेंट उत्सर्जित करते. + * + * आवश्यकता: + * + * - `spender` शून्य पत्ता असू शकत नाही. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); + return true; + } +``` + +`a.add(b)` फंक्शन एक सुरक्षित बेरीज आहे. असंभाव्य परिस्थितीत की `a`+`b`>=`2^256` असेल तर ते सामान्य बेरीजप्रमाणे +रॅप अराउंड होत नाही. + +```solidity + + /** + * @dev कॉलरद्वारे `spender` ला दिलेला अलाउन्स अणुप्रायपणे कमी करते. + * + * हा {approve} चा एक पर्याय आहे जो {IERC20-approve} मध्ये वर्णन केलेल्या समस्यांसाठी + * एक कमी करण्याच्या उपायांप्रमाणे वापरला जाऊ शकतो. + * + * अद्यतनित अलाउन्स दर्शवणारा एक {Approval} इव्हेंट उत्सर्जित करते. + * + * आवश्यकता: + * + * - `spender` शून्य पत्ता असू शकत नाही. + * - `spender` कडे किमान `subtractedValue` + * इतका कॉलरसाठी अलाउन्स असणे आवश्यक आहे. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, + "ERC20: decreased allowance below zero")); + return true; + } +``` + +### टोकन माहितीमध्ये बदल करणारी फंक्शन्स {#functions-that-modify-token-information} + +ही चार फंक्शन्स आहेत जी वास्तविक काम करतात: `_transfer`, `_mint`, `_burn`, आणि `_approve`. + +#### _transfer फंक्शन {#_transfer} + +```solidity + /** + * @dev `sender` कडून `recipient` कडे `amount` टोकन हलवते. + * + * हे अंतर्गत फंक्शन {transfer} च्या समकक्ष आहे, आणि उदाहरणार्थ, स्वयंचलित टोकन शुल्क, स्लॅशिंग यंत्रणा, इत्यादी लागू करण्यासाठी वापरले जाऊ शकते. + * + * एक {Transfer} इव्हेंट उत्सर्जित करते. + * + * आवश्यकता: + * + * - `sender` शून्य पत्ता असू शकत नाही. + * - `recipient` शून्य पत्ता असू शकत नाही. + * - `sender` कडे किमान `amount` इतकी शिल्लक असणे आवश्यक आहे. + */ + function _transfer(address sender, address recipient, uint256 amount) internal virtual { +``` + +हे फंक्शन, `_transfer`, एका खात्यातून दुसऱ्या खात्यात टोकन हस्तांतरित करते. ते `transfer` (प्रेषकाच्या स्वतःच्या खात्यातून हस्तांतरणासाठी) आणि `transferFrom` (दुसऱ्याच्या खात्यातून +हस्तांतरणासाठी अलाउन्स वापरण्यासाठी) दोन्हीद्वारे कॉल केले जाते. + +  + +```solidity + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); +``` + +Ethereum मध्ये शून्य पत्त्याची मालकी कोणाकडेही नाही (म्हणजेच, कोणालाही अशी खाजगी की माहित नाही जिची जुळणारी सार्वजनिक की +शून्य पत्त्यात रूपांतरित होते). जेव्हा लोक तो पत्ता वापरतात, तेव्हा ती सहसा एक सॉफ्टवेअर बग असते - म्हणून आम्ही +शून्य पत्ता प्रेषक किंवा प्राप्तकर्ता म्हणून वापरल्यास अयशस्वी होतो. + +  + +```solidity + _beforeTokenTransfer(sender, recipient, amount); + +``` + +हा कॉन्ट्रॅक्ट वापरण्याचे दोन मार्ग आहेत: + +1. तुमच्या स्वतःच्या कोडसाठी टेम्पलेट म्हणून वापरा +2. [त्यातून इनहेरिट करा](https://www.bitdegree.org/learn/solidity-inheritance), आणि फक्त त्या फंक्शन्सना ओव्हरराइड करा ज्यात तुम्हाला बदल करायचा आहे + +दुसरी पद्धत खूपच चांगली आहे कारण OpenZeppelin ERC-20 कोडचे आधीच ऑडिट केले गेले आहे आणि ते सुरक्षित असल्याचे दर्शविले आहे. जेव्हा तुम्ही इनहेरिटन्स +वापरता तेव्हा तुम्ही कोणत्या फंक्शन्समध्ये बदल करता हे स्पष्ट होते, आणि तुमच्या कॉन्ट्रॅक्टवर विश्वास ठेवण्यासाठी लोकांना फक्त त्या विशिष्ट फंक्शन्सचे ऑडिट करण्याची आवश्यकता असते. + +जेव्हा जेव्हा टोकनची देवाणघेवाण होते तेव्हा प्रत्येक वेळी एक फंक्शन करणे अनेकदा उपयुक्त ठरते. तथापि, `_transfer` हे एक अत्यंत महत्त्वाचे फंक्शन आहे आणि ते +असुरक्षितपणे लिहिणे शक्य आहे (खाली पहा), म्हणून ते ओव्हरराइड न करणे सर्वोत्तम आहे. यावर उपाय म्हणजे `_beforeTokenTransfer`, एक +[हुक फंक्शन](https://wikipedia.org/wiki/Hooking). तुम्ही हे फंक्शन ओव्हरराइड करू शकता, आणि ते प्रत्येक हस्तांतरणावर कॉल केले जाईल. + +  + +```solidity + _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); + _balances[recipient] = _balances[recipient].add(amount); +``` + +या ओळी आहेत ज्या प्रत्यक्षात हस्तांतरण करतात. लक्षात घ्या की त्यांच्यामध्ये **काहीही नाही**, आणि आम्ही +हस्तांतरित रक्कम प्राप्तकर्त्याला जोडण्यापूर्वी प्रेषकाकडून वजा करतो. हे महत्त्वाचे आहे कारण जर मध्ये दुसऱ्या कॉन्ट्रॅक्टला कॉल +असता, तर त्याचा वापर या कॉन्ट्रॅक्टला फसवण्यासाठी केला गेला असता. अशा प्रकारे हस्तांतरण +अणुप्राय (atomic) आहे, त्याच्यामध्ये काहीही होऊ शकत नाही. + +  + +```solidity + emit Transfer(sender, recipient, amount); + } +``` + +शेवटी, एक `Transfer` इव्हेंट उत्सर्जित करा. इव्हेंट्स स्मार्ट कॉन्ट्रॅक्ट्सना ऍक्सेस करता येत नाहीत, परंतु ब्लॉकचेनच्या +बाहेर चालणारा कोड इव्हेंट्स ऐकू शकतो आणि त्यावर प्रतिक्रिया देऊ शकतो. उदाहरणार्थ, वॉलेट मालकाला अधिक टोकन कधी मिळतात याचा मागोवा ठेवू शकते. + +#### _mint आणि _burn फंक्शन्स {#_mint-and-_burn} + +ही दोन फंक्शन्स (`_mint` आणि `_burn`) टोकनच्या एकूण पुरवठ्यात बदल करतात. +ती इंटरनल आहेत आणि या कॉन्ट्रॅक्टमध्ये त्यांना कॉल करणारे कोणतेही फंक्शन नाही, +त्यामुळे तुम्ही कॉन्ट्रॅक्टमधून इनहेरिट केल्यास आणि नवीन टोकन कोणत्या परिस्थितीत मिंट करायचे किंवा +अस्तित्वात असलेले बर्न करायचे हे ठरवण्यासाठी तुमचा स्वतःचा +लॉजिक जोडल्यासच ते उपयुक्त आहेत. + +**टीप:** प्रत्येक ERC-20 टोकनचा स्वतःचा व्यवसाय लॉजिक असतो जो टोकन व्यवस्थापन ठरवतो. +उदाहरणार्थ, एक निश्चित पुरवठा कॉन्ट्रॅक्ट कदाचित फक्त कन्स्ट्रक्टरमध्ये `_mint` ला कॉल करेल आणि `_burn` ला कधीही कॉल करणार नाही. टोकन विकणारा कॉन्ट्रॅक्ट +पैसे भरल्यावर `_mint` ला कॉल करेल, आणि संभाव्यतः अनियंत्रित चलनवाढ टाळण्यासाठी काही टप्प्यावर `_burn` ला कॉल करेल. + +```solidity + /** @dev `amount` टोकन तयार करते आणि ते `account` ला नियुक्त करते, ज्यामुळे + * एकूण पुरवठा वाढतो. + * + * `from` शून्य पत्त्यावर सेट करून एक {Transfer} इव्हेंट उत्सर्जित करते. + * + * आवश्यकता: + * + * - `to` शून्य पत्ता असू शकत नाही. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + _beforeTokenTransfer(address(0), account, amount); + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } +``` + +जेव्हा टोकनची एकूण संख्या बदलते तेव्हा `_totalSupply` अद्यतनित करण्याची खात्री करा. + +  + +```solidity + /** + * @dev `account` मधून `amount` टोकन नष्ट करते, ज्यामुळे + * एकूण पुरवठा कमी होतो. + * + * `to` शून्य पत्त्यावर सेट करून एक {Transfer} इव्हेंट उत्सर्जित करते. + * + * आवश्यकता: + * + * - `account` शून्य पत्ता असू शकत नाही. + * - `account` कडे किमान `amount` टोकन असणे आवश्यक आहे. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); + } +``` + +`_burn` फंक्शन जवळजवळ `_mint` सारखेच आहे, फक्त ते उलट दिशेने जाते. + +#### _approve फंक्शन {#_approve} + +हे फंक्शन आहे जे प्रत्यक्षात अलाउन्स निर्दिष्ट करते. लक्षात घ्या की ते एका मालकाला +मालकाच्या वर्तमान शिलकेपेक्षा जास्त असलेला अलाउन्स निर्दिष्ट करण्याची परवानगी देते. हे ठीक आहे कारण शिल्लक +हस्तांतरणाच्या वेळी तपासली जाते, जेव्हा ती अलाउन्स तयार केल्यावरच्या शिलकेपेक्षा वेगळी असू शकते. + +```solidity + /** + * @dev `owner` च्या टोकनवर `spender` चा अलाउन्स म्हणून `amount` सेट करते. + * + * हे अंतर्गत फंक्शन `approve` च्या समकक्ष आहे, आणि उदाहरणार्थ, विशिष्ट सबसिस्टमसाठी स्वयंचलित अलाउन्स सेट करण्यासाठी वापरले जाऊ शकते. + * + * एक {Approval} इव्हेंट उत्सर्जित करते. + * + * आवश्यकता: + * + * - `owner` शून्य पत्ता असू शकत नाही. + * - `spender` शून्य पत्ता असू शकत नाही. + */ + function _approve(address owner, address spender, uint256 amount) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; +``` + +  + +एक `Approval` इव्हेंट उत्सर्जित करा. ॲप्लिकेशन कसे लिहिले आहे यावर अवलंबून, स्पेंडर कॉन्ट्रॅक्टला +अप्रूव्हलबद्दल मालकाद्वारे किंवा हे इव्हेंट्स ऐकणाऱ्या सर्व्हरद्वारे सांगितले जाऊ शकते. + +```solidity + emit Approval(owner, spender, amount); + } + +``` + +### दशांश व्हेरिएबलमध्ये बदल करा {#modify-the-decimals-variable} + +```solidity + + + /** + * @dev {decimals} ला 18 च्या डीफॉल्ट मूल्याव्यतिरिक्त दुसऱ्या मूल्यावर सेट करते. + * + * चेतावणी: हे फंक्शन केवळ कन्स्ट्रक्टरमधून कॉल केले पाहिजे. टोकन + * कॉन्ट्रॅक्टशी संवाद साधणारे बहुतेक ॲप्लिकेशन्स {decimals} कधीही बदलतील अशी + * अपेक्षा करणार नाहीत, आणि जर बदलले तर ते चुकीच्या पद्धतीने काम करू शकतात. + */ + function _setupDecimals(uint8 decimals_) internal { + _decimals = decimals_; + } +``` + +हे फंक्शन `_decimals` व्हेरिएबलमध्ये बदल करते जे वापरकर्ता इंटरफेसना रक्कम कशी इंटरप्रेट करायची हे सांगण्यासाठी वापरले जाते. +तुम्ही ते कन्स्ट्रक्टरमधून कॉल केले पाहिजे. त्यानंतरच्या कोणत्याही टप्प्यावर ते कॉल करणे अप्रामाणिक ठरेल, आणि ॲप्लिकेशन्स +ते हाताळण्यासाठी डिझाइन केलेले नाहीत. + +### हुक्स {#hooks} + +```solidity + + /** + * @dev टोकनच्या कोणत्याही हस्तांतरणापूर्वी कॉल केला जाणारा हुक. यामध्ये + * मिंटिंग आणि बर्निंगचा समावेश आहे. + * + * कॉलिंग अटी: + * + * - जेव्हा `from` आणि `to` दोन्ही शून्य-नसलेले असतात, तेव्हा ``from`` च्या टोकनची `amount` + * `to` ला हस्तांतरित केली जाईल. + * - जेव्हा `from` शून्य असेल, तेव्हा `to` साठी `amount` टोकन मिंट केले जातील. + * - जेव्हा `to` शून्य असेल, तेव्हा ``from`` च्या टोकनची `amount` बर्न केली जाईल. + * - `from` आणि `to` दोन्ही कधीही शून्य नसतात. + * + * हुकबद्दल अधिक जाणून घेण्यासाठी, xref:ROOT:extending-contracts.adoc#using-hooks[हुक वापरणे] येथे जा. + */ + function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } +} +``` + +हे हस्तांतरणादरम्यान कॉल केले जाणारे हुक फंक्शन आहे. हे येथे रिकामे आहे, परंतु तुम्हाला +त्याला काहीतरी करायला लावायचे असल्यास तुम्ही फक्त ते ओव्हरराइड करा. + +## निष्कर्ष {#conclusion} + +पुनरावलोकनासाठी, या कॉन्ट्रॅक्टमधील काही सर्वात महत्त्वाच्या कल्पना येथे आहेत (माझ्या मते, तुमची मते भिन्न असू शकतात): + +- _ब्लॉकचेनवर कोणतीही गुपिते नाहीत_. स्मार्ट कॉन्ट्रॅक्ट ऍक्सेस करू शकणारी कोणतीही माहिती + संपूर्ण जगासाठी उपलब्ध आहे. +- तुम्ही तुमच्या स्वतःच्या व्यवहारांच्या क्रमावर नियंत्रण ठेवू शकता, परंतु इतर लोकांचे व्यवहार + कधी होतात यावर नाही. हेच कारण आहे की अलाउन्स बदलणे धोकादायक असू शकते, कारण ते + स्पेंडरला दोन्ही अलाउन्सची बेरीज खर्च करू देते. +- `uint256` प्रकाराची मूल्ये रॅप अराउंड होतात. दुसऱ्या शब्दांत, _0-1=2^256-1_. जर ते इच्छित + वर्तन नसेल, तर तुम्हाला ते तपासावे लागेल (किंवा SafeMath लायब्ररी वापरा जी तुमच्यासाठी ते करते). लक्षात घ्या की हे + [Solidity 0.8.0](https://docs.soliditylang.org/en/breaking/080-breaking-changes.html) मध्ये बदलले आहे. +- एका विशिष्ट प्रकारातील सर्व स्टेट बदल एका विशिष्ट ठिकाणी करा, कारण यामुळे ऑडिटिंग सोपे होते. + हेच कारण आहे की आमच्याकडे, उदाहरणार्थ, `_approve` आहे, जे `approve`, `transferFrom`, + `increaseAllowance`, आणि `decreaseAllowance` द्वारे कॉल केले जाते +- स्टेट बदल अणुप्राय (atomic) असावेत, त्यांच्यामध्ये इतर कोणतीही क्रिया नसावी (जसे तुम्ही + `_transfer` मध्ये पाहू शकता). याचे कारण असे की स्टेट बदलादरम्यान तुमच्याकडे एक विसंगत स्टेट असते. उदाहरणार्थ, + तुम्ही प्रेषकाच्या शिलकीतून वजा करता आणि प्राप्तकर्त्याच्या शिलकीत जोडता या वेळेदरम्यान अस्तित्त्वात + असलेले टोकन आवश्यकतेपेक्षा कमी असतात. जर त्यांच्यामध्ये + ऑपरेशन्स असतील तर याचा संभाव्य गैरवापर होऊ शकतो, विशेषतः वेगळ्या कॉन्ट्रॅक्टला केलेले कॉल. + +आता तुम्ही पाहिले आहे की OpenZeppelin ERC-20 कॉन्ट्रॅक्ट कसे लिहिले आहे, आणि विशेषतः ते कसे अधिक +सुरक्षित बनवले आहे, आता जा आणि तुमचे स्वतःचे सुरक्षित कॉन्ट्रॅक्ट आणि ॲप्लिकेशन्स लिहा. + +[माझ्या कामाबद्दल अधिक माहितीसाठी येथे पहा](https://cryptodocguy.pro/). diff --git a/public/content/translations/mr/developers/tutorials/erc20-with-safety-rails/index.md b/public/content/translations/mr/developers/tutorials/erc20-with-safety-rails/index.md new file mode 100644 index 00000000000..467daa6b667 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/erc20-with-safety-rails/index.md @@ -0,0 +1,217 @@ +--- +title: "ERC-20 सुरक्षा रेल्ससह" +description: "लोकांना मूर्ख चुका टाळण्यास कशी मदत करावी" +author: Ori Pomerantz +lang: mr +tags: [ "erc-20" ] +skill: beginner +published: 2022-08-15 +--- + +## प्रस्तावना {#introduction} + +Ethereum बद्दल एक मोठी चांगली गोष्ट म्हणजे अशी कोणतीही केंद्रीय सत्ता नाही जी तुमचे व्यवहार बदलू किंवा पूर्ववत करू शकेल. Ethereum मधील एक मोठी समस्या अशी आहे की वापरकर्त्याच्या चुका किंवा अवैध व्यवहार पूर्ववत करण्याची शक्ती असलेली कोणतीही केंद्रीय सत्ता नाही. या लेखात तुम्ही [ERC-20](/developers/docs/standards/tokens/erc-20/) टोकन्ससह वापरकर्ते करत असलेल्या काही सामान्य चुकांबद्दल शिकाल, तसेच अशा ERC-20 कॉन्ट्रॅक्ट्स कसे तयार करावे जे वापरकर्त्यांना त्या चुका टाळण्यास मदत करतात, किंवा जे केंद्रीय सत्तेला काही अधिकार देतात (उदाहरणार्थ, खाती फ्रीझ करणे). + +लक्षात घ्या की आम्ही [OpenZeppelin ERC-20 टोकन कॉन्ट्रॅक्ट](https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/token/ERC20) वापरणार असलो तरी, हा लेख त्याचे तपशीलवार स्पष्टीकरण देत नाही. तुम्ही ही माहिती [येथे](/developers/tutorials/erc20-annotated-code) शोधू शकता. + +तुम्हाला संपूर्ण सोर्स कोड पहायचा असल्यास: + +1. [Remix IDE](https://remix.ethereum.org/) उघडा. +2. क्लोन गिटहब आयकॉनवर क्लिक करा (![clone github icon](icon-clone.png)). +3. गिटहब रिपॉझिटरी `https://github.com/qbzzt/20220815-erc20-safety-rails` क्लोन करा. +4. **contracts > erc20-safety-rails.sol** उघडा. + +## ERC-20 कॉन्ट्रॅक्ट तयार करणे {#creating-an-erc-20-contract} + +आपण सुरक्षा रेलची कार्यक्षमता जोडण्यापूर्वी, आपल्याला एका ERC-20 कॉन्ट्रॅक्टची आवश्यकता आहे. या लेखात आम्ही [OpenZeppelin Contracts Wizard](https://docs.openzeppelin.com/contracts/5.x/wizard) वापरणार आहोत. ते दुसऱ्या ब्राउझरमध्ये उघडा आणि या सूचनांचे पालन करा: + +1. **ERC20** निवडा. + +2. या सेटिंग्ज प्रविष्ट करा: + + | पॅरामीटर | मूल्य | + | -------------- | ----------------------------------------------------------------------------------- | + | नाव | SafetyRailsToken | + | चिन्ह | SAFE | + | Premint | आम्हाला प्रति टोकन जोडीसाठी एकापेक्षा जास्त लिक्विडिटी पूल नको आहे. | + | वैशिष्ट्ये | काहीही नाही | + | ॲक्सेस कंट्रोल | Ownable | + | अपग्रेडेबिलिटी | काहीही नाही | + +3. वर स्क्रोल करा आणि भिन्न पर्यावरण वापरण्यासाठी **Open in Remix** (Remix साठी) किंवा **Download** वर क्लिक करा. मी असे गृहीत धरतो की तुम्ही Remix वापरत आहात, तुम्ही दुसरे काही वापरल्यास, योग्य बदल करा. + +4. आमच्याकडे आता पूर्णपणे कार्यरत ERC-20 कॉन्ट्रॅक्ट आहे. इम्पोर्ट केलेला कोड पाहण्यासाठी तुम्ही `.deps` > `npm` चा विस्तार करू शकता. + +5. ते ERC-20 कॉन्ट्रॅक्ट म्हणून कार्य करते हे पाहण्यासाठी कॉन्ट्रॅक्ट कंपाईल करा, उपयोजित करा आणि त्याच्याशी खेळा. तुम्हाला Remix कसे वापरावे हे शिकायचे असल्यास, [हे ट्यूटोरियल वापरा](https://remix.ethereum.org/?#activate=udapp,solidity,LearnEth). + +## सामान्य चुका {#common-mistakes} + +### चुका {#the-mistakes} + +वापरकर्ते कधीकधी चुकीच्या पत्त्यावर टोकन पाठवतात. त्यांना काय करायचे होते हे जाणून घेण्यासाठी आम्ही त्यांचे मन वाचू शकत नसलो तरी, दोन प्रकारच्या त्रुटी आहेत ज्या खूप वेळा घडतात आणि ओळखण्यास सोप्या आहेत: + +1. टोकन कॉन्ट्रॅक्टच्या स्वतःच्या पत्त्यावर पाठवणे. उदाहरणार्थ, [Optimism's OP token](https://optimism.mirror.xyz/qvd0WfuLKnePm1Gxb9dpGchPf5uDz5NSMEFdgirDS4c) ने दोन महिन्यांपेक्षा कमी कालावधीत [120,000 पेक्षा जास्त](https://optimism.blockscout.com/address/0x4200000000000000000000000000000000000042) OP टोकन जमा केले. हे मोठ्या प्रमाणात संपत्ती दर्शवते जी लोकांनी कदाचित गमावली आहे. + +2. टोकन रिकाम्या पत्त्यावर पाठवणे, जो [बाह्य मालकीच्या खात्याशी](/developers/docs/accounts/#externally-owned-accounts-and-key-pairs) किंवा [स्मार्ट कॉन्ट्रॅक्टशी](/developers/docs/smart-contracts) संबंधित नाही. हे किती वेळा घडते याची माझ्याकडे आकडेवारी नसली तरी, [एका घटनेत 20,000,000 टोकन खर्च होऊ शकले असते](https://gov.optimism.io/t/message-to-optimism-community-from-wintermute/2595). + +### हस्तांतरण प्रतिबंधित करणे {#preventing-transfers} + +OpenZeppelin ERC-20 कॉन्ट्रॅक्टमध्ये [एक हुक, `_beforeTokenTransfer`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol#L364-L368) समाविष्ट आहे, जो टोकन हस्तांतरित होण्यापूर्वी कॉल केला जातो. डीफॉल्टनुसार हा हुक काहीही करत नाही, परंतु आम्ही त्यावर आमची स्वतःची कार्यक्षमता टांगू शकतो, जसे की समस्या असल्यास उलटणारे तपास. + +हुक वापरण्यासाठी, कन्स्ट्रक्टरनंतर हे फंक्शन जोडा: + +```solidity + function _beforeTokenTransfer(address from, address to, uint256 amount) + internal virtual + override(ERC20) + { + super._beforeTokenTransfer(from, to, amount); + } +``` + +जर तुम्ही Solidity शी फारसे परिचित नसाल तर या फंक्शनचे काही भाग नवीन असू शकतात: + +```solidity + internal virtual +``` + +`virtual` कीवर्डचा अर्थ असा आहे की जसे आम्ही `ERC20` कडून कार्यक्षमता मिळवली आणि हे फंक्शन ओव्हरराइड केले, त्याचप्रमाणे इतर कॉन्ट्रॅक्ट्स आमच्याकडून वारसा घेऊ शकतात आणि हे फंक्शन ओव्हरराइड करू शकतात. + +```solidity + override(ERC20) +``` + +आम्हाला स्पष्टपणे नमूद करावे लागेल की आम्ही `_beforeTokenTransfer` ची ERC20 टोकन व्याख्या [ओव्हरराइड](https://docs.soliditylang.org/en/v0.8.15/contracts.html#function-overriding) करत आहोत. सर्वसाधारणपणे, सुरक्षिततेच्या दृष्टिकोनातून, स्पष्ट व्याख्या अंतर्निहित व्याख्यांपेक्षा खूपच चांगल्या आहेत - तुम्ही तुमच्या समोर काहीतरी केले असल्यास ते विसरू शकत नाही. हेच कारण आहे की आम्हाला कोणत्या सुपरक्लासचा `_beforeTokenTransfer` ओव्हरराइड करत आहोत हे निर्दिष्ट करणे आवश्यक आहे. + +```solidity + super._beforeTokenTransfer(from, to, amount); +``` + +ही ओळ कॉन्ट्रॅक्ट किंवा कॉन्ट्रॅक्ट्सच्या `_beforeTokenTransfer` फंक्शनला कॉल करते ज्यांच्याकडून आम्ही वारसा घेतला आहे. या प्रकरणात, ते फक्त `ERC20` आहे, `Ownable` कडे हा हुक नाही. सध्या `ERC20._beforeTokenTransfer` काहीही करत नसले तरी, भविष्यात कार्यक्षमता जोडल्यास आम्ही ते कॉल करतो (आणि मग आम्ही कॉन्ट्रॅक्ट पुन्हा तैनात करण्याचा निर्णय घेतो, कारण उपयोजनानंतर कॉन्ट्रॅक्ट बदलत नाहीत). + +### आवश्यकतांचे कोडिंग करणे {#coding-the-requirements} + +आम्ही फंक्शनमध्ये या आवश्यकता जोडू इच्छितो: + +- `to` पत्ता `address(this)` च्या बरोबर असू शकत नाही, जो ERC-20 कॉन्ट्रॅक्टचा स्वतःचा पत्ता आहे. +- `to` पत्ता रिकामा असू शकत नाही, तो यापैकी एक असावा: + - बाह्य मालकीचे खाते (EOA). एखादा पत्ता थेट EOA आहे की नाही हे आम्ही तपासू शकत नाही, परंतु आम्ही पत्त्याची ETH शिल्लक तपासू शकतो. EOAs मध्ये जवळजवळ नेहमीच शिल्लक असते, जरी ते आता वापरले जात नसले तरीही - शेवटच्या wei पर्यंत ते साफ करणे कठीण आहे. + - एक स्मार्ट कॉन्ट्रॅक्ट. एखादा पत्ता स्मार्ट कॉन्ट्रॅक्ट आहे की नाही हे तपासणे थोडे कठीण आहे. बाह्य कोडची लांबी तपासणारा एक ऑपकोड आहे, ज्याला [`EXTCODESIZE`](https://www.evm.codes/#3b) म्हणतात, परंतु तो थेट Solidity मध्ये उपलब्ध नाही. त्यासाठी आम्हाला [Yul](https://docs.soliditylang.org/en/v0.8.15/yul.html) वापरावे लागेल, जे EVM असेंब्ली आहे. Solidity मधून आम्ही वापरू शकणारी इतर मूल्ये आहेत ([`
.code` आणि `
.codehash`](https://docs.soliditylang.org/en/v0.8.15/units-and-global-variables.html#members-of-address-types)), पण ती अधिक महाग आहेत. + +चला नवीन कोड ओळीने ओळ पाहूया: + +```solidity + require(to != address(this), "कॉन्ट्रॅक्ट पत्त्यावर टोकन पाठवू शकत नाही"); +``` + +ही पहिली आवश्यकता आहे, `to` आणि `this(address)` समान नाहीत हे तपासा. + +```solidity + bool isToContract; + assembly { + isToContract := gt(extcodesize(to), 0) + } +``` + +अशा प्रकारे आम्ही पत्ता कॉन्ट्रॅक्ट आहे की नाही हे तपासतो. आम्ही Yul कडून थेट आउटपुट प्राप्त करू शकत नाही, म्हणून त्याऐवजी आम्ही परिणाम ठेवण्यासाठी एक व्हेरिएबल परिभाषित करतो (या प्रकरणात `isToContract`). Yul ज्या प्रकारे कार्य करते ते असे आहे की प्रत्येक ऑपकोड एक फंक्शन मानला जातो. म्हणून प्रथम आम्ही कॉन्ट्रॅक्टचा आकार मिळविण्यासाठी [`EXTCODESIZE`](https://www.evm.codes/#3b) कॉल करतो आणि नंतर ते शून्य नाही हे तपासण्यासाठी [`GT`](https://www.evm.codes/#11) वापरतो (आम्ही अनसाईंड इंटीजर्ससह काम करत आहोत, म्हणून अर्थातच ते नकारात्मक असू शकत नाही). त्यानंतर आम्ही निकाल `isToContract` मध्ये लिहितो. + +```solidity + require(to.balance != 0 || isToContract, "रिकाम्या पत्त्यावर टोकन पाठवू शकत नाही"); +``` + +आणि शेवटी, आमच्याकडे रिकाम्या पत्त्यांसाठी वास्तविक तपासणी आहे. + +## प्रशासकीय प्रवेश {#admin-access} + +कधीकधी चुका पूर्ववत करू शकणारा प्रशासक असणे उपयुक्त ठरते. गैरवापराची शक्यता कमी करण्यासाठी, हा प्रशासक एक [multisig](https://blog.logrocket.com/security-choices-multi-signature-wallets/) असू शकतो जेणेकरून एका कृतीवर अनेक लोकांना सहमत व्हावे लागेल. या लेखात आमच्याकडे दोन प्रशासकीय वैशिष्ट्ये असतील: + +1. खाती फ्रीझ करणे आणि अनफ्रीझ करणे. हे उपयुक्त असू शकते, उदाहरणार्थ, जेव्हा एखादे खाते धोक्यात आले असेल. +2. मालमत्ता स्वच्छता. + + कधीकधी फसवणूक करणारे वैधता मिळविण्यासाठी वास्तविक टोकनच्या कॉन्ट्रॅक्टवर बनावट टोकन पाठवतात. उदाहरणार्थ, [येथे पहा](https://optimism.blockscout.com/token/0x2348B1a1228DDCd2dB668c3d30207c3E1852fBbe?tab=holders). कायदेशीर ERC-20 कॉन्ट्रॅक्ट [0x4200....0042](https://optimism.blockscout.com/token/0x4200000000000000000000000000000000000042) आहे. त्याचा बहाणा करणारा घोटाळा [0x234....bbe](https://optimism.blockscout.com/token/0x2348B1a1228DDCd2dB668c3d30207c3E1852fBbe) आहे. + + हे देखील शक्य आहे की लोक चुकून आमच्या कॉन्ट्रॅक्टवर कायदेशीर ERC-20 टोकन पाठवतात, जे त्यांना बाहेर काढण्याचा मार्ग हवा असण्याचे आणखी एक कारण आहे. + +OpenZeppelin प्रशासकीय प्रवेश सक्षम करण्यासाठी दोन यंत्रणा प्रदान करते: + +- [`Ownable`](https://docs.openzeppelin.com/contracts/5.x/access-control#ownership-and-ownable) कॉन्ट्रॅक्ट्सचा एकच मालक असतो. `onlyOwner` [modifier](https://www.tutorialspoint.com/solidity/solidity_function_modifiers.htm) असलेले फंक्शन्स फक्त त्या मालकाद्वारे कॉल केले जाऊ शकतात. मालक मालकी दुसऱ्या कोणाला हस्तांतरित करू शकतात किंवा पूर्णपणे सोडून देऊ शकतात. इतर सर्व खात्यांचे अधिकार सामान्यतः समान असतात. +- [`AccessControl`](https://docs.openzeppelin.com/contracts/5.x/access-control#role-based-access-control) कॉन्ट्रॅक्ट्समध्ये [भूमिका-आधारित प्रवेश नियंत्रण (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control) असते. + +साधेपणासाठी, या लेखात आम्ही `Ownable` वापरतो. + +### कॉन्ट्रॅक्ट्स फ्रीझ करणे आणि थॉ करणे {#freezing-and-thawing-contracts} + +कॉन्ट्रॅक्ट्स फ्रीझ करणे आणि थॉ करण्यासाठी अनेक बदलांची आवश्यकता आहे: + +- कोणते पत्ते फ्रीझ केले आहेत याचा मागोवा ठेवण्यासाठी पत्त्यांवरून [booleans](https://en.wikipedia.org/wiki/Boolean_data_type) पर्यंतचे [mapping](https://www.tutorialspoint.com/solidity/solidity_mappings.htm). सर्व मूल्ये सुरुवातीला शून्य असतात, ज्याचा अर्थ बुलियन मूल्यांसाठी असत्य (false) असा लावला जातो. हेच आम्हाला हवे आहे कारण डीफॉल्टनुसार खाती फ्रीझ केलेली नसतात. + + ```solidity + mapping(address => bool) public frozenAccounts; + ``` + +- एखादे खाते फ्रीझ किंवा थॉ झाल्यावर कोणालाही माहिती देण्यासाठी [Events](https://www.tutorialspoint.com/solidity/solidity_events.htm). तांत्रिकदृष्ट्या या क्रियांसाठी इव्हेंट्स आवश्यक नाहीत, परंतु ते ऑफचेन कोडला या इव्हेंट्स ऐकण्यास आणि काय होत आहे हे जाणून घेण्यास मदत करते. स्मार्ट कॉन्ट्रॅक्टसाठी जेव्हा दुसऱ्या कोणासाठी संबंधित काहीतरी घडते तेव्हा ते उत्सर्जित करणे चांगले शिष्टाचार मानले जाते. + + इव्हेंट्स अनुक्रमित केले जातात जेणेकरून खाते किती वेळा फ्रीझ किंवा थॉ केले गेले आहे हे शोधणे शक्य होईल. + + ```solidity + // जेव्हा खाती फ्रीझ किंवा अनफ्रीझ केली जातात + event AccountFrozen(address indexed _addr); + event AccountThawed(address indexed _addr); + ``` + +- खाती फ्रीझ आणि थॉ करण्यासाठी फंक्शन्स. ही दोन फंक्शन्स जवळजवळ सारखीच आहेत, म्हणून आपण फक्त फ्रीझ फंक्शन पाहू. + + ```solidity + function freezeAccount(address addr) + public + onlyOwner + ``` + + [`public`](https://www.tutorialspoint.com/solidity/solidity_contracts.htm) म्हणून चिन्हांकित केलेली फंक्शन्स इतर स्मार्ट कॉन्ट्रॅक्ट्समधून किंवा थेट व्यवहाराद्वारे कॉल केली जाऊ शकतात. + + ```solidity + { + require(!frozenAccounts[addr], "खाते आधीच फ्रीझ आहे"); + frozenAccounts[addr] = true; + emit AccountFrozen(addr); + } // freezeAccount + ``` + + जर खाते आधीच फ्रीझ असेल, तर उलट करा. अन्यथा, ते फ्रीझ करा आणि एक इव्हेंट `emit` करा. + +- फ्रीझ केलेल्या खात्यातून पैसे हलवण्यापासून रोखण्यासाठी `_beforeTokenTransfer` बदला. लक्षात घ्या की फ्रीझ केलेल्या खात्यात अजूनही पैसे हस्तांतरित केले जाऊ शकतात. + + ```solidity + require(!frozenAccounts[from], "खाते फ्रीझ आहे"); + ``` + +### मालमत्ता स्वच्छता {#asset-cleanup} + +या कॉन्ट्रॅक्टद्वारे ठेवलेले ERC-20 टोकन सोडण्यासाठी, आम्हाला त्यांच्या टोकन कॉन्ट्रॅक्टवर [`transfer`](https://eips.ethereum.org/EIPS/eip-20#transfer) किंवा [`approve`](https://eips.ethereum.org/EIPS/eip-20#approve) फंक्शन कॉल करणे आवश्यक आहे. या प्रकरणात भत्त्यांवर गॅस वाया घालवण्यात काही अर्थ नाही, आपण थेट हस्तांतरण करणेच बरे. + +```solidity + function cleanupERC20( + address erc20, + address dest + ) + public + onlyOwner + { + IERC20 token = IERC20(erc20); +``` + +जेव्हा आम्हाला पत्ता मिळतो तेव्हा कॉन्ट्रॅक्टसाठी ऑब्जेक्ट तयार करण्यासाठी हे सिंटॅक्स आहे. आपण हे करू शकतो कारण आमच्याकडे सोर्स कोडचा भाग म्हणून ERC20 टोकनची व्याख्या आहे (ओळ 4 पहा), आणि त्या फाईलमध्ये [IERC20 साठीची व्याख्या](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol) समाविष्ट आहे, जो OpenZeppelin ERC-20 कॉन्ट्रॅक्टचा इंटरफेस आहे. + +```solidity + uint balance = token.balanceOf(address(this)); + token.transfer(dest, balance); + } +``` + +हे एक स्वच्छता फंक्शन आहे, म्हणून आम्ही कोणतेही टोकन सोडू इच्छित नाही असे गृहीत धरले जाते. वापरकर्त्याकडून मॅन्युअली शिल्लक मिळवण्याऐवजी, आपण प्रक्रिया स्वयंचलित करणेच बरे. + +## निष्कर्ष {#conclusion} + +हा एक परिपूर्ण उपाय नाही - "वापरकर्त्याने चूक केली" या समस्येवर कोणताही परिपूर्ण उपाय नाही. तथापि, या प्रकारच्या तपासण्या वापरून किमान काही चुका टाळता येतात. खाती फ्रीझ करण्याची क्षमता, धोकादायक असली तरी, हॅकरला चोरलेले फंड नाकारून काही हॅक्सचे नुकसान मर्यादित करण्यासाठी वापरली जाऊ शकते. + +[माझ्या कामाबद्दल अधिक माहितीसाठी येथे पहा](https://cryptodocguy.pro/). diff --git a/public/content/translations/mr/developers/tutorials/ethereum-for-web2-auth/index.md b/public/content/translations/mr/developers/tutorials/ethereum-for-web2-auth/index.md new file mode 100644 index 00000000000..57fbf468676 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/ethereum-for-web2-auth/index.md @@ -0,0 +1,886 @@ +--- +title: "web2 प्रमाणीकरणासाठी Ethereum वापरणे" +description: "हे ट्युटोरियल वाचल्यानंतर, एक डेव्हलपर Ethereum लॉगिन (web3) ला SAML लॉगिन सोबत इंटिग्रेट करू शकेल, जे web2 मध्ये सिंगल साइन-ऑन आणि इतर संबंधित सेवा प्रदान करण्यासाठी वापरले जाणारे एक स्टँडर्ड आहे. हे web2 रिसोर्सेसना Ethereum सिग्नेचर्सद्वारे ऑथेंटिकेट करण्याची परवानगी देते, ज्यात वापरकर्त्याचे अ‍ॅट्रिब्यूट्स अटेस्टेशन्समधून येतात." +author: Ori Pomerantz +tags: [ "web2", "प्रमाणीकरण", "eas" ] +skill: beginner +lang: mr +published: 2025-04-30 +--- + +## परिचय + +[SAML](https://www.onelogin.com/learn/saml) हे web2 वर वापरले जाणारे एक स्टँडर्ड आहे जे [आयडेंटिटी प्रोव्हायडर (IdP)](https://en.wikipedia.org/wiki/Identity_provider#SAML_identity_provider) ला [सर्व्हिस प्रोव्हायडर्स (SP)](https://en.wikipedia.org/wiki/Service_provider_\(SAML\)) साठी वापरकर्त्याची माहिती प्रदान करण्याची परवानगी देते. + +या ट्युटोरियलमध्ये तुम्ही Ethereum सिग्नेचरला SAML सोबत कसे समाकलित करायचे ते शिकाल जेणेकरून वापरकर्ते त्यांचे Ethereum वॉलेट वापरून स्वतःला web2 सेवांमध्ये प्रमाणित करू शकतील जे अद्याप मूळतः Ethereum ला सपोर्ट करत नाहीत. + +लक्षात घ्या की हे ट्युटोरियल दोन स्वतंत्र श्रोत्यांसाठी लिहिलेले आहे: + +- Ethereum चे लोक ज्यांना Ethereum समजते आणि ज्यांना SAML शिकण्याची गरज आहे +- Web2 चे लोक ज्यांना SAML आणि web2 प्रमाणीकरण समजते आणि ज्यांना Ethereum शिकण्याची गरज आहे + +परिणामी, यात बरीच प्रास्ताविक माहिती असणार आहे जी तुम्हाला आधीच माहित आहे. ते वगळण्यास मोकळ्या मनाने. + +### Ethereum च्या लोकांसाठी SAML + +SAML हा एक सेंट्रलाइज्ड प्रोटोकॉल आहे. एक सर्व्हिस प्रोव्हायडर (SP) केवळ आयडेंटिटी प्रोव्हायडर (IdP) कडून अझर्शन्स (जसे की "हा माझा वापरकर्ता जॉन आहे, त्याला A, B आणि C करण्याची परवानगी असावी") स्वीकारतो, जर त्याचा त्याच्याशी किंवा त्या IdP च्या प्रमाणपत्रावर सही करणाऱ्या [सर्टिफिकेट अथॉरिटी](https://www.ssl.com/article/what-is-a-certificate-authority-ca/) शी पूर्व-अस्तित्वात असलेला विश्वासाचा संबंध असेल. + +उदाहरणार्थ, SP ही कंपन्यांना प्रवास सेवा पुरवणारी ट्रॅव्हल एजन्सी असू शकते आणि IdP ही कंपनीची अंतर्गत वेबसाईट असू शकते. जेव्हा कर्मचाऱ्यांना व्यवसायासाठी प्रवास बुक करण्याची आवश्यकता असते, तेव्हा ट्रॅव्हल एजन्सी त्यांना प्रवास बुक करण्याची परवानगी देण्यापूर्वी कंपनीद्वारे प्रमाणीकरणासाठी पाठवते. + +![स्टेप बाय स्टेप SAML प्रक्रिया](./fig-01-saml.png) + +हा तो मार्ग आहे ज्याद्वारे तीन घटक, ब्राउझर, SP आणि IdP, प्रवेशासाठी वाटाघाटी करतात. SP ला ब्राउझर वापरणाऱ्या वापरकर्त्याबद्दल आगाऊ काहीही जाणून घेण्याची आवश्यकता नाही, फक्त IdP वर विश्वास ठेवणे आवश्यक आहे. + +### SAML च्या लोकांसाठी Ethereum + +Ethereum ही एक विकेंद्रित प्रणाली आहे. + +![Ethereum लॉगऑन](./fig-02-eth-logon.png) + +वापरकर्त्यांकडे एक प्रायव्हेट की असते (सामान्यतः ब्राउझर एक्स्टेंशनमध्ये ठेवली जाते). प्रायव्हेट की मधून तुम्ही पब्लिक की मिळवू शकता, आणि त्यातून एक 20-बाईट अ‍ॅड्रेस. जेव्हा वापरकर्त्यांना सिस्टीममध्ये लॉग इन करण्याची आवश्यकता असते, तेव्हा त्यांना एका नॉन्स (एकल-वापर मूल्य) सह मेसेजवर सही करण्याची विनंती केली जाते. सर्व्हर त्या अ‍ॅड्रेसद्वारे सिग्नेचर तयार केली गेली होती हे सत्यापित करू शकतो. + +![अटेस्टेशन्समधून अतिरिक्त डेटा मिळवणे](./fig-03-eas-data.png) + +सिग्नेचर केवळ Ethereum अ‍ॅड्रेसची पडताळणी करते. इतर वापरकर्ता अ‍ॅट्रिब्युट्स मिळवण्यासाठी, तुम्ही सामान्यतः [अटेस्टेशन्स](https://attest.org/) वापरता. अटेस्टेशनमध्ये सामान्यतः हे फिल्ड्स असतात: + +- **अटेस्टॉर**, ज्या अ‍ॅड्रेसने अटेस्टेशन केले +- **प्राप्तकर्ता**, ज्या अ‍ॅड्रेसवर अटेस्टेशन लागू होते +- **डेटा**, अटेस्ट केला जाणारा डेटा, जसे की नाव, परवानग्या इ. +- **स्कीमा**, डेटाचा अर्थ लावण्यासाठी वापरल्या जाणार्‍या स्कीमाचा ID. + +Ethereum च्या विकेंद्रित स्वरूपामुळे, कोणताही वापरकर्ता अटेस्टेशन्स करू शकतो. आपण कोणती अटेस्टेशन्स विश्वसनीय मानतो हे ओळखण्यासाठी अटेस्टॉरची ओळख महत्त्वाची आहे. + +## सेटअप + +पहिली पायरी म्हणजे SAML SP आणि SAML IdP एकमेकांशी संवाद साधत असणे. + +1. सॉफ्टवेअर डाऊनलोड करा. या लेखासाठी नमुना सॉफ्टवेअर [github वर](https://github.com/qbzzt/250420-saml-ethereum) आहे. वेगवेगळे टप्पे वेगवेगळ्या शाखांमध्ये संग्रहित केले आहेत, या टप्प्यासाठी तुम्हाला `saml-only` पाहिजे. + + ```sh + git clone https://github.com/qbzzt/250420-saml-ethereum -b saml-only + cd 250420-saml-ethereum + pnpm install + ``` + +2. स्व-स्वाक्षरी केलेल्या प्रमाणपत्रांसह की तयार करा. याचा अर्थ की ही की स्वतःच एक प्रमाणपत्र प्राधिकरण आहे आणि सेवा प्रदात्याकडे व्यक्तिचलितरित्या आयात करणे आवश्यक आहे. अधिक माहितीसाठी [OpenSSL डॉक्स](https://docs.openssl.org/master/man1/openssl-req/) पहा. + + ```sh + mkdir keys + cd keys + openssl req -new -x509 -days 365 -nodes -sha256 -out saml-sp.crt -keyout saml-sp.pem -subj /CN=sp/ + openssl req -new -x509 -days 365 -nodes -sha256 -out saml-idp.crt -keyout saml-idp.pem -subj /CN=idp/ + cd .. + ``` + +3. सर्व्हर (SP आणि IdP दोन्ही) सुरू करा + + ```sh + pnpm start + ``` + +4. URL [http://localhost:3000/](http://localhost:3000/) वर SP वर ब्राउझ करा आणि IdP (पोर्ट 3001) वर पुनर्निर्देशित होण्यासाठी बटणावर क्लिक करा. + +5. IdP ला तुमचा ईमेल अ‍ॅड्रेस द्या आणि **सर्व्हिस प्रोव्हायडरमध्ये लॉगिन करा** वर क्लिक करा. तुम्ही सर्व्हिस प्रोव्हायडर (पोर्ट 3000) वर परत पुनर्निर्देशित झाल्याचे आणि ते तुम्हाला तुमच्या ईमेल अ‍ॅड्रेसने ओळखत असल्याचे पहा. + +### तपशीलवार स्पष्टीकरण + +हे काय घडते, ते टप्प्याटप्प्याने येथे दिले आहे: + +![Ethereum शिवाय सामान्य SAML लॉगऑन](./fig-04-saml-no-eth.png) + +#### src/config.mts + +या फाईलमध्ये आयडेंटिटी प्रोव्हायडर आणि सर्व्हिस प्रोव्हायडर दोन्हीसाठी कॉन्फिगरेशन आहे. सामान्यतः हे दोन वेगळे घटक असतील, परंतु येथे आपण साधेपणासाठी कोड शेअर करू शकतो. + +```typescript +const fs = await import("fs") + +const protocol="http" +``` + +सध्या आम्ही फक्त चाचणी करत आहोत, त्यामुळे HTTP वापरणे ठीक आहे. + +```typescript +export const spCert = fs.readFileSync("keys/saml-sp.crt").toString() +export const idpCert = fs.readFileSync("keys/saml-idp.crt").toString() +``` + +पब्लिक की वाचा, ज्या सामान्यतः दोन्ही घटकांसाठी उपलब्ध असतात (आणि एकतर थेट विश्वासार्ह असतात, किंवा विश्वासार्ह प्रमाणपत्र प्राधिकरणाद्वारे स्वाक्षरी केलेल्या असतात). + +```typescript +export const spPort = 3000 +export const spHostname = "localhost" +export const spDir = "sp" + +export const idpPort = 3001 +export const idpHostname = "localhost" +export const idpDir = "idp" + +export const spUrl = `${protocol}://${spHostname}:${spPort}/${spDir}` +export const idpUrl = `${protocol}://${idpHostname}:${idpPort}/${idpDir}` +``` + +दोन्ही घटकांसाठी URLs. + +```typescript +export const spPublicData = { +``` + +सर्व्हिस प्रोव्हायडरसाठी सार्वजनिक डेटा. + +```typescript + entityID: `${spUrl}/metadata`, +``` + +प्रथेनुसार, SAML मध्ये `entityID` ही URL असते जिथे घटकाचा मेटाडेटा उपलब्ध असतो. हा मेटाडेटा येथील सार्वजनिक डेटाशी संबंधित आहे, फक्त तो XML स्वरूपात आहे. + +```typescript + wantAssertionsSigned: true, + authnRequestsSigned: false, + signingCert: spCert, + allowCreate: true, + assertionConsumerService: [{ + Binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', + Location: `${spUrl}/assertion`, + }] + } +``` + +आमच्या उद्देशांसाठी सर्वात महत्त्वाची व्याख्या `assertionConsumerServer` आहे. याचा अर्थ असा की सर्व्हिस प्रोव्हायडरला काहीतरी ठामपणे सांगण्यासाठी (उदाहरणार्थ, "तुम्हाला ही माहिती पाठवणारा वापरकर्ता somebody@example.com आहे") आम्हाला `http://localhost:3000/sp/assertion` या URL वर [HTTP POST](https://www.w3schools.com/tags/ref_httpmethods.asp) वापरण्याची आवश्यकता आहे. + +```typescript +export const idpPublicData = { + entityID: `${idpUrl}/metadata`, + signingCert: idpCert, + wantAuthnRequestsSigned: false, + singleSignOnService: [{ + Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", + Location: `${idpUrl}/login` + }], + singleLogoutService: [{ + Binding: "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", + Location: `${idpUrl}/logout` + }], + } +``` + +आयडेंटिटी प्रोव्हायडरसाठी सार्वजनिक डेटा समान आहे. यात नमूद केले आहे की वापरकर्त्याला लॉग इन करण्यासाठी तुम्ही `http://localhost:3001/idp/login` वर POST करा आणि वापरकर्त्याला लॉग आउट करण्यासाठी तुम्ही `http://localhost:3001/idp/logout` वर POST करा. + +#### src/sp.mts + +हा कोड सर्व्हिस प्रोव्हायडरची अंमलबजावणी करतो. + +```typescript +import * as config from "./config.mts" +const fs = await import("fs") +const saml = await import("samlify") +``` + +आम्ही SAML लागू करण्यासाठी [`samlify`](https://www.npmjs.com/package/samlify) लायब्ररी वापरतो. + +```typescript +import * as validator from "@authenio/samlify-node-xmllint" +saml.setSchemaValidator(validator) +``` + +`samlify` लायब्ररीला एक पॅकेज हवे असते जे XML योग्य आहे, अपेक्षित पब्लिक की ने स्वाक्षरी केलेले आहे इत्यादीची पडताळणी करते. आम्ही या उद्देशासाठी [`@authenio/samlify-node-xmllint`](https://www.npmjs.com/package/@authenio/samlify-node-xmllint) वापरतो. + +```typescript +const express = (await import("express")).default +const spRouter = express.Router() +const app = express() +``` + +एक [`express`](https://expressjs.com/) [`Router`](https://expressjs.com/en/5x/api.html#router) ही एक "मिनी वेब साईट" आहे जी वेबसाईटच्या आत माउंट केली जाऊ शकते. या प्रकरणात, आम्ही सर्व सर्व्हिस प्रोव्हायडर व्याख्या एकत्र गटबद्ध करण्यासाठी याचा वापर करतो. + +```typescript +const spPrivateKey = fs.readFileSync("keys/saml-sp.pem").toString() + +const sp = saml.ServiceProvider({ + privateKey: spPrivateKey, + ...config.spPublicData +}) +``` + +सर्व्हिस प्रोव्हायडरचे स्वतःचे प्रतिनिधित्व म्हणजे सर्व सार्वजनिक डेटा आणि माहितीवर स्वाक्षरी करण्यासाठी वापरली जाणारी प्रायव्हेट की. + +```typescript +const idp = saml.IdentityProvider(config.idpPublicData); +``` + +सार्वजनिक डेटामध्ये सर्व्हिस प्रोव्हायडरला आयडेंटिटी प्रोव्हायडरबद्दल माहित असणे आवश्यक असलेली प्रत्येक गोष्ट असते. + +```typescript +spRouter.get(`/metadata`, + (req, res) => res.header("Content-Type", "text/xml").send(sp.getMetadata()) +) +``` + +इतर SAML घटकांसह आंतरकार्यक्षमता सक्षम करण्यासाठी, सेवा आणि ओळख प्रदात्यांनी त्यांचा सार्वजनिक डेटा (मेटाडेटा म्हणतात) `/metadata` मध्ये XML स्वरूपात उपलब्ध करून दिला पाहिजे. + +```typescript +spRouter.post(`/assertion`, +``` + +हे ब्राउझरद्वारे स्वतःची ओळख पटवण्यासाठी अ‍ॅक्सेस केलेले पेज आहे. असर्शनमध्ये वापरकर्ता ओळखकर्ता (येथे आम्ही ईमेल अ‍ॅड्रेस वापरतो) समाविष्ट असतो आणि त्यात अतिरिक्त अ‍ॅट्रिब्यूट्स समाविष्ट असू शकतात. हे वरील क्रम आकृतीमधील पायरी 7 साठी हँडलर आहे. + +```typescript + async (req, res) => { + // console.log(`SAML response:\n${Buffer.from(req.body.SAMLResponse, 'base64').toString('utf-8')}`) +``` + +तुम्ही अझर्शनमध्ये प्रदान केलेला XML डेटा पाहण्यासाठी टिप्पणी केलेला कमांड वापरू शकता. ते [base64 एन्कोड केलेले](https://en.wikipedia.org/wiki/Base64) आहे. + +```typescript + try { + const loginResponse = await sp.parseLoginResponse(idp, 'post', req); +``` + +आयडेंटिटी सर्व्हरवरून लॉगिन विनंती पार्स करा. + +```typescript + res.send(` + + +

Hello ${loginResponse.extract.nameID}

+ + + `) + res.send(); +``` + +वापरकर्त्याला दाखवण्यासाठी की आम्हाला लॉगिन मिळाले आहे, एक HTML प्रतिसाद पाठवा. + +```typescript + } catch (err) { + console.error('Error processing SAML response:', err); + res.status(400).send('SAML authentication failed'); + } + } +) +``` + +अयशस्वी झाल्यास वापरकर्त्याला कळवा. + +```typescript +spRouter.get('/login', +``` + +जेव्हा ब्राउझर हे पृष्ठ मिळवण्याचा प्रयत्न करतो तेव्हा एक लॉगिन विनंती तयार करा. हे वरील क्रम आकृतीमधील पायरी 1 साठी हँडलर आहे. + +```typescript + async (req, res) => { + const loginRequest = await sp.createLoginRequest(idp, "post") +``` + +लॉगिन विनंती पोस्ट करण्यासाठी माहिती मिळवा. + +```typescript + res.send(` + + + +``` + +हे पृष्ठ फॉर्म (खाली पहा) आपोआप सबमिट करते. यामुळे वापरकर्त्याला पुनर्निर्देशित होण्यासाठी काहीही करण्याची गरज नाही. हे वरील क्रम आकृतीमधील पायरी 2 आहे. + +```typescript +
+``` + +`loginRequest.entityEndpoint` (आयडेंटिटी प्रोव्हायडर एंडपॉईंटची URL) वर पोस्ट करा. + +```typescript + +``` + +इनपुट नाव `loginRequest.type` (`SAMLRequest`) आहे. त्या फिल्डमधील मजकूर `loginRequest.context` आहे, जो पुन्हा base64 एन्कोड केलेला XML आहे. + +```typescript +
+ + + `) + } +) + +app.use(express.urlencoded({extended: true})) +``` + +[हे मिडलवेअर](https://expressjs.com/en/5x/api.html#express.urlencoded) [HTTP विनंती](https://www.tutorialspoint.com/http/http_requests.htm) चा मुख्य भाग वाचतो. डीफॉल्टनुसार एक्सप्रेस त्याकडे दुर्लक्ष करते, कारण बहुतेक विनंत्यांसाठी त्याची आवश्यकता नसते. आम्हाला त्याची आवश्यकता आहे कारण POST मुख्य भाग वापरतो. + +```typescript +app.use(`/${config.spDir}`, spRouter) +``` + +सर्व्हिस प्रोव्हायडर डिरेक्टरी (`/sp`) मध्ये राउटर माउंट करा. + +```typescript +app.get("/", (req, res) => { + res.send(` + + + + + + `) +}) +``` + +जर ब्राउझरला रूट डिरेक्टरी मिळवण्याचा प्रयत्न केल्यास, त्याला लॉगिन पेजची लिंक द्या. + +```typescript +app.listen(config.spPort, () => { + console.log(`service provider is running on http://${config.spHostname}:${config.spPort}`) +}) +``` + +या एक्सप्रेस ॲप्लिकेशनसह `spPort` ऐका. + +#### src/idp.mts + +हा आयडेंटिटी प्रोव्हायडर आहे. हे सर्व्हिस प्रोव्हायडरसारखेच आहे, खालील स्पष्टीकरण वेगळ्या भागांसाठी आहेत. + +```typescript +const xmlParser = new (await import("fast-xml-parser")).XMLParser( + { + ignoreAttributes: false, // Preserve attributes + attributeNamePrefix: "@_", // Prefix for attributes + } +) +``` + +आम्हाला सर्व्हिस प्रोव्हायडरकडून मिळालेली XML विनंती वाचणे आणि समजून घेणे आवश्यक आहे. + +```typescript +const getLoginPage = requestId => ` +``` + +हे फंक्शन वरील क्रम आकृतीमधील पायरी 4 मध्ये परत आलेल्या स्वयंचलित-सबमिट केलेल्या फॉर्मसह पृष्ठ तयार करते. + +```typescript + + + Login page + + +

Login page

+
+ + Email address: +
+ +``` + +आम्ही सर्व्हिस प्रोव्हायडरला दोन फिल्ड्स पाठवतो: + +1. ज्या `requestId` ला आम्ही प्रतिसाद देत आहोत. +2. वापरकर्ता ओळखकर्ता (आम्ही वापरकर्त्याने आतासाठी प्रदान केलेला ईमेल अ‍ॅड्रेस वापरतो). + +```typescript +
+ + + +const idpRouter = express.Router() + +idpRouter.post("/loginSubmitted", async (req, res) => { + const loginResponse = await idp.createLoginResponse( +``` + +हे वरील क्रम आकृतीमधील पायरी 5 साठी हँडलर आहे. [`idp.createLoginResponse`](https://github.com/tngan/samlify/blob/master/src/entity-idp.ts#L73-L125) लॉगिन प्रतिसाद तयार करते. + +```typescript + sp, + { + authnContextClassRef: 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', + audience: sp.entityID, +``` + +श्रोता सर्व्हिस प्रोव्हायडर आहे. + +```typescript + extract: { + request: { + id: req.body.requestId + } + }, +``` + +विनंतीमधून काढलेली माहिती. विनंतीमधील आपल्याला महत्त्वाचा असलेला एक पॅरामीटर म्हणजे requestId, जो सर्व्हिस प्रोव्हायडरला विनंत्या आणि त्यांचे प्रतिसाद जुळवू देतो. + +```typescript + signingKey: { privateKey: idpPrivateKey, publicKey: config.idpCert } // Ensure signing +``` + +प्रतिसादावर स्वाक्षरी करण्यासाठी डेटा मिळवण्यासाठी आम्हाला `signingKey` ची आवश्यकता आहे. सर्व्हिस प्रोव्हायडर स्वाक्षरी नसलेल्या विनंत्यांवर विश्वास ठेवत नाही. + +```typescript + }, + "post", + { + email: req.body.email +``` + +हे फिल्ड आम्ही सर्व्हिस प्रोव्हायडरला परत पाठवत असलेल्या वापरकर्ता माहितीसह आहे. + +```typescript + } + ); + + res.send(` + + + + +
+ +
+ + + `) +}) +``` + +पुन्हा, स्वयंचलित-सबमिट केलेला फॉर्म वापरा. हे वरील क्रम आकृतीमधील पायरी 6 आहे. + +```typescript + +// IdP endpoint for login requests +idpRouter.post(`/login`, +``` + +हा एंडपॉईंट आहे जो सर्व्हिस प्रोव्हायडरकडून लॉगिन विनंती प्राप्त करतो. हे वरील क्रम आकृतीमधील पायरी 3 साठी हँडलर आहे. + +```typescript + async (req, res) => { + try { + // Workaround because I couldn't get parseLoginRequest to work. + // const loginRequest = await idp.parseLoginRequest(sp, 'post', req) + const samlRequest = xmlParser.parse(Buffer.from(req.body.SAMLRequest, 'base64').toString('utf-8')) + res.send(getLoginPage(samlRequest["samlp:AuthnRequest"]["@_ID"])) +``` + +आपण प्रमाणीकरण विनंतीचा आयडी वाचण्यासाठी [`idp.parseLoginRequest`](https://github.com/tngan/samlify/blob/master/src/entity-idp.ts#L127-L144) वापरू शकले पाहिजे. तथापि, मला ते काम करायला जमले नाही आणि त्यावर जास्त वेळ घालवणे योग्य नव्हते म्हणून मी फक्त एक [सामान्य-उद्देशीय XML पार्सर](https://www.npmjs.com/package/fast-xml-parser) वापरतो. आम्हाला आवश्यक असलेली माहिती `` टॅगमधील `ID` विशेषता आहे, जी XML च्या शीर्ष स्तरावर आहे. + +## Ethereum सिग्नेचर वापरणे + +आता आपण सर्व्हिस प्रोव्हायडरला वापरकर्त्याची ओळख पाठवू शकतो, पुढील पायरी म्हणजे विश्वसनीय पद्धतीने वापरकर्त्याची ओळख मिळवणे. Viem आपल्याला वॉलेटमधून वापरकर्त्याचा अ‍ॅड्रेस विचारण्याची परवानगी देतो, पण याचा अर्थ ब्राउझरकडून माहिती विचारणे आहे. आपण ब्राउझरवर नियंत्रण ठेवत नाही, त्यामुळे आपण त्यातून मिळणाऱ्या प्रतिसादावर आपोआप विश्वास ठेवू शकत नाही. + +त्याऐवजी, IdP ब्राउझरला स्वाक्षरी करण्यासाठी एक स्ट्रिंग पाठवेल. जर ब्राउझरमधील वॉलेट या स्ट्रिंगवर स्वाक्षरी करत असेल, तर याचा अर्थ तो खरोखरच तो अ‍ॅड्रेस आहे (म्हणजेच, त्याला अ‍ॅड्रेसशी संबंधित असलेली प्रायव्हेट की माहित आहे). + +हे कृतीत पाहण्यासाठी, विद्यमान IdP आणि SP थांबवा आणि हे कमांड चालवा: + +```sh +git checkout eth-signatures +pnpm install +pnpm start +``` + +नंतर [SP वर](http://localhost:3000) ब्राउझ करा आणि निर्देशांचे पालन करा. + +लक्षात ठेवा की या टप्प्यावर आम्हाला Ethereum अ‍ॅड्रेसवरून ईमेल अ‍ॅड्रेस कसा मिळवायचा हे माहित नाही, म्हणून त्याऐवजी आम्ही SP ला `@bad.email.address` असे रिपोर्ट करतो. + +### तपशीलवार स्पष्टीकरण + +बदल मागील आकृतीमधील पायरी 4-5 मध्ये आहेत. + +![Ethereum सिग्नेचरसह SAML](./fig-05-saml-w-signature.png) + +आम्ही बदललेली एकमेव फाईल `idp.mts` आहे. येथे बदललेले भाग आहेत. + +```typescript +import { v4 as uuidv4 } from 'uuid' +import { verifyMessage } from 'viem' +``` + +आम्हाला या दोन अतिरिक्त लायब्ररींची गरज आहे. आम्ही [nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) व्हॅल्यू तयार करण्यासाठी [`uuid`](https://www.npmjs.com/package/uuid) वापरतो. मूल्य स्वतः महत्त्वाचे नाही, फक्त ते एकदाच वापरले जाते हे महत्त्वाचे आहे. + +[`viem`](https://viem.sh/) लायब्ररी आम्हाला Ethereum डेफिनेशन्स वापरण्याची परवानगी देते. येथे आम्हाला स्वाक्षरी खरोखरच वैध आहे की नाही हे तपासण्यासाठी त्याची आवश्यकता आहे. + +```typescript +const loginPrompt = "To access the service provider, sign this nonce: " +``` + +वॉलेट वापरकर्त्याला मेसेजवर स्वाक्षरी करण्याची परवानगी विचारते. फक्त एक नॉन्स असलेला संदेश वापरकर्त्यांना गोंधळात टाकू शकतो, म्हणून आम्ही हा प्रॉम्प्ट समाविष्ट करतो. + +```typescript +// Keep requestIDs here +let nonces = {} +``` + +आम्हाला त्याला प्रतिसाद देण्यासाठी विनंती माहितीची आवश्यकता आहे. आपण ते विनंतीसह पाठवू शकतो (पायरी 4), आणि ते परत मिळवू शकतो (पायरी 5). तथापि, आपण ब्राउझरकडून मिळणाऱ्या माहितीवर विश्वास ठेवू शकत नाही, जो संभाव्यतः शत्रुत्वापूर्ण वापरकर्त्याच्या नियंत्रणाखाली असतो. त्यामुळे ते येथे संग्रहित करणे चांगले आहे, नॉन्सला की म्हणून वापरून. + +लक्षात घ्या की आम्ही हे साधेपणासाठी येथे व्हेरिएबल म्हणून करत आहोत. तथापि, याचे अनेक तोटे आहेत: + +- आपण डिनायल ऑफ सर्व्हिस हल्ल्यासाठी असुरक्षित आहोत. एक दुर्भावनापूर्ण वापरकर्ता अनेक वेळा लॉग ऑन करण्याचा प्रयत्न करू शकतो, ज्यामुळे आमची मेमरी भरली जाईल. +- जर IdP प्रक्रिया पुन्हा सुरू करण्याची आवश्यकता असेल, तर आम्ही विद्यमान मूल्ये गमावतो. +- आपण अनेक प्रक्रिया ओलांडून लोड बॅलन्स करू शकत नाही, कारण प्रत्येकाचे स्वतःचे व्हेरिएबल असेल. + +उत्पादन प्रणालीवर आपण डेटाबेस वापरू आणि काही प्रकारची समाप्ती यंत्रणा लागू करू. + +```typescript +const getSignaturePage = requestId => { + const nonce = uuidv4() + nonces[nonce] = requestId +``` + +एक नॉन्स तयार करा आणि भविष्यातील वापरासाठी `requestId` संग्रहित करा. + +```typescript + return ` + + + + + +

Please sign

+ +
+ + + +` +} +``` + +उरलेले फक्त स्टँडर्ड HTML आहे. + +```typescript +idpRouter.get("/signature/:nonce/:account/:signature", async (req, res) => { +``` + +हे क्रम आकृतीमधील पायरी 5 साठी हँडलर आहे. + +```typescript + const requestId = nonces[req.params.nonce] + if (requestId === undefined) { + res.send("Bad nonce") + return ; + } + + nonces[req.params.nonce] = undefined +``` + +रिक्वेस्ट आयडी मिळवा, आणि `nonces` मधून नॉन्स हटवा जेणेकरून त्याचा पुन्हा वापर होणार नाही याची खात्री करा. + +```typescript + try { +``` + +सिग्नेचर अवैध असण्याचे अनेक मार्ग असल्यामुळे, आपण हे `try ...` मध्ये गुंडाळतो. कोणत्याही फेकलेल्या त्रुटी पकडण्यासाठी `catch` ब्लॉक. + +```typescript + const validSignature = await verifyMessage({ + address: req.params.account, + message: `${loginPrompt}${req.params.nonce}`, + signature: req.params.signature + }) +``` + +क्रम आकृतीमधील पायरी 5.5 लागू करण्यासाठी [`verifyMessage`](https://viem.sh/docs/actions/public/verifyMessage#verifymessage) वापरा. + +```typescript + if (!validSignature) + throw("Bad signature") + } catch (err) { + res.send("Error:" + err) + return ; + } +``` + +हँडलरचा उर्वरित भाग एका लहान बदलाशिवाय, आपण पूर्वी `/loginSubmitted` हँडलरमध्ये जे केले आहे त्याच्या समतुल्य आहे. + +```typescript + const loginResponse = await idp.createLoginResponse( + . + . + . + { + email: req.params.account + "@bad.email.address" + } + ); +``` + +आमच्याकडे खरा ईमेल अ‍ॅड्रेस नाही (तो आम्हाला पुढील विभागात मिळेल), म्हणून आतासाठी आम्ही Ethereum अ‍ॅड्रेस परत करतो आणि तो ईमेल अ‍ॅड्रेस नाही असे स्पष्टपणे चिन्हांकित करतो. + +```typescript +// IdP endpoint for login requests +idpRouter.post(`/login`, + async (req, res) => { + try { + // Workaround because I couldn't get parseLoginRequest to work. + // const loginRequest = await idp.parseLoginRequest(sp, 'post', req) + const samlRequest = xmlParser.parse(Buffer.from(req.body.SAMLRequest, 'base64').toString('utf-8')) + res.send(getSignaturePage(samlRequest["samlp:AuthnRequest"]["@_ID"])) + } catch (err) { + console.error('Error processing SAML response:', err); + res.status(400).send('SAML authentication failed'); + } + } +) +``` + +`getLoginPage` ऐवजी, आता पायरी 3 हँडलरमध्ये `getSignaturePage` वापरा. + +## ईमेल अ‍ॅड्रेस मिळवणे + +पुढील पायरी ईमेल अ‍ॅड्रेस मिळवणे आहे, जो सर्व्हिस प्रोव्हायडरने मागितलेला ओळखकर्ता आहे. ते करण्यासाठी, आम्ही [Ethereum Attestation Service (EAS)](https://attest.org/) वापरतो. + +अटेस्टेशन्स मिळवण्याचा सर्वात सोपा मार्ग म्हणजे [GraphQL API](https://docs.attest.org/docs/developer-tools/api) वापरणे. आम्ही ही क्वेरी वापरतो: + +``` +query GetAttestationsByRecipient { + attestations( + where: { + recipient: { equals: "${getAddress(ethAddr)}" } + schemaId: { equals: "0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977" } + } + take: 1 + ) { + data + id + attester + } +} +``` + +या [`schemaId`](https://optimism.easscan.org/schema/view/0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977) मध्ये फक्त एक ई-मेल अ‍ॅड्रेस समाविष्ट आहे. ही क्वेरी या स्कीमाच्या अटेस्टेशन्ससाठी विचारते. अटेस्टेशनच्या विषयाला `recipient` म्हणतात. तो नेहमी एक Ethereum अ‍ॅड्रेस असतो. + +चेतावणी: आपण येथे अटेस्टेशन्स मिळवत असलेल्या पद्धतीत दोन सुरक्षा समस्या आहेत. + +- आपण API एंडपॉईंट, `https://optimism.easscan.org/graphql` वर जात आहोत, जो एक सेंट्रलाइज्ड घटक आहे. आपण `id` अ‍ॅट्रिब्यूट मिळवू शकतो आणि नंतर अटेस्टेशन वास्तविक आहे की नाही हे तपासण्यासाठी ऑनचेन तपासणी करू शकतो, परंतु API एंडपॉईंट अजूनही अटेस्टेशन्सबद्दल न सांगता सेन्सॉर करू शकतो. + + ही समस्या सोडवणे अशक्य नाही, आपण स्वतःचा GraphQL एंडपॉईंट चालवू शकतो आणि चेन लॉगमधून अटेस्टेशन्स मिळवू शकतो, परंतु ते आमच्या उद्देशांसाठी जास्त आहे. + +- आपण अटेस्टॉरच्या ओळखीकडे पाहत नाही. कोणीही आम्हाला खोटी माहिती देऊ शकतो. वास्तविक जगातील अंमलबजावणीमध्ये आमच्याकडे विश्वासार्ह अटेस्टॉरचा एक सेट असेल आणि आम्ही फक्त त्यांच्या अटेस्टेशन्स पाहू. + +हे कृतीत पाहण्यासाठी, विद्यमान IdP आणि SP थांबवा आणि हे कमांड चालवा: + +```sh +git checkout email-address +pnpm install +pnpm start +``` + +नंतर तुमचा ई-मेल अ‍ॅड्रेस द्या. तुमच्याकडे ते करण्याचे दोन मार्ग आहेत: + +- प्रायव्हेट की वापरून वॉलेट आयात करा आणि चाचणीसाठी `0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` ही प्रायव्हेट की वापरा. + +- तुमच्या स्वतःच्या ई-मेल अ‍ॅड्रेससाठी एक अटेस्टेशन जोडा: + + 1. [अटेस्टेशन एक्सप्लोररमधील स्कीमावर](https://optimism.easscan.org/schema/view/0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977) ब्राउझ करा. + + 2. **स्कीमासह अटेस्ट करा** वर क्लिक करा. + + 3. प्राप्तकर्ता म्हणून तुमचा Ethereum अ‍ॅड्रेस, ईमेल अ‍ॅड्रेस म्हणून तुमचा ई-मेल अ‍ॅड्रेस टाका आणि **ऑनचेन** निवडा. नंतर **अटेस्टेशन तयार करा** वर क्लिक करा. + + 4. तुमच्या वॉलेटमध्ये व्यवहाराला मंजुरी द्या. गॅससाठी पैसे देण्यासाठी तुम्हाला [Optimism Blockchain](https://app.optimism.io/bridge/deposit) वर काही ETH ची आवश्यकता असेल. + +एकतर, तुम्ही हे केल्यानंतर [http://localhost:3000](http://localhost:3000) वर ब्राउझ करा आणि निर्देशांचे पालन करा. जर तुम्ही चाचणीची प्रायव्हेट की आयात केली असेल, तर तुम्हाला मिळणारा ई-मेल `test_addr_0@example.com` आहे. जर तुम्ही तुमचा स्वतःचा अ‍ॅड्रेस वापरला असेल, तर तो तुम्ही अटेस्ट केलेला असावा. + +### तपशीलवार स्पष्टीकरण + +![Ethereum अ‍ॅड्रेसवरून ई-मेल मिळवणे](./fig-06-saml-sig-n-email.png) + +नवीन पायऱ्या GraphQL कम्युनिकेशन, पायऱ्या 5.6 आणि 5.7 आहेत. + +पुन्हा, येथे `idp.mts` चे बदललेले भाग आहेत. + +```typescript +import { GraphQLClient } from 'graphql-request' +import { SchemaEncoder } from '@ethereum-attestation-service/eas-sdk' +``` + +आपल्याला आवश्यक असलेल्या लायब्ररी आयात करा. + +```typescript +const graphqlEndpointUrl = "https://optimism.easscan.org/graphql" +``` + +[प्रत्येक ब्लॉकचेनसाठी एक वेगळा एंडपॉईंट](https://docs.attest.org/docs/developer-tools/api) आहे. + +```typescript +const graphqlClient = new GraphQLClient(graphqlEndpointUrl, { fetch }) +``` + +एक नवीन `GraphQLClient` क्लायंट तयार करा जो आपण एंडपॉईंटवर क्वेरी करण्यासाठी वापरू शकतो. + +```typescript +const graphqlSchema = 'string emailAddress' +const graphqlEncoder = new SchemaEncoder(graphqlSchema) +``` + +GraphQL आपल्याला फक्त बाइट्ससह एक अपारदर्शक डेटा ऑब्जेक्ट देतो. ते समजून घेण्यासाठी आपल्याला स्कीमाची आवश्यकता आहे. + +```typescript +const ethereumAddressToEmail = async ethAddr => { +``` + +Ethereum अ‍ॅड्रेसवरून ई-मेल अ‍ॅड्रेसवर जाण्यासाठी एक फंक्शन. + +```typescript + const query = ` + query GetAttestationsByRecipient { +``` + +ही एक GraphQL क्वेरी आहे. + +```typescript + attestations( +``` + +आम्ही अटेस्टेशन्स शोधत आहोत. + +```typescript + where: { + recipient: { equals: "${getAddress(ethAddr)}" } + schemaId: { equals: "0xfa2eff59a916e3cc3246f9aec5e0ca00874ae9d09e4678e5016006f07622f977" } + } +``` + +आम्हाला हवी असलेली अटेस्टेशन्स आमच्या स्कीमामध्ये आहेत, जिथे प्राप्तकर्ता `getAddress(ethAddr)` आहे. [`getAddress`](https://viem.sh/docs/utilities/getAddress#getaddress) फंक्शन खात्री करते की आमच्या अ‍ॅड्रेसमध्ये योग्य [चेकसम](https://github.com/ethereum/ercs/blob/master/ERCS/erc-55.md) आहे. हे आवश्यक आहे कारण GraphQL केस-सिग्निफिकेंट आहे. "0xBAD060A7", "0xBad060A7", आणि "0xbad060a7" ही वेगवेगळी मूल्ये आहेत. + +```typescript + take: 1 +``` + +आपल्याला कितीही अटेस्टेशन्स सापडले तरी, आम्हाला फक्त पहिलेच हवे आहे. + +```typescript + ) { + data + id + attester + } + }` +``` + +आम्हाला मिळवायचे असलेले फिल्ड्स. + +- `attester`: ज्या अ‍ॅड्रेसने अटेस्टेशन सादर केले. सामान्यतः याचा वापर अटेस्टेशनवर विश्वास ठेवायचा की नाही हे ठरवण्यासाठी केला जातो. +- `id`: अटेस्टेशन आयडी. तुम्ही GraphQL क्वेरीमधून मिळालेली माहिती योग्य आहे की नाही हे तपासण्यासाठी [अटेस्टेशन ऑनचेन वाचण्यासाठी](https://optimism.blockscout.com/address/0x4200000000000000000000000000000000000021?tab=read_proxy&source_address=0x4E0275Ea5a89e7a3c1B58411379D1a0eDdc5b088#0xa3112a64) हे मूल्य वापरू शकता. +- `data`: स्कीमा डेटा (या प्रकरणात, ई-मेल अ‍ॅड्रेस). + +```typescript + const queryResult = await graphqlClient.request(query) + + if (queryResult.attestations.length == 0) + return "no_address@available.is" +``` + +जर अटेस्टेशन नसेल, तर एक असे मूल्य परत करा जे स्पष्टपणे चुकीचे आहे, परंतु सर्व्हिस प्रोव्हायडरला ते वैध वाटेल. + +```typescript + const attestationDataFields = graphqlEncoder.decodeData(queryResult.attestations[0].data) + return attestationDataFields[0].value.value +} +``` + +जर मूल्य असेल, तर डेटा डीकोड करण्यासाठी `decodeData` वापरा. आम्हाला ते प्रदान करत असलेला मेटाडेटा नको, फक्त मूल्यच हवे आहे. + +```typescript + const loginResponse = await idp.createLoginResponse( + sp, + { + . + . + . + }, + "post", + { + email: await ethereumAddressToEmail(req.params.account) + } + ); +``` + +ई-मेल अ‍ॅड्रेस मिळवण्यासाठी नवीन फंक्शन वापरा. + +## विकेंद्रीकरणाचे काय? + +या कॉन्फिगरेशनमध्ये वापरकर्ते स्वतःला दुसरे कोणीतरी असल्याचे भासवू शकत नाहीत, जोपर्यंत आपण Ethereum ते ई-मेल अ‍ॅड्रेस मॅपिंगसाठी विश्वासार्ह अटेस्टर्सवर अवलंबून आहोत. तथापि, आमचा ओळख प्रदाता अजूनही एक केंद्रीकृत घटक आहे. ज्याच्याकडे आयडेंटिटी प्रोव्हायडरची प्रायव्हेट की आहे तो सर्व्हिस प्रोव्हायडरला खोटी माहिती पाठवू शकतो. + +[मल्टी-पार्टी कम्प्युटेशन (MPC)](https://en.wikipedia.org/wiki/Secure_multi-party_computation) वापरून एक उपाय असू शकतो. मी भविष्यातील ट्युटोरियलमध्ये त्याबद्दल लिहिण्याची आशा करतो. + +## निष्कर्ष + +लॉग ऑन स्टँडर्डचा अवलंब, जसे की Ethereum सिग्नेचर, कोंबडी आणि अंड्याच्या समस्येला सामोरे जातो. सर्व्हिस प्रोव्हायडर शक्य तितक्या विस्तृत बाजारपेठेत आवाहन करू इच्छितात. वापरकर्ते त्यांच्या लॉग ऑन स्टँडर्डला सपोर्ट करण्याची चिंता न करता सेवांमध्ये प्रवेश करू इच्छितात. +अ‍ॅडॉप्टर्स तयार करणे, जसे की Ethereum IdP, आपल्याला या अडथळ्यावर मात करण्यास मदत करू शकते. + +[माझ्या कामाबद्दल अधिक माहितीसाठी येथे पहा](https://cryptodocguy.pro/). diff --git a/public/content/translations/mr/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md b/public/content/translations/mr/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md new file mode 100644 index 00000000000..30aa0f8a9a5 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/getting-started-with-ethereum-development-using-alchemy/index.md @@ -0,0 +1,156 @@ +--- +title: "Ethereum डेव्हलपमेंटसोबत सुरुवात करणे" +description: "हे Ethereum डेव्हलपमेंटची सुरुवात करण्यासाठी नवशिक्यांचे मार्गदर्शक आहे. आम्ही तुम्हाला API एंडपॉइंट तयार करण्यापासून, कमांड लाइन रिक्वेस्ट करण्यापर्यंत, ते तुमचे पहिले web3 स्क्रिप्ट लिहिण्यापर्यंत घेऊन जाऊ! ब्लॉकचेन डेव्हलपमेंट अनुभवाची आवश्यकता नाही!" +author: "Elan Halpern" +tags: + [ + "javascript", + "ethers.js", + "नोड्स", + "querying", + "alchemy" + ] +skill: beginner +lang: mr +published: 2020-10-30 +source: Medium +sourceUrl: https://medium.com/alchemy-api/getting-started-with-ethereum-development-using-alchemy-c3d6a45c567f +--- + +![Ethereum आणि Alchemy चे लोगो](./ethereum-alchemy.png) + +हे Ethereum डेव्हलपमेंटची सुरुवात करण्यासाठी नवशिक्यांचे मार्गदर्शक आहे. या ट्युटोरियलसाठी आम्ही [Alchemy](https://alchemyapi.io/) वापरणार आहोत, जे Maker, 0x, MyEtherWallet, Dharma आणि Kyber सह 70% आघाडीच्या ब्लॉकचेन ॲप्समधील लाखो वापरकर्त्यांना सामर्थ्य देणारे, अग्रगण्य ब्लॉकचेन डेव्हलपर प्लॅटफॉर्म आहे. Alchemy आम्हाला Ethereum चेनवर एका API एंडपॉइंटमध्ये प्रवेश देईल जेणेकरून आम्ही व्यवहार (transactions) वाचू आणि लिहू शकू. + +आम्ही तुम्हाला Alchemy वर साइन अप करण्यापासून ते तुमचे पहिले web3 स्क्रिप्ट लिहिण्यापर्यंत घेऊन जाऊ! ब्लॉकचेन डेव्हलपमेंट अनुभवाची आवश्यकता नाही! + +## १. मोफत Alchemy खात्यासाठी साइन अप करा {#sign-up-for-a-free-alchemy-account} + +Alchemy वर खाते तयार करणे सोपे आहे, [येथे विनामूल्य साइन अप करा](https://auth.alchemy.com/). + +## २. Alchemy ॲप तयार करा {#create-an-alchemy-app} + +Ethereum चेनशी संवाद साधण्यासाठी आणि Alchemy ची उत्पादने वापरण्यासाठी, तुमच्या रिक्वेस्ट प्रमाणित करण्याकरिता तुम्हाला एका API की ची आवश्यकता आहे. + +तुम्ही [डॅशबोर्डवरून API की तयार करू शकता](https://dashboard.alchemy.com/). नवीन की तयार करण्यासाठी, खाली दर्शविल्याप्रमाणे “ॲप तयार करा” (Create App) वर नेव्हिगेट करा: + +[_ShapeShift_](https://shapeshift.com/) _यांचे त्यांचा डॅशबोर्ड दाखवण्याची परवानगी दिल्याबद्दल विशेष आभार!_ + +![Alchemy डॅशबोर्ड](./alchemy-dashboard.png) + +तुमची नवीन की मिळवण्यासाठी “ॲप तयार करा” (Create App) अंतर्गत तपशील भरा. तुम्ही पूर्वी तयार केलेले ॲप्स आणि तुमच्या टीमने बनवलेले ॲप्स देखील येथे पाहू शकता. कोणत्याही ॲपसाठी विद्यमान की मिळवण्यासाठी “की पाहा” (View Key) वर क्लिक करा. + +![Alchemy सह ॲप तयार करा स्क्रीनशॉट](./create-app.png) + +तुम्ही “ॲप्स” (Apps) वर फिरवून आणि एक निवडून विद्यमान API की देखील मिळवू शकता. तुम्ही येथे “की पाहा” (View Key) करू शकता, तसेच विशिष्ट डोमेन व्हाइटलिस्ट करण्यासाठी, अनेक डेव्हलपर टूल्स पाहण्यासाठी, आणि ॲनालिटिक्स पाहण्यासाठी “ॲप संपादित करा” (Edit App) देखील वापरू शकता. + +![API की कशा मिळवायच्या हे वापरकर्त्याला दाखवणारी Gif](./pull-api-keys.gif) + +## ३. कमांड लाइनवरून रिक्वेस्ट करा {#make-a-request-from-the-command-line} + +JSON-RPC आणि curl वापरून Alchemy द्वारे Ethereum ब्लॉकचेनशी संवाद साधा. + +मॅन्युअल रिक्वेस्टसाठी, आम्ही `POST` रिक्वेस्टद्वारे `JSON-RPC` शी संवाद साधण्याची शिफारस करतो. फक्त `Content-Type: application/json` हेडर आणि तुमची क्वेरी `POST` बॉडी म्हणून खालील फील्डसह पास करा: + +- `jsonrpc`: JSON-RPC आवृत्ती—सध्या, फक्त `2.0` समर्थित आहे. +- `method`: ETH API पद्धत. [API संदर्भ पाहा.](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc) +- `params`: पद्धतीला पास करण्यासाठी पॅरामीटर्सची यादी. +- `id`: तुमच्या रिक्वेस्टचा ID. हे प्रतिसादाद्वारे परत केले जाईल जेणेकरून प्रतिसाद कोणत्या रिक्वेस्टचा आहे याचा तुम्ही मागोवा ठेवू शकाल. + +सध्याची गॅस किंमत मिळवण्यासाठी तुम्ही कमांड लाइनवरून चालवू शकता असे एक उदाहरण येथे आहे: + +```bash +curl https://eth-mainnet.alchemyapi.io/v2/demo \ +-X POST \ +-H "Content-Type: application/json" \ +-d '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":73}' +``` + +_**टीप:** [https://eth-mainnet.alchemyapi.io/v2/demo](https://eth-mainnet.alchemyapi.io/jsonrpc/demo) ला तुमच्या स्वतःच्या API की `https://eth-mainnet.alchemyapi.io/v2/**your-api-key` ने बदला._ + +**परिणाम:** + +```json +{ "id": 73,"jsonrpc": "2.0","result": "0x09184e72a000" // 10000000000000 } +``` + +## ४. तुमचा Web3 क्लायंट सेट अप करा {#set-up-your-web3-client} + +**तुमच्याकडे विद्यमान क्लायंट असल्यास,** तुमचा सध्याचा नोड प्रोव्हायडर URL तुमच्या API की सह Alchemy URL मध्ये बदला: `“https://eth-mainnet.alchemyapi.io/v2/your-api-key"` + +**_टीप:_** खालील स्क्रिप्ट्स **नोड संदर्भात** चालवणे किंवा **फाईलमध्ये सेव्ह करणे** आवश्यक आहे, कमांड लाइनवरून चालवू नये. तुमच्याकडे आधीपासून Node किंवा npm इंस्टॉल केलेले नसल्यास, मॅकसाठी हे द्रुत [सेट-अप मार्गदर्शक](https://app.gitbook.com/@alchemyapi/s/alchemy/guides/alchemy-for-macs) पाहा. + +अशा अनेक [Web3 लायब्ररीज](https://docs.alchemyapi.io/guides/getting-started#other-web3-libraries) आहेत ज्या तुम्ही Alchemy सह समाकलित करू शकता, तथापि, आम्ही [Alchemy Web3](https://docs.alchemy.com/reference/api-overview) वापरण्याची शिफारस करतो, जे web3.js साठी एक ड्रॉप-इन रिप्लेसमेंट आहे, आणि जे Alchemy सोबत अखंडपणे काम करण्यासाठी तयार आणि कॉन्फिगर केले आहे. हे स्वयंचलित पुन्हा प्रयत्न (automatic retries) आणि मजबूत WebSocket समर्थन यासारखे अनेक फायदे प्रदान करते. + +AlchemyWeb3.js इंस्टॉल करण्यासाठी, **तुमच्या प्रोजेक्ट डिरेक्टरीमध्ये नेव्हिगेट करा** आणि चालवा: + +**Yarn सह:** + +``` +yarn add @alch/alchemy-web3 +``` + +**NPM सह:** + +``` +npm install @alch/alchemy-web3 +``` + +Alchemy च्या नोड इन्फ्रास्ट्रक्चरशी संवाद साधण्यासाठी, NodeJS मध्ये चालवा किंवा हे जावास्क्रिप्ट फाईलमध्ये जोडा: + +```js +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3( + "https://eth-mainnet.alchemyapi.io/v2/your-api-key" +) +``` + +## ५. तुमची पहिली Web3 स्क्रिप्ट लिहा! {#write-your-first-web3-script} + +आता थोडे web3 प्रोग्रामिंग करून पाहण्यासाठी, आपण Ethereum मेननेटवरून नवीनतम ब्लॉक नंबर प्रिंट करणारी एक साधी स्क्रिप्ट लिहूया. + +**१.** **तुम्ही आधीच केले नसेल तर, तुमच्या टर्मिनलमध्ये एक नवीन प्रोजेक्ट डिरेक्टरी तयार करा आणि त्यात cd करा:** + +``` +mkdir web3-example +cd web3-example +``` + +**२.** **तुम्ही आधीच केली नसेल तर तुमच्या प्रोजेक्टमध्ये Alchemy web3 (किंवा कोणतीही web3) डिपेन्डन्सी इंस्टॉल करा:** + +``` +npm install @alch/alchemy-web3 +``` + +**३.** **`index.js` नावाची फाईल तयार करा आणि खालील सामग्री जोडा:** + +> तुम्ही शेवटी `demo` ला तुमच्या Alchemy HTTP API की ने बदलले पाहिजे. + +```js +async function main() { + const { createAlchemyWeb3 } = require("@alch/alchemy-web3") + const web3 = createAlchemyWeb3("https://eth-mainnet.alchemyapi.io/v2/demo") + const blockNumber = await web3.eth.getBlockNumber() + console.log("नवीनतम ब्लॉक नंबर आहे " + blockNumber) +} +main() +``` + +async गोष्टींशी अपरिचित आहात? ही [मीडियम पोस्ट](https://medium.com/better-programming/understanding-async-await-in-javascript-1d81bb079b2c) पाहा. + +\*\*4. **node वापरून ते तुमच्या टर्मिनलमध्ये चालवा** + +``` +node index.js +``` + +\*\*5. **तुम्हाला आता तुमच्या कन्सोलमध्ये नवीनतम ब्लॉक नंबर आउटपुट दिसेल!** + +``` +नवीनतम ब्लॉक नंबर आहे 11043912 +``` + +**व्वा!** अभिनंदन! **तुम्ही Alchemy वापरून तुमची पहिली web3 स्क्रिप्ट नुकतीच लिहिली आहे 🎉** + +पुढे काय करायचे याची खात्री नाही? आमच्या [हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट मार्गदर्शक](https://www.alchemy.com/docs/hello-world-smart-contract) मध्ये तुमचा पहिला स्मार्ट कॉन्ट्रॅक्ट तैनात (deploy) करून आणि काही solidity प्रोग्रामिंग करून पाहा, किंवा [डॅशबोर्ड डेमो ॲप](https://docs.alchemyapi.io/tutorials/demo-app) सह तुमचे डॅशबोर्ड ज्ञान तपासा! + +_[Alchemy सह विनामूल्य साइन अप करा](https://auth.alchemy.com/), आमचे [दस्तऐवजीकरण](https://www.alchemy.com/docs/) पाहा, आणि नवीनतम बातम्यांसाठी, आम्हाला [Twitter](https://twitter.com/AlchemyPlatform) वर फॉलो करा_. diff --git a/public/content/translations/mr/developers/tutorials/guide-to-smart-contract-security-tools/index.md b/public/content/translations/mr/developers/tutorials/guide-to-smart-contract-security-tools/index.md new file mode 100644 index 00000000000..075df7fff4b --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/guide-to-smart-contract-security-tools/index.md @@ -0,0 +1,102 @@ +--- +title: "स्मार्ट कॉन्ट्रॅक्ट सुरक्षा साधनांसाठी मार्गदर्शक" +description: "तीन वेगवेगळ्या चाचणी आणि प्रोग्राम विश्लेषण तंत्रांचे अवलोकन" +author: "Trailofbits" +lang: mr +tags: [ "सॉलिडिटी", "स्मार्ट कॉन्ट्रॅक्ट", "सुरक्षा" ] +skill: intermediate +published: 2020-09-07 +source: Building secure contracts +sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis +--- + +आम्ही तीन विशिष्ट चाचणी आणि प्रोग्राम विश्लेषण तंत्र वापरणार आहोत: + +- **[Slither](/developers/tutorials/how-to-use-slither-to-find-smart-contract-bugs/) सह स्थिर विश्लेषण.** प्रोग्रामचे सर्व मार्ग एकाच वेळी अंदाजित आणि विश्लेषित केले जातात, वेगवेगळ्या प्रोग्राम प्रस्तुतीकरणाद्वारे (उदा., कंट्रोल-फ्लो-ग्राफ) +- **[Echidna](/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/) सह फझिंग.** व्यवहारांच्या छद्म-यादृच्छिक निर्मितीसह कोड कार्यान्वित केला जातो. फझर दिलेल्या गुणधर्माचे उल्लंघन करण्यासाठी व्यवहारांचा क्रम शोधण्याचा प्रयत्न करेल. +- **[Manticore](/developers/tutorials/how-to-use-manticore-to-find-smart-contract-bugs/) सह प्रतीकात्मक अंमलबजावणी.** एक औपचारिक पडताळणी तंत्र, जे प्रत्येक अंमलबजावणी मार्गाला गणितीय सूत्रात अनुवादित करते, ज्यावर मर्यादा तपासल्या जाऊ शकतात. + +प्रत्येक तंत्राचे फायदे आणि तोटे आहेत, आणि ते [विशिष्ट प्रकरणांमध्ये](#determining-security-properties) उपयुक्त ठरेल: + +| तंत्र | टूल | वापर | वेग | चुकलेले बग्स | खोटे अलार्म | +| ---------------------- | --------- | -------------------------------- | ------ | ------------- | ----------- | +| स्थिर विश्लेषण | Slither | CLI आणि स्क्रिप्ट्स | सेकंद | मध्यम | कमी | +| फझिंग | Echidna | Solidity गुणधर्म | मिनिटे | कमी | काहीही नाही | +| प्रतीकात्मक अंमलबजावणी | Manticore | Solidity गुणधर्म आणि स्क्रिप्ट्स | तास | काहीही नाही\* | काहीही नाही | + +\* जर सर्व मार्ग टाइमआउटशिवाय शोधले गेले तर + +**Slither** काही सेकंदात कॉन्ट्रॅक्ट्सचे विश्लेषण करते, तथापि, स्थिर विश्लेषणामुळे खोटे अलार्म येऊ शकतात आणि ते जटिल तपासणीसाठी (उदा., अंकगणितीय तपासणी) कमी योग्य असेल. अंगभूत डिटेक्टरमध्ये पुश-बटण प्रवेशासाठी API द्वारे Slither चालवा किंवा वापरकर्ता-परिभाषित तपासणीसाठी API द्वारे चालवा. + +**Echidna** ला चालण्यासाठी काही मिनिटे लागतात आणि ते फक्त खरे सकारात्मक परिणाम देईल. Echidna वापरकर्त्याने प्रदान केलेले सुरक्षा गुणधर्म तपासते, जे Solidity मध्ये लिहिलेले आहेत. हे यादृच्छिक शोधावर आधारित असल्यामुळे बग्स चुकवू शकते. + +**Manticore** सर्वात "जड" विश्लेषण करते. Echidna प्रमाणेच, Manticore वापरकर्त्याने प्रदान केलेले गुणधर्म सत्यापित करते. त्याला चालण्यासाठी जास्त वेळ लागेल, पण ते एका गुणधर्माची वैधता सिद्ध करू शकते आणि खोटे अलार्म कळवणार नाही. + +## सुचवलेले कार्यप्रवाह {#suggested-workflow} + +आता कोणतेही सोपे बग्स नाहीत किंवा नंतर येणार नाहीत याची खात्री करण्यासाठी Slither च्या अंगभूत डिटेक्टरने सुरुवात करा. वारसा, व्हेरिएबल अवलंबित्व आणि संरचनात्मक समस्यांशी संबंधित गुणधर्म तपासण्यासाठी Slither वापरा. जसजसा कोडबेस वाढेल, तसतसे स्टेट मशीनचे अधिक जटिल गुणधर्म तपासण्यासाठी Echidna वापरा. Solidity कडून अनुपलब्ध संरक्षणांसाठी सानुकूल तपासणी विकसित करण्यासाठी Slither ला पुन्हा भेट द्या, जसे की फंक्शन ओव्हरराइड होण्यापासून संरक्षण. शेवटी, महत्त्वपूर्ण सुरक्षा गुणधर्मांची लक्ष्यित पडताळणी करण्यासाठी Manticore वापरा, उदा., अंकगणितीय ऑपरेशन्स. + +- सामान्य समस्या शोधण्यासाठी Slither चा CLI वापरा +- आपल्या कॉन्ट्रॅक्टच्या उच्च-स्तरीय सुरक्षा गुणधर्मांची चाचणी करण्यासाठी Echidna वापरा +- सानुकूल स्थिर तपासणी लिहिण्यासाठी Slither वापरा +- जेव्हा तुम्हाला महत्त्वपूर्ण सुरक्षा गुणधर्मांची सखोल खात्री हवी असेल तेव्हा Manticore वापरा + +**युनिट चाचण्यांवर एक टीप**. उच्च-गुणवत्तेचे सॉफ्टवेअर तयार करण्यासाठी युनिट चाचण्या आवश्यक आहेत. तथापि, ही तंत्रे सुरक्षा त्रुटी शोधण्यासाठी सर्वात योग्य नाहीत. ते सामान्यतः कोडच्या सकारात्मक वर्तनाची चाचणी करण्यासाठी वापरले जातात (म्हणजे, कोड सामान्य संदर्भात अपेक्षेप्रमाणे कार्य करतो), तर सुरक्षा त्रुटी विकसकांनी विचारात न घेतलेल्या एज केसेसमध्ये असतात. आमच्या डझनभर स्मार्ट कॉन्ट्रॅक्ट सुरक्षा पुनरावलोकनांच्या अभ्यासात, [युनिट टेस्ट कव्हरेजचा आमच्या क्लायंटच्या कोडमध्ये आढळलेल्या सुरक्षा त्रुटींच्या संख्येवर किंवा तीव्रतेवर कोणताही परिणाम झाला नाही](https://blog.trailofbits.com/2019/08/08/246-findings-from-our-smart-contract-audits-an-executive-summary/). + +## सुरक्षा गुणधर्म निश्चित करणे {#determining-security-properties} + +आपल्या कोडची प्रभावीपणे चाचणी आणि पडताळणी करण्यासाठी, आपण लक्ष देण्याची आवश्यकता असलेली क्षेत्रे ओळखली पाहिजेत. तुमची सुरक्षेवर खर्च होणारी संसाधने मर्यादित असल्याने, तुमच्या प्रयत्नांना अनुकूल करण्यासाठी तुमच्या कोडबेसमधील कमकुवत किंवा उच्च-मूल्य असलेल्या भागांची व्याप्ती करणे महत्त्वाचे आहे. थ्रेट मॉडेलिंग मदत करू शकते. पुनरावलोकन करण्याचा विचार करा: + +- [रॅपिड रिस्क असेसमेंट्स](https://infosec.mozilla.org/guidelines/risk/rapid_risk_assessment.html) (वेळ कमी असताना आमचा प्राधान्याचा दृष्टिकोन) +- [डेटा-सेंट्रिक सिस्टम थ्रेट मॉडेलिंगसाठी मार्गदर्शक](https://csrc.nist.gov/pubs/sp/800/154/ipd) (उर्फ NIST 800-154) +- [शोस्टॅक थ्रेट मॉडेलिंग](https://www.amazon.com/Threat-Modeling-Designing-Adam-Shostack/dp/1118809998) +- [STRIDE](https://wikipedia.org/wiki/STRIDE_\(security\)) / [DREAD](https://wikipedia.org/wiki/DREAD_\(risk_assessment_model\)) +- [PASTA](https://wikipedia.org/wiki/Threat_model#P.A.S.T.A.) +- [असर्शन्सचा वापर](https://blog.regehr.org/archives/1091) + +### घटक {#components} + +तुम्हाला काय तपासायचे आहे हे जाणून घेतल्याने तुम्हाला योग्य साधन निवडण्यातही मदत होईल. + +स्मार्ट कॉन्ट्रॅक्टसाठी वारंवार संबंधित असलेल्या व्यापक क्षेत्रांमध्ये यांचा समावेश आहे: + +- **स्टेट मशीन.** बहुतेक कॉन्ट्रॅक्ट्स स्टेट मशीन म्हणून सादर केले जाऊ शकतात. हे तपासण्याचा विचार करा की (१) कोणतीही अवैध स्थिती गाठली जाऊ शकत नाही, (२) जर एखादी स्थिती वैध असेल तर ती गाठली जाऊ शकते, आणि (३) कोणतीही स्थिती कॉन्ट्रॅक्टला अडकवत नाही. + + - स्टेट-मशीन स्पेसिफिकेशन्सची चाचणी घेण्यासाठी Echidna आणि Manticore ही पसंतीची साधने आहेत. + +- **प्रवेश नियंत्रणे.** जर तुमच्या सिस्टममध्ये विशेषाधिकार असलेले वापरकर्ते असतील (उदा., मालक, नियंत्रक, ...) तुम्ही हे सुनिश्चित केले पाहिजे की (१) प्रत्येक वापरकर्ता केवळ अधिकृत कृती करू शकतो आणि (२) कोणताही वापरकर्ता अधिक विशेषाधिकार असलेल्या वापरकर्त्याच्या कृतींना ब्लॉक करू शकत नाही. + + - Slither, Echidna आणि Manticore योग्य प्रवेश नियंत्रणे तपासू शकतात. उदाहरणार्थ, Slither हे तपासू शकते की केवळ व्हाइटलिस्ट केलेल्या फंक्शन्समध्ये onlyOwner मॉडिफायरची कमतरता आहे. Echidna आणि Manticore अधिक जटिल प्रवेश नियंत्रणासाठी उपयुक्त आहेत, जसे की कॉन्ट्रॅक्टने विशिष्ट स्थितीत पोहोचल्यास दिलेली परवानगी. + +- **अंकगणितीय ऑपरेशन्स.** अंकगणितीय ऑपरेशन्सची सुदृढता तपासणे महत्त्वाचे आहे. ओव्हरफ्लो/अंडरफ्लो टाळण्यासाठी सर्वत्र `SafeMath` वापरणे हे एक चांगले पाऊल आहे, तथापि, आपण तरीही इतर अंकगणितीय त्रुटींचा विचार केला पाहिजे, ज्यात राउंडिंग समस्या आणि कॉन्ट्रॅक्टला अडकवणाऱ्या त्रुटींचा समावेश आहे. + + - Manticore येथे सर्वोत्तम पर्याय आहे. जर अंकगणित SMT सॉल्व्हरच्या कार्यक्षेत्राबाहेर असेल तर Echidna वापरला जाऊ शकतो. + +- **वारसा अचूकता.** Solidity कॉन्ट्रॅक्ट्स मोठ्या प्रमाणावर एकाधिक वारसावर अवलंबून असतात. शॅडोइंग फंक्शनमध्ये `super` कॉल चुकणे आणि c3 लिनिअरायझेशन क्रमाचा चुकीचा अर्थ लावणे यासारख्या चुका सहजपणे येऊ शकतात. + + - या समस्या शोधण्याची खात्री करण्यासाठी Slither हे साधन आहे. + +- **बाह्य संवाद.** कॉन्ट्रॅक्ट्स एकमेकांशी संवाद साधतात, आणि काही बाह्य कॉन्ट्रॅक्ट्सवर विश्वास ठेवला जाऊ नये. उदाहरणार्थ, जर तुमचा कॉन्ट्रॅक्ट बाह्य ऑरेकल्सवर अवलंबून असेल, तर उपलब्ध ऑरेकल्सपैकी अर्धे जरी तडजोड केले गेले तरी तो सुरक्षित राहील का? + + - तुमच्या कॉन्ट्रॅक्ट्ससह बाह्य संवादांची चाचणी करण्यासाठी Manticore आणि Echidna सर्वोत्तम पर्याय आहेत. Manticore मध्ये बाह्य कॉन्ट्रॅक्ट्सना स्टब करण्यासाठी एक अंगभूत यंत्रणा आहे. + +- **मानक अनुरूपता.** Ethereum मानकांच्या (उदा., ERC20) डिझाइनमध्ये त्रुटींचा इतिहास आहे. तुम्ही ज्या मानकावर तयार करत आहात त्याच्या मर्यादांबद्दल जागरूक रहा. + - Slither, Echidna, आणि Manticore तुम्हाला दिलेल्या मानकापासून विचलन शोधण्यात मदत करतील. + +### साधन निवड चीटशीट {#tool-selection-cheatsheet} + +| घटक | साधने | उदाहरणे | +| ------------------ | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| स्टेट मशीन | Echidna, Manticore | | +| प्रवेश नियंत्रण | Slither, Echidna, Manticore | [Slither व्यायाम 2](https://github.com/crytic/slither/blob/7f54c8b948c34fb35e1d61adaa1bd568ca733253/docs/src/tutorials/exercise2.md), [Echidna व्यायाम 2](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/exercises/Exercise-2.md) | +| अंकगणितीय ऑपरेशन्स | Manticore, Echidna | [Echidna व्यायाम 1](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/exercises/Exercise-1.md), [Manticore व्यायाम 1 - 3](https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/manticore/exercises) | +| वारसा अचूकता | Slither | [Slither व्यायाम 1](https://github.com/crytic/slither/blob/7f54c8b948c34fb35e1d61adaa1bd568ca733253/docs/src/tutorials/exercise1.md) | +| बाह्य संवाद | Manticore, Echidna | | +| मानक अनुरूपता | Slither, Echidna, Manticore | [`slither-erc`](https://github.com/crytic/slither/wiki/ERC-Conformance) | + +तुमच्या ध्येयांनुसार इतर क्षेत्रांची तपासणी करणे आवश्यक असेल, परंतु लक्ष केंद्रित करण्याची ही स्थूल-दाणेदार क्षेत्रे कोणत्याही स्मार्ट कॉन्ट्रॅक्ट सिस्टमसाठी एक चांगली सुरुवात आहेत. + +आमच्या सार्वजनिक ऑडिटमध्ये सत्यापित किंवा चाचणी केलेल्या गुणधर्मांची उदाहरणे आहेत. वास्तविक-जगातील सुरक्षा गुणधर्मांचे पुनरावलोकन करण्यासाठी खालील अहवालांमधील `स्वयंचलित चाचणी आणि पडताळणी` विभाग वाचण्याचा विचार करा: + +- [0x](https://github.com/trailofbits/publications/blob/master/reviews/0x-protocol.pdf) +- [Balancer](https://github.com/trailofbits/publications/blob/master/reviews/BalancerCore.pdf) diff --git a/public/content/translations/mr/developers/tutorials/hello-world-smart-contract-fullstack/index.md b/public/content/translations/mr/developers/tutorials/hello-world-smart-contract-fullstack/index.md new file mode 100644 index 00000000000..70432814ee9 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/hello-world-smart-contract-fullstack/index.md @@ -0,0 +1,1540 @@ +--- +title: "नवशिक्यांसाठी हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट - फुलस्टॅक" +description: "Ethereum वर एक साधे स्मार्ट कॉन्ट्रॅक्ट लिहिण्यावर आणि उपयोजित करण्यावर एक प्रास्ताविक ट्युटोरियल." +author: "nstrike2" +tags: + [ + "सॉलिडिटी", + "hardhat", + "alchemy", + "स्मार्ट कॉन्ट्रॅक्ट", + "डिप्लॉयिंग", + "ब्लॉक एक्सप्लोरर", + "frontend", + "व्यवहार" + ] +skill: beginner +lang: mr +published: 2021-10-25 +--- + +तुम्ही ब्लॉकचेन डेव्हलपमेंटसाठी नवीन असाल आणि तुम्हाला कोठून सुरुवात करावी किंवा स्मार्ट कॉन्ट्रॅक्ट कसे तैनात करावे आणि त्यांच्याशी संवाद कसा साधावा हे माहित नसेल, तर हे मार्गदर्शक तुमच्यासाठी आहे. आम्ही [MetaMask](https://metamask.io), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org), आणि [Alchemy](https://alchemy.com/eth) वापरून Goerli टेस्ट नेटवर्कवर एक साधे, स्मार्ट कॉन्ट्रॅक्ट तयार करणे आणि तैनात करण्याच्या प्रक्रियेतून जाऊ. + +हे ट्युटोरियल पूर्ण करण्यासाठी तुम्हाला Alchemy खात्याची आवश्यकता असेल. [विनामूल्य खात्यासाठी साइन अप करा](https://www.alchemy.com/). + +तुम्हाला कोणत्याही क्षणी प्रश्न असल्यास, [Alchemy Discord](https://discord.gg/gWuC7zB) मध्ये संपर्क साधा! + +## भाग १ - Hardhat वापरून तुमचे स्मार्ट कॉन्ट्रॅक्ट तयार करा आणि तैनात करा {#part-1} + +### Ethereum नेटवर्कशी कनेक्ट करा {#connect-to-the-ethereum-network} + +Ethereum चेनला विनंत्या करण्याचे अनेक मार्ग आहेत. साधेपणासाठी, आम्ही Alchemy वर एक विनामूल्य खाते वापरू, जे एक ब्लॉकचेन डेव्हलपर प्लॅटफॉर्म आणि API आहे, जे आम्हाला स्वतः नोड न चालवता Ethereum चेनशी संवाद साधण्याची परवानगी देते. Alchemy मध्ये देखरेख आणि विश्लेषणासाठी डेव्हलपर टूल्स देखील आहेत; आम्ही या ट्युटोरियलमध्ये आमच्या स्मार्ट कॉन्ट्रॅक्ट तैनातीमध्ये काय चालले आहे हे समजून घेण्यासाठी त्यांचा फायदा घेऊ. + +### तुमचे ॲप आणि API की तयार करा {#create-your-app-and-api-key} + +एकदा तुम्ही Alchemy खाते तयार केल्यावर, तुम्ही ॲप तयार करून API की तयार करू शकता. यामुळे तुम्हाला Goerli टेस्टनेटवर विनंत्या करण्याची परवानगी मिळेल. तुम्ही टेस्टनेटशी परिचित नसल्यास, तुम्ही [नेटवर्क निवडण्याबाबत Alchemy चे मार्गदर्शक](https://www.alchemy.com/docs/choosing-a-web3-network) वाचू शकता. + +Alchemy डॅशबोर्डवर, नेव्हिगेशन बारमधील **ॲप्स** ड्रॉपडाउन शोधा आणि **ॲप तयार करा** वर क्लिक करा. + +![हॅलो वर्ल्ड ॲप तयार करा](./hello-world-create-app.png) + +तुमच्या ॲपला '_Hello World_' असे नाव द्या आणि एक लहान वर्णन लिहा. तुमचे पर्यावरण म्हणून **स्टेजिंग** आणि तुमचे नेटवर्क म्हणून **Goerli** निवडा. + +![ॲप व्ह्यू हॅलो वर्ल्ड तयार करा](./create-app-view-hello-world.png) + +_टीप: **Goerli** निवडण्याची खात्री करा, अन्यथा हे ट्युटोरियल कार्य करणार नाही._ + +**ॲप तयार करा** वर क्लिक करा. तुमचे ॲप खालील टेबलमध्ये दिसेल. + +### एक Ethereum खाते तयार करा {#create-an-ethereum-account} + +तुम्हाला व्यवहार पाठवण्यासाठी आणि प्राप्त करण्यासाठी Ethereum खात्याची आवश्यकता आहे. आम्ही MetaMask वापरू, जो ब्राउझरमधील एक व्हर्च्युअल वॉलेट आहे, जो वापरकर्त्यांना त्यांच्या Ethereum खात्याचा पत्ता व्यवस्थापित करू देतो. + +तुम्ही [येथे](https://metamask.io/download) विनामूल्य MetaMask खाते डाउनलोड आणि तयार करू शकता. तुम्ही खाते तयार करत असताना, किंवा तुमच्याकडे आधीपासूनच खाते असल्यास, वरच्या उजवीकडील “Goerli टेस्ट नेटवर्क” वर स्विच करण्याची खात्री करा (जेणेकरून आपण खऱ्या पैशांशी व्यवहार करत नाही आहोत). + +### पायरी ४: फॉसेटमधून इथर जोडा {#step-4-add-ether-from-a-faucet} + +तुमचे स्मार्ट कॉन्ट्रॅक्ट टेस्ट नेटवर्कवर तैनात करण्यासाठी, तुम्हाला काही बनावट ETH ची आवश्यकता असेल. Goerli नेटवर्कवर ETH मिळवण्यासाठी, Goerli फॉसेटवर जा आणि तुमच्या Goerli खात्याचा पत्ता प्रविष्ट करा. लक्षात ठेवा की Goerli फॉसेट अलीकडे थोडे अविश्वसनीय असू शकतात - प्रयत्न करण्यासाठी पर्यायांची सूची पाहण्यासाठी [टेस्ट नेटवर्क पृष्ठ](/developers/docs/networks/#goerli) पहा: + +_टीप: नेटवर्कमधील गर्दीमुळे, यास थोडा वेळ लागू शकतो._ +`` + +### पायरी 5: तुमची शिल्लक तपासा {#step-5-check-your-balance} + +तुमच्या वॉलेटमध्ये ETH आहे की नाही हे पुन्हा तपासण्यासाठी, चला [Alchemy च्या कंपोझर टूल](https://composer.alchemyapi.io/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D) वापरून [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) विनंती करूया. हे आमच्या वॉलेटमधील ETH ची रक्कम परत करेल. अधिक जाणून घेण्यासाठी [कंपोझर टूल कसे वापरावे यावरील Alchemy चे छोटे ट्युटोरियल](https://youtu.be/r6sjRxBZJuU) पहा. + +तुमचा MetaMask खात्याचा पत्ता इनपुट करा आणि **विनंती पाठवा** वर क्लिक करा. तुम्हाला खालील कोड स्निपेटसारखा प्रतिसाद दिसेल. + +```json +{ "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" } +``` + +> _टीप: हा निकाल ETH मध्ये नाही, तर wei मध्ये आहे. Wei चा वापर इथरच्या सर्वात लहान मूल्यांकनासाठी केला जातो._ + +हुश्श! आपले बनावट पैसे तिथे आहेत. + +### पायरी 6: आपला प्रकल्प सुरू करा {#step-6-initialize-our-project} + +प्रथम, आपल्याला आपल्या प्रकल्पासाठी एक फोल्डर तयार करण्याची आवश्यकता असेल. तुमच्या कमांड लाइनवर नेव्हिगेट करा आणि खालील इनपुट करा. + +``` +mkdir hello-world +cd hello-world +``` + +आता आपण आपल्या प्रोजेक्ट फोल्डरमध्ये आहोत, आपण प्रोजेक्ट सुरू करण्यासाठी `npm init` वापरू. + +> तुमच्याकडे अद्याप npm इंस्टॉल केलेले नसल्यास, [Node.js आणि npm इंस्टॉल करण्यासाठी या सूचनांचे](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm) पालन करा. + +या ट्युटोरियलच्या उद्देशासाठी, तुम्ही आरंभीकरणाच्या प्रश्नांची उत्तरे कशी देता याने काही फरक पडत नाही. संदर्भासाठी आम्ही ते कसे केले ते येथे आहे: + +``` +पॅकेजचे नाव: (hello-world) +आवृत्ती: (1.0.0) +वर्णन: हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट +एंट्री पॉइंट: (index.js) +चाचणी कमांड: +git रेपॉजिटरी: +कीवर्ड: +लेखक: +परवाना: (ISC) + +/Users/.../.../.../hello-world/package.json मध्ये लिहिणार आहात: + +{ + "name": "hello-world", + "version": "1.0.0", + "description": "हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} +``` + +package.json ला मंजूर करा आणि आपण पुढे जाण्यास तयार आहोत! + +### पायरी 7: Hardhat डाउनलोड करा {#step-7-download-hardhat} + +Hardhat हे तुमचे Ethereum सॉफ्टवेअर संकलित (compile), उपयोजित (deploy), चाचणी (test) आणि डीबग (debug) करण्यासाठी एक विकास वातावरण आहे. हे डेव्हलपर्सना थेट चेनवर उपयोजित करण्यापूर्वी स्थानिक पातळीवर स्मार्ट कॉन्ट्रॅक्ट्स आणि dApps तयार करताना मदत करते. + +आपल्या `hello-world` प्रोजेक्टमध्ये चालवा: + +``` +npm install --save-dev hardhat +``` + +[इन्स्टॉलेशन सूचनांविषयी](https://hardhat.org/getting-started/#overview) अधिक तपशीलांसाठी हे पेज पहा. + +### पायरी 8: Hardhat प्रकल्प तयार करा {#step-8-create-hardhat-project} + +आमच्या `hello-world` प्रकल्प फोल्डरमध्ये, चालवा: + +``` +npx hardhat +``` + +त्यानंतर तुम्हाला एक स्वागत संदेश आणि तुम्हाला काय करायचे आहे यासाठी पर्याय दिसेल. “create an empty hardhat.config.js” निवडा: + +``` +888 888 888 888 888 +888 888 888 888 888 +888 888 888 888 888 +8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 +888 888 "88b 888P" d88" 888 888 "88b "88b 888 +888 888 .d888888 888 888 888 888 888 .d888888 888 +888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. +888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 + +👷 Hardhat v2.0.11 मध्ये आपले स्वागत आहे 👷‍ + +तुम्ही काय करू इच्छिता? … +एक नमुना प्रकल्प तयार करा +❯ एक रिक्त hardhat.config.js तयार करा +बाहेर पडा +``` + +हे प्रकल्पात `hardhat.config.js` फाइल तयार करेल. आपण हे नंतर ट्युटोरियलमध्ये आपल्या प्रकल्पासाठी सेटअप निर्दिष्ट करण्यासाठी वापरू. + +### पायरी 9: प्रकल्प फोल्डर जोडा {#step-9-add-project-folders} + +प्रकल्प संघटित ठेवण्यासाठी, चला दोन नवीन फोल्डर तयार करूया. कमांड लाइनमध्ये, तुमच्या `hello-world` प्रकल्पाच्या रूट डिरेक्टरीमध्ये नेव्हिगेट करा आणि टाइप करा: + +``` +mkdir contracts +mkdir scripts +``` + +- `contracts/` मध्ये आपण आपली हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट कोड फाईल ठेवू +- `scripts/` मध्ये आपण आपले कॉन्ट्रॅक्ट उपयोजित करण्यासाठी आणि त्याच्याशी संवाद साधण्यासाठी स्क्रिप्ट्स ठेवू + +### पायरी 10: आमचे कॉन्ट्रॅक्ट लिहा {#step-10-write-our-contract} + +तुम्ही स्वतःला विचारत असाल की, आपण कोड कधी लिहिणार आहोत? वेळ झाली आहे! + +तुमच्या आवडत्या एडिटरमध्ये हॅलो-वर्ल्ड प्रकल्प उघडा. स्मार्ट कॉन्ट्रॅक्ट सामान्यतः Solidity मध्ये लिहिले जातात, जे आपण आपले स्मार्ट कॉन्ट्रॅक्ट लिहिण्यासाठी वापरू.‌ + +1. `contracts` फोल्डरवर नेव्हिगेट करा आणि `HelloWorld.sol` नावाची नवीन फाइल तयार करा +2. खाली एक नमुना हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट आहे जो आपण या ट्युटोरियलसाठी वापरणार आहोत. खालील मजकूर `HelloWorld.sol` फाइलमध्ये कॉपी करा. + +_टीप: हे कॉन्ट्रॅक्ट काय करते हे समजून घेण्यासाठी टिप्पण्या वाचण्याची खात्री करा._ + +``` +// सिमेंटिक व्हर्जनिंग वापरून, Solidity ची आवृत्ती निर्दिष्ट करते. +// अधिक जाणून घ्या: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +pragma solidity >=0.7.3; + +// `HelloWorld` नावाचे एक कॉन्ट्रॅक्ट परिभाषित करते. +// एक कॉन्ट्रॅक्ट म्हणजे फंक्शन्स आणि डेटा (त्याची स्थिती) यांचा संग्रह. एकदा तैनात झाल्यावर, एक कॉन्ट्रॅक्ट Ethereum ब्लॉकचेनवर एका विशिष्ट पत्त्यावर राहते. अधिक जाणून घ्या: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +contract HelloWorld { + + //जेव्हा अपडेट फंक्शन कॉल केले जाते तेव्हा उत्सर्जित होते + //स्मार्ट कॉन्ट्रॅक्ट इव्हेंट्स हे तुमच्या कॉन्ट्रॅक्टसाठी तुमच्या ॲपच्या फ्रंट-एंडला ब्लॉकचेनवर काहीतरी घडल्याचे कळवण्याचा एक मार्ग आहे, जे काही विशिष्ट इव्हेंट्ससाठी 'ऐकत' असू शकते आणि ते घडल्यावर कारवाई करू शकते. + event UpdatedMessages(string oldStr, string newStr); + + // `string` प्रकारचा `message` नावाचा एक स्टेट व्हेरिएबल घोषित करते. + // स्टेट व्हेरिएबल्स असे व्हेरिएबल्स आहेत ज्यांची मूल्ये कॉन्ट्रॅक्ट स्टोरेजमध्ये कायमस्वरूपी संग्रहित केली जातात. `public` कीवर्ड व्हेरिएबल्सला कॉन्ट्रॅक्टच्या बाहेरून प्रवेशयोग्य बनवतो आणि एक फंक्शन तयार करतो ज्याला इतर कॉन्ट्रॅक्ट्स किंवा क्लायंट मूल्यामध्ये प्रवेश करण्यासाठी कॉल करू शकतात. + string public message; + + // अनेक वर्ग-आधारित ऑब्जेक्ट-ओरिएंटेड भाषांप्रमाणे, कंस्ट्रक्टर एक विशेष फंक्शन आहे जे फक्त कॉन्ट्रॅक्ट निर्मितीवर कार्यान्वित होते. + // कंस्ट्रक्टरचा वापर कॉन्ट्रॅक्टचा डेटा सुरू करण्यासाठी केला जातो. अधिक जाणून घ्या:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + constructor(string memory initMessage) { + + // एक स्ट्रिंग युक्तिवाद `initMessage` स्वीकारते आणि कॉन्ट्रॅक्टच्या `message` स्टोरेज व्हेरिएबलमध्ये मूल्य सेट करते). + message = initMessage; + } + + // एक सार्वजनिक फंक्शन जे स्ट्रिंग युक्तिवाद स्वीकारते आणि `message` स्टोरेज व्हेरिएबल अपडेट करते. + function update(string memory newMessage) public { + string memory oldMsg = message; + message = newMessage; + emit UpdatedMessages(oldMsg, newMessage); + } +} +``` + +हे एक मूलभूत स्मार्ट कॉन्ट्रॅक्ट आहे जे निर्मितीच्या वेळी एक संदेश संग्रहित करते. `update` फंक्शनला कॉल करून ते अपडेट केले जाऊ शकते. + +### पायरी 11: MetaMask आणि Alchemy ला तुमच्या प्रकल्पाशी कनेक्ट करा {#step-11-connect-metamask-alchemy-to-your-project} + +आपण MetaMask वॉलेट, Alchemy खाते तयार केले आहे आणि आपले स्मार्ट कॉन्ट्रॅक्ट लिहिले आहे, आता या तिन्हीना जोडण्याची वेळ आली आहे. + +तुमच्या वॉलेटमधून पाठवलेल्या प्रत्येक व्यवहारासाठी तुमच्या युनिक खाजगी की वापरून स्वाक्षरी आवश्यक असते. आमच्या प्रोग्रामला ही परवानगी देण्यासाठी, आम्ही आमची खाजगी की एका पर्यावरण फाइलमध्ये सुरक्षितपणे संग्रहित करू शकतो. आम्ही येथे Alchemy साठी एक API की देखील संग्रहित करू. + +> व्यवहार पाठवण्याबद्दल अधिक जाणून घेण्यासाठी, वेब3 वापरून व्यवहार पाठवण्यावरील [हे ट्युटोरियल](https://www.alchemy.com/docs/hello-world-smart-contract#step-11-connect-metamask--alchemy-to-your-project) पहा. + +प्रथम, तुमच्या प्रोजेक्ट डिरेक्टरीमध्ये dotenv पॅकेज इंस्टॉल करा: + +``` +npm install dotenv --save +``` + +मग, प्रकल्पाच्या रूट डिरेक्टरीमध्ये `.env` फाइल तयार करा. तुमची MetaMask खाजगी की आणि HTTP Alchemy API URL त्यात जोडा. + +तुमच्या पर्यावरण फाइलचे नाव `.env` असणे आवश्यक आहे अन्यथा ती पर्यावरण फाइल म्हणून ओळखली जाणार नाही. + +त्याला `process.env` किंवा `.env-custom` किंवा दुसरे काहीही नाव देऊ नका. + +- तुमची खाजगी की निर्यात करण्यासाठी [या सूचनांचे](https://metamask.zendesk.com/hc/en-us/articles/360015289632-How-to-Export-an-Account-Private-Key) पालन करा +- HTTP Alchemy API URL मिळवण्यासाठी खाली पहा + +![](./get-alchemy-api-key.gif) + +तुमचे `.env` असे दिसले पाहिजे: + +``` +API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key" +PRIVATE_KEY = "your-metamask-private-key" +``` + +हे प्रत्यक्षात आपल्या कोडशी जोडण्यासाठी, आपण या व्हेरिएबल्सचा संदर्भ आपल्या `hardhat.config.js` फाईलमध्ये पायरी १३ वर देऊ. + +### पायरी १२: Ethers.js इंस्टॉल करा {#step-12-install-ethersjs} + +Ethers.js ही एक लायब्ररी आहे जी अधिक वापरकर्ता-अनुकूल पद्धतींसह [मानक JSON-RPC पद्धती](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc) रॅप करून Ethereum शी संवाद साधणे आणि विनंत्या करणे सोपे करते. + +Hardhat आम्हाला अतिरिक्त टूलिंग आणि विस्तारित कार्यक्षमतेसाठी [प्लगइन्स](https://hardhat.org/plugins/) समाकलित करण्याची परवानगी देतो. आम्ही कॉन्ट्रॅक्ट उपयोजनासाठी [Ethers प्लगइन](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers) चा फायदा घेऊ. + +आपल्या प्रोजेक्ट डिरेक्टरीमध्ये टाइप करा: + +```bash +npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0" +``` + +### पायरी 13: hardhat.config.js अपडेट करा {#step-13-update-hardhat-configjs} + +आतापर्यंत आपण अनेक डिपेंडेंसी आणि प्लगइन जोडले आहेत, आता आपल्याला `hardhat.config.js` अद्यतनित करण्याची आवश्यकता आहे जेणेकरून आपल्या प्रोजेक्टला त्या सर्वांबद्दल माहिती मिळेल. + +तुमचे `hardhat.config.js` याप्रमाणे दिसण्यासाठी अद्यतनित करा: + +```javascript +/** + * @type import('hardhat/config').HardhatUserConfig + */ + +require("dotenv").config() +require("@nomiclabs/hardhat-ethers") + +const { API_URL, PRIVATE_KEY } = process.env + +module.exports = { + solidity: "0.7.3", + defaultNetwork: "goerli", + networks: { + hardhat: {}, + goerli: { + url: API_URL, + accounts: [`0x${PRIVATE_KEY}`], + }, + }, +} +``` + +### पायरी 14: आमचे कॉन्ट्रॅक्ट कंपाईल करा {#step-14-compile-our-contract} + +आतापर्यंत सर्व काही कार्यरत आहे याची खात्री करण्यासाठी, चला आमचा कॉन्ट्रॅक्ट संकलित करूया. `compile` कार्य हे बिल्ट-इन हार्डहॅट कार्यांपैकी एक आहे. + +कमांड लाइनमधून चालवा: + +```bash +npx hardhat compile +``` + +तुम्हाला `SPDX license identifier not provided in source file` बद्दल चेतावणी मिळू शकते, परंतु त्याबद्दल काळजी करण्याची गरज नाही — आशा आहे की इतर सर्व काही चांगले दिसेल! नसल्यास, तुम्ही नेहमी [Alchemy discord](https://discord.gg/u72VCg3) मध्ये संदेश पाठवू शकता. + +### पायरी 15: आमची उपयोजन स्क्रिप्ट लिहा {#step-15-write-our-deploy-script} + +आता आमचा कॉन्ट्रॅक्ट लिहिला आहे आणि आमची कॉन्फिगरेशन फाइल तयार आहे, आता आमच्या कॉन्ट्रॅक्टची उपयोजन स्क्रिप्ट लिहिण्याची वेळ आली आहे. + +`scripts/` फोल्डरवर नेव्हिगेट करा आणि `deploy.js` नावाची एक नवीन फाइल तयार करा, त्यात खालील सामग्री जोडा: + +```javascript +async function main() { + const HelloWorld = await ethers.getContractFactory("HelloWorld") + + // उपयोजन सुरू करा, एक प्रॉमिस परत करा जे कॉन्ट्रॅक्ट ऑब्जेक्टमध्ये निराकरण करते + const hello_world = await HelloWorld.deploy("Hello World!") + console.log("Contract deployed to address:", hello_world.address) +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error) + process.exit(1) + }) +``` + +Hardhat त्यांच्या [कॉन्ट्रॅक्ट्स ट्यूटोरियल](https://hardhat.org/tutorial/testing-contracts.html#writing-tests) मध्ये या प्रत्येक कोड ओळी काय करते हे आश्चर्यकारकपणे स्पष्ट करते, आम्ही त्यांचे स्पष्टीकरण येथे स्वीकारले आहे. + +```javascript +const HelloWorld = await ethers.getContractFactory("HelloWorld") +``` + +ethers.js मधील `ContractFactory` हे नवीन स्मार्ट कॉन्ट्रॅक्ट्स तैनात करण्यासाठी वापरले जाणारे एक ॲबस्ट्रॅक्शन आहे, म्हणून येथे `HelloWorld` हे आमच्या हॅलो वर्ल्ड कॉन्ट्रॅक्टच्या उदाहरणांसाठी एक [फॅक्टरी](https://en.wikipedia.org/wiki/Factory_\(object-oriented_programming\)) आहे. `hardhat-ethers` प्लगइन वापरताना `ContractFactory` आणि `Contract`, उदाहरणे डीफॉल्टनुसार पहिल्या स्वाक्षरीकर्त्याशी (मालक) जोडलेली असतात. + +```javascript +const hello_world = await HelloWorld.deploy() +``` + +`ContractFactory` वर `deploy()` कॉल केल्याने उपयोजन सुरू होईल आणि एक `Promise` परत येईल जो `Contract` ऑब्जेक्टमध्ये निराकरण करतो. हे ते ऑब्जेक्ट आहे ज्यामध्ये आमच्या प्रत्येक स्मार्ट कॉन्ट्रॅक्ट फंक्शनसाठी एक पद्धत आहे. + +### पायरी १६: आपले कॉन्ट्रॅक्ट उपयोजित करा {#step-16-deploy-our-contract} + +आम्ही अखेरीस आमचा स्मार्ट कॉन्ट्रॅक्ट उपयोजित करण्यास तयार आहोत! कमांड लाइनवर नेव्हिगेट करा आणि चालवा: + +```bash +npx hardhat run scripts/deploy.js --network goerli +``` + +तुम्हाला त्यानंतर असे काहीतरी दिसेल: + +```bash +Contract deployed to address: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570 +``` + +**कृपया हा पत्ता सेव्ह करा**. आम्ही ट्युटोरियलमध्ये नंतर याचा वापर करू. + +जर आपण [Goerli etherscan](https://goerli.etherscan.io) वर गेलो आणि आपला कॉन्ट्रॅक्ट पत्ता शोधला तर आपण पाहू शकू की ते यशस्वीरित्या तैनात केले गेले आहे. व्यवहार असा काहीतरी दिसेल: + +![](./etherscan-contract.png) + +`From` पत्ता तुमच्या MetaMask खात्याच्या पत्त्याशी जुळला पाहिजे आणि `To` पत्त्यावर **कॉन्ट्रॅक्ट निर्मिती** असे लिहिलेले असेल. जर आपण व्यवहारात क्लिक केले तर आपल्याला `To` फील्डमध्ये आपला कॉन्ट्रॅक्ट पत्ता दिसेल. + +![](./etherscan-transaction.png) + +अभिनंदन! तुम्ही नुकतेच Ethereum टेस्टनेटवर एक स्मार्ट कॉन्ट्रॅक्ट तैनात केले आहे. + +पडद्यामागे काय चालले आहे हे समजून घेण्यासाठी, चला आपल्या [Alchemy डॅशबोर्ड](https://dashboard.alchemy.com/explorer) मधील एक्सप्लोरर टॅबवर नेव्हिगेट करूया. तुमच्याकडे एकापेक्षा जास्त Alchemy ॲप्स असल्यास ॲपनुसार फिल्टर करा आणि **Hello World** निवडा. + +![](./hello-world-explorer.png) + +येथे तुम्हाला काही JSON-RPC पद्धती दिसतील ज्या Hardhat/Ethers ने `.deploy()` फंक्शन कॉल केल्यावर आपल्यासाठी पडद्यामागे बनवल्या आहेत. येथे दोन महत्त्वाच्या पद्धती आहेत [`eth_sendRawTransaction`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_sendrawtransaction), जे आमचे कॉन्ट्रॅक्ट Goerli चेनवर लिहिण्याची विनंती आहे, आणि [`eth_getTransactionByHash`](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_gettransactionbyhash), जे हॅश दिल्यावर आमच्या व्यवहाराबद्दल माहिती वाचण्याची विनंती आहे. व्यवहार पाठवण्याबद्दल अधिक जाणून घेण्यासाठी, [Web3 वापरून व्यवहार पाठवण्यावरील आमचे ट्युटोरियल](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) पहा. + +## भाग २: तुमच्या स्मार्ट कॉन्ट्रॅक्टशी संवाद साधा {#part-2-interact-with-your-smart-contract} + +आता आपण यशस्वीरित्या Goerli नेटवर्कवर एक स्मार्ट कॉन्ट्रॅक्ट तैनात केले आहे, चला त्याच्याशी संवाद कसा साधायचा हे शिकूया. + +### एक interact.js फाइल तयार करा {#create-a-interactjs-file} + +ही ती फाईल आहे जिथे आपण आपली संवाद स्क्रिप्ट लिहू. आम्ही Ethers.js लायब्ररी वापरणार आहोत जी तुम्ही आधी भाग १ मध्ये इन्स्टॉल केली होती. + +`scripts/` फोल्डरमध्ये, `interact.js` नावाची नवीन फाइल तयार करा आणि खालील कोड जोडा: + +```javascript +// interact.js + +const API_KEY = process.env.API_KEY +const PRIVATE_KEY = process.env.PRIVATE_KEY +const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS +``` + +### तुमची .env फाईल अपडेट करा {#update-your-env-file} + +आम्ही नवीन पर्यावरण व्हेरिएबल्स वापरणार आहोत, म्हणून आम्हाला त्यांना `.env` फाइलमध्ये परिभाषित करणे आवश्यक आहे जी [आम्ही आधी तयार केली होती](#step-11-connect-metamask-&-alchemy-to-your-project). + +आम्हाला आमच्या Alchemy `API_KEY` आणि `CONTRACT_ADDRESS` साठी एक परिभाषा जोडावी लागेल जिथे तुमचे स्मार्ट कॉन्ट्रॅक्ट तैनात केले होते. + +तुमची `.env` फाइल अशी काहीतरी दिसली पाहिजे: + +```bash +# .env + +API_URL = "https://eth-goerli.alchemyapi.io/v2/" +API_KEY = "" +PRIVATE_KEY = "" +CONTRACT_ADDRESS = "0x" +``` + +### तुमचे कॉन्ट्रॅक्ट ABI मिळवा {#grab-your-contract-ABI} + +आमचे कॉन्ट्रॅक्ट [ABI (ॲप्लिकेशन बायनरी इंटरफेस)](/glossary/#abi) आमच्या स्मार्ट कॉन्ट्रॅक्टशी संवाद साधण्यासाठी इंटरफेस आहे. Hardhat आपोआप एक ABI तयार करतो आणि ते `HelloWorld.json` मध्ये सेव्ह करतो. ABI वापरण्यासाठी, आम्हाला आमच्या `interact.js` फाइलमध्ये खालील कोडच्या ओळी जोडून सामग्री पार्स करणे आवश्यक आहे: + +```javascript +// interact.js +const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json") +``` + +जर तुम्हाला ABI पाहायचा असेल तर तुम्ही ते तुमच्या कन्सोलवर प्रिंट करू शकता: + +```javascript +console.log(JSON.stringify(contract.abi)) +``` + +तुमचे ABI कन्सोलवर छापलेले पाहण्यासाठी, तुमच्या टर्मिनलवर नेव्हिगेट करा आणि चालवा: + +```bash +npx hardhat run scripts/interact.js +``` + +### तुमच्या कॉन्ट्रॅक्टचे एक उदाहरण तयार करा {#create-an-instance-of-your-contract} + +आमच्या कॉन्ट्रॅक्टशी संवाद साधण्यासाठी, आम्हाला आमच्या कोडमध्ये एक कॉन्ट्रॅक्ट उदाहरण तयार करणे आवश्यक आहे. Ethers.js सह असे करण्यासाठी, आम्हाला तीन संकल्पनांवर काम करावे लागेल: + +1. प्रदाता - एक नोड प्रदाता जो तुम्हाला ब्लॉकचेनवर वाचण्याचा आणि लिहिण्याचा प्रवेश देतो +2. स्वाक्षरीकर्ता - एक Ethereum खाते जे व्यवहारांवर स्वाक्षरी करू शकते +3. कॉन्ट्रॅक्ट - ऑनचेन तैनात केलेल्या विशिष्ट कॉन्ट्रॅक्टचे प्रतिनिधित्व करणारा एक Ethers.js ऑब्जेक्ट + +आम्ही कॉन्ट्रॅक्टचे उदाहरण तयार करण्यासाठी मागील पायरीमधील कॉन्ट्रॅक्ट ABI वापरू: + +```javascript +// interact.js + +// प्रदाता +const alchemyProvider = new ethers.providers.AlchemyProvider( + (network = "goerli"), + API_KEY +) + +// स्वाक्षरीकर्ता +const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider) + +// कॉन्ट्रॅक्ट +const helloWorldContract = new ethers.Contract( + CONTRACT_ADDRESS, + contract.abi, + signer +) +``` + +[ethers.js माहिती](https://docs.ethers.io/v5/) मध्ये प्रदाते, स्वाक्षरीकर्ते आणि कॉन्ट्रॅक्ट्सबद्दल अधिक जाणून घ्या. + +### आरंभिक संदेश वाचा {#read-the-init-message} + +लक्षात आहे का आपण आपले कॉन्ट्रॅक्ट `initMessage = "Hello world!"` सह तैनात केले होते? आम्ही आता आमच्या स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला तो संदेश वाचणार आहोत आणि तो कन्सोलवर प्रिंट करणार आहोत. + +जावास्क्रिप्टमध्ये, नेटवर्कशी संवाद साधताना असिंक्रोनस फंक्शन्स वापरली जातात. असिंक्रोनस फंक्शन्सबद्दल अधिक जाणून घेण्यासाठी, [हा मीडियम लेख](https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff) वाचा. + +आमच्या स्मार्ट कॉन्ट्रॅक्टमधील `message` फंक्शनला कॉल करण्यासाठी आणि आरंभिक संदेश वाचण्यासाठी खालील कोड वापरा: + +```javascript +// interact.js + +// ... + +async function main() { + const message = await helloWorldContract.message() + console.log("The message is: " + message) +} +main() +``` + +टर्मिनलमध्ये `npx hardhat run scripts/interact.js` वापरून फाइल चालवल्यानंतर आम्हाला हा प्रतिसाद दिसला पाहिजे: + +``` +The message is: Hello world! +``` + +अभिनंदन! तुम्ही नुकतेच Ethereum ब्लॉकचेनवरून स्मार्ट कॉन्ट्रॅक्ट डेटा यशस्वीरित्या वाचला आहे, छान काम! + +### संदेश अपडेट करा {#update-the-message} + +फक्त संदेश वाचण्याऐवजी, आम्ही `update` फंक्शन वापरून आमच्या स्मार्ट कॉन्ट्रॅक्टमध्ये सेव्ह केलेला संदेश देखील अपडेट करू शकतो! छान आहे, नाही का? + +संदेश अपडेट करण्यासाठी, आम्ही थेट आमच्या इन्स्टँटिएटेड कॉन्ट्रॅक्ट ऑब्जेक्टवर `update` फंक्शन कॉल करू शकतो: + +```javascript +// interact.js + +// ... + +async function main() { + const message = await helloWorldContract.message() + console.log("The message is: " + message) + + console.log("Updating the message...") + const tx = await helloWorldContract.update("This is the new message.") + await tx.wait() +} +main() +``` + +लक्षात घ्या की ओळ ११ वर, आम्ही परत आलेल्या व्यवहार ऑब्जेक्टवर `.wait()` ला कॉल करतो. हे सुनिश्चित करते की आमची स्क्रिप्ट फंक्शनमधून बाहेर पडण्यापूर्वी ब्लॉकचेनवर व्यवहार माइन होण्याची वाट पाहते. जर `.wait()` कॉल समाविष्ट नसेल, तर स्क्रिप्टला कॉन्ट्रॅक्टमधील अपडेट केलेले `message` मूल्य दिसणार नाही. + +### नवीन संदेश वाचा {#read-the-new-message} + +अपडेट केलेले `message` मूल्य वाचण्यासाठी तुम्ही [मागील पायरी](#read-the-init-message) पुन्हा करू शकाल. थोडा वेळ घ्या आणि बघा की तुम्ही ते नवीन मूल्य प्रिंट करण्यासाठी आवश्यक बदल करू शकता का! + +तुम्हाला इशारा हवा असल्यास, तुमची `interact.js` फाइल या टप्प्यावर कशी दिसली पाहिजे ते येथे आहे: + +```javascript +// interact.js + +const API_KEY = process.env.API_KEY +const PRIVATE_KEY = process.env.PRIVATE_KEY +const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS + +const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json") + +// प्रदाता - Alchemy +const alchemyProvider = new ethers.providers.AlchemyProvider( + (network = "goerli"), + API_KEY +) + +// स्वाक्षरीकर्ता - तुम्ही +const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider) + +// कॉन्ट्रॅक्ट उदाहरण +const helloWorldContract = new ethers.Contract( + CONTRACT_ADDRESS, + contract.abi, + signer +) + +async function main() { + const message = await helloWorldContract.message() + console.log("The message is: " + message) + + console.log("Updating the message...") + const tx = await helloWorldContract.update("this is the new message") + await tx.wait() + + const newMessage = await helloWorldContract.message() + console.log("The new message is: " + newMessage) +} + +main() +``` + +आता फक्त स्क्रिप्ट चालवा आणि तुम्हाला जुना संदेश, अपडेटिंग स्थिती आणि नवीन संदेश तुमच्या टर्मिनलवर छापलेला दिसेल! + +`npx hardhat run scripts/interact.js --network goerli` + +``` +The message is: Hello World! +Updating the message... +The new message is: This is the new message. +``` + +ती स्क्रिप्ट चालवताना, तुम्हाला कदाचित लक्षात येईल की नवीन संदेश लोड होण्यापूर्वी `Updating the message...` पायरी लोड होण्यास थोडा वेळ लागतो. हे मायनिंग प्रक्रियेमुळे आहे; जर तुम्हाला व्यवहार माइन होत असताना त्यांचा मागोवा घेण्यास उत्सुकता असेल, तर व्यवहाराची स्थिती पाहण्यासाठी [Alchemy मेमपूल](https://dashboard.alchemyapi.io/mempool) ला भेट द्या. जर व्यवहार ड्रॉप झाला, तर [Goerli Etherscan](https://goerli.etherscan.io) तपासणे आणि तुमच्या व्यवहार हॅशसाठी शोधणे देखील उपयुक्त आहे. + +## भाग ३: तुमचे स्मार्ट कॉन्ट्रॅक्ट Etherscan वर प्रकाशित करा {#part-3-publish-your-smart-contract-to-etherscan} + +तुम्ही तुमच्या स्मार्ट कॉन्ट्रॅक्टला जीवदान देण्यासाठी सर्व कठोर परिश्रम केले; आता ते जगासोबत शेअर करण्याची वेळ आली आहे! + +Etherscan वर तुमचे स्मार्ट कॉन्ट्रॅक्ट सत्यापित करून, कोणीही तुमचा सोर्स कोड पाहू शकतो आणि तुमच्या स्मार्ट कॉन्ट्रॅक्टशी संवाद साधू शकतो. चला सुरू करूया! + +### पायरी १: तुमच्या Etherscan खात्यावर एक API की तयार करा {#step-1-generate-an-api-key-on-your-etherscan-account} + +तुम्ही जे स्मार्ट कॉन्ट्रॅक्ट प्रकाशित करण्याचा प्रयत्न करत आहात त्याचे तुम्ही मालक आहात हे सत्यापित करण्यासाठी Etherscan API की आवश्यक आहे. + +तुमच्याकडे आधीपासून Etherscan खाते नसल्यास, [खात्यासाठी साइन अप करा](https://etherscan.io/register). + +एकदा लॉग इन केल्यावर, नेव्हिगेशन बारमध्ये तुमचे वापरकर्तानाव शोधा, त्यावर होव्हर करा आणि **माझे प्रोफाइल** बटण निवडा. + +तुमच्या प्रोफाइल पेजवर, तुम्हाला एक साइड नेव्हिगेशन बार दिसेल. साइड नेव्हिगेशन बारमधून, **API की** निवडा. पुढे, नवीन API की तयार करण्यासाठी "जोडा" बटण दाबा, तुमच्या ॲपला **hello-world** नाव द्या आणि **नवीन API की तयार करा** बटण दाबा. + +तुमची नवीन API की API की टेबलमध्ये दिसेल. API की तुमच्या क्लिपबोर्डवर कॉपी करा. + +पुढे, आम्हाला आमच्या `.env` फाइलमध्ये Etherscan API की जोडण्याची आवश्यकता आहे. + +ते जोडल्यानंतर, तुमची `.env` फाइल अशी दिसेल: + +```javascript +API_URL = "https://eth-goerli.alchemyapi.io/v2/your-api-key" +PUBLIC_KEY = "your-public-account-address" +PRIVATE_KEY = "your-private-account-address" +CONTRACT_ADDRESS = "your-contract-address" +ETHERSCAN_API_KEY = "your-etherscan-key" +``` + +### Hardhat-तैनात स्मार्ट कॉन्ट्रॅक्ट {#hardhat-deployed-smart-contracts} + +#### hardhat-etherscan इन्स्टॉल करा {#install-hardhat-etherscan} + +Hardhat वापरून तुमचे कॉन्ट्रॅक्ट Etherscan वर प्रकाशित करणे सोपे आहे. सुरुवात करण्यासाठी तुम्हाला प्रथम `hardhat-etherscan` प्लगइन इन्स्टॉल करावे लागेल. `hardhat-etherscan` आपोआप स्मार्ट कॉन्ट्रॅक्टचा सोर्स कोड आणि ABI Etherscan वर सत्यापित करेल. हे जोडण्यासाठी, `hello-world` डिरेक्टरीमध्ये चालवा: + +```text +npm install --save-dev @nomiclabs/hardhat-etherscan +``` + +एकदा इन्स्टॉल झाल्यावर, तुमच्या `hardhat.config.js` च्या शीर्षस्थानी खालील विधान समाविष्ट करा, आणि Etherscan कॉन्फिग पर्याय जोडा: + +```javascript +// hardhat.config.js + +require("dotenv").config() +require("@nomiclabs/hardhat-ethers") +require("@nomiclabs/hardhat-etherscan") + +const { API_URL, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env + +module.exports = { + solidity: "0.7.3", + defaultNetwork: "goerli", + networks: { + hardhat: {}, + goerli: { + url: API_URL, + accounts: [`0x${PRIVATE_KEY}`], + }, + }, + etherscan: { + // Etherscan साठी तुमची API की + // https://etherscan.io/ वर एक मिळवा + apiKey: ETHERSCAN_API_KEY, + }, +} +``` + +#### Etherscan वर तुमचे स्मार्ट कॉन्ट्रॅक्ट सत्यापित करा {#verify-your-smart-contract-on-etherscan} + +सर्व फायली सेव्ह झाल्या आहेत आणि सर्व `.env` व्हेरिएबल्स योग्यरित्या कॉन्फिगर केले आहेत याची खात्री करा. + +`verify` टास्क चालवा, कॉन्ट्रॅक्ट पत्ता आणि ज्या नेटवर्कवर ते तैनात आहे ते पास करा: + +```text +npx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS 'Hello World!' +``` + +खात्री करा की `DEPLOYED_CONTRACT_ADDRESS` हे Goerli टेस्ट नेटवर्कवर तुमच्या तैनात केलेल्या स्मार्ट कॉन्ट्रॅक्टचा पत्ता आहे. तसेच, अंतिम युक्तिवाद (`'Hello World!'`) हा भाग १ मधील [तैनाती पायरी दरम्यान](#write-our-deploy-script) वापरलेल्या समान स्ट्रिंग मूल्याचा असावा. + +जर सर्व काही ठीक झाले, तर तुम्हाला तुमच्या टर्मिनलमध्ये खालील संदेश दिसेल: + +```text +Successfully submitted source code for contract +contracts/HelloWorld.sol:HelloWorld at 0xdeployed-contract-address +for verification on Etherscan. Waiting for verification result... + + +Successfully verified contract HelloWorld on Etherscan. +https://goerli.etherscan.io/address/#contracts +``` + +अभिनंदन! तुमचा स्मार्ट कॉन्ट्रॅक्ट कोड Etherscan वर आहे! + +### Etherscan वर तुमचे स्मार्ट कॉन्ट्रॅक्ट तपासा! {#check-out-your-smart-contract-on-etherscan} + +जेव्हा तुम्ही तुमच्या टर्मिनलमध्ये दिलेल्या लिंकवर नेव्हिगेट करता, तेव्हा तुम्हाला तुमचा स्मार्ट कॉन्ट्रॅक्ट कोड आणि ABI Etherscan वर प्रकाशित केलेला दिसेल! + +**व्वा - तुम्ही ते केले चॅम्प! आता कोणीही तुमच्या स्मार्ट कॉन्ट्रॅक्टला कॉल किंवा लिहू शकतो! तुम्ही पुढे काय तयार करता हे पाहण्यासाठी आम्ही उत्सुक आहोत!** + +## भाग ४ - तुमचे स्मार्ट कॉन्ट्रॅक्ट फ्रंटएंडसह एकत्रित करणे {#part-4-integrating-your-smart-contract-with-the-frontend} + +या ट्युटोरियलच्या अखेरीस, तुम्हाला कळेल की कसे: + +- तुमच्या डॅपला MetaMask वॉलेट कनेक्ट करा +- [Alchemy Web3](https://docs.alchemy.com/alchemy/documentation/alchemy-web3) API वापरून तुमच्या स्मार्ट कॉन्ट्रॅक्टमधून डेटा वाचा +- MetaMask वापरून Ethereum व्यवहारांवर स्वाक्षरी करा + +या डॅपसाठी, आम्ही आमच्या फ्रंटएंड फ्रेमवर्क म्हणून [React](https://react.dev/) वापरणार आहोत; तथापि, हे लक्षात घेणे महत्त्वाचे आहे की आम्ही त्याच्या मूलभूत गोष्टींचे विश्लेषण करण्यात जास्त वेळ घालवणार नाही, कारण आम्ही मुख्यतः आमच्या प्रकल्पात Web3 कार्यक्षमता आणण्यावर लक्ष केंद्रित करणार आहोत. + +एक पूर्वअट म्हणून, तुम्हाला React चे नवशिक्या-स्तराचे ज्ञान असले पाहिजे. नसल्यास, आम्ही अधिकृत [React चा परिचय ट्युटोरियल](https://react.dev/learn) पूर्ण करण्याची शिफारस करतो. + +### स्टार्टर फाइल्स क्लोन करा {#clone-the-starter-files} + +प्रथम, या प्रकल्पासाठी स्टार्टर फायली मिळवण्यासाठी [hello-world-part-four GitHub रेपॉजिटरी](https://github.com/alchemyplatform/hello-world-part-four-tutorial) वर जा आणि ही रेपॉजिटरी तुमच्या स्थानिक मशीनवर क्लोन करा. + +क्लोन केलेली रेपॉजिटरी स्थानिकरित्या उघडा. लक्षात घ्या की त्यात दोन फोल्डर आहेत: `starter-files` आणि `completed`. + +- `starter-files`- **आम्ही या डिरेक्टरीमध्ये काम करणार आहोत**, आम्ही UI ला तुमच्या Ethereum वॉलेटशी आणि आम्ही [भाग ३](#part-3) मध्ये Etherscan वर प्रकाशित केलेल्या स्मार्ट कॉन्ट्रॅक्टशी कनेक्ट करू. +- `completed` मध्ये संपूर्ण पूर्ण ट्युटोरियल आहे आणि तुम्ही अडकल्यास केवळ संदर्भ म्हणून वापरले पाहिजे. + +पुढे, तुमची `starter-files` ची प्रत तुमच्या आवडत्या कोड एडिटरमध्ये उघडा आणि नंतर `src` फोल्डरमध्ये नेव्हिगेट करा. + +आपण लिहिणार असलेला सर्व कोड `src` फोल्डरखाली असेल. आमच्या प्रकल्पाला Web3 कार्यक्षमता देण्यासाठी आम्ही `HelloWorld.js` घटक आणि `util/interact.js` जावास्क्रिप्ट फायली संपादित करणार आहोत. + +### स्टार्टर फायली तपासा {#check-out-the-starter-files} + +आम्ही कोडिंग सुरू करण्यापूर्वी, चला स्टार्टर फायलींमध्ये आम्हाला काय प्रदान केले आहे ते पाहूया. + +#### तुमचा react प्रोजेक्ट चालू करा {#get-your-react-project-running} + +चला आपल्या ब्राउझरमध्ये React प्रोजेक्ट चालवून सुरुवात करूया. React चे सौंदर्य हे आहे की एकदा आपला प्रोजेक्ट आपल्या ब्राउझरमध्ये चालू झाला की, आपण केलेले कोणतेही बदल आपल्या ब्राउझरमध्ये थेट अपडेट केले जातील. + +प्रकल्प चालू करण्यासाठी, `starter-files` फोल्डरच्या रूट डिरेक्टरीवर नेव्हिगेट करा, आणि प्रकल्पाच्या अवलंबित्वे स्थापित करण्यासाठी तुमच्या टर्मिनलमध्ये `npm install` चालवा: + +```bash +cd starter-files +npm install +``` + +एकदा ते इन्स्टॉल झाल्यावर, तुमच्या टर्मिनलमध्ये `npm start` चालवा: + +```bash +npm start +``` + +असे केल्याने तुमच्या ब्राउझरमध्ये [http://localhost:3000/](http://localhost:3000/) उघडले पाहिजे, जिथे तुम्हाला आमच्या प्रकल्पासाठी फ्रंटएंड दिसेल. त्यात एक फील्ड (तुमच्या स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला संदेश अपडेट करण्यासाठी एक जागा), एक "वॉलेट कनेक्ट करा" बटण आणि एक "अपडेट करा" बटण असले पाहिजे. + +तुम्ही कोणतेही बटण क्लिक करण्याचा प्रयत्न केल्यास, तुम्हाला लक्षात येईल की ते कार्य करत नाहीत—कारण आम्हाला अजूनही त्यांची कार्यक्षमता प्रोग्राम करायची आहे. + +#### `HelloWorld.js` घटक {#the-helloworld-js-component} + +चला आमच्या एडिटरमधील `src` फोल्डरमध्ये परत जाऊया आणि `HelloWorld.js` फाइल उघडूया. या फाईलमधील सर्व काही समजून घेणे खूप महत्त्वाचे आहे, कारण हा प्राथमिक React घटक आहे ज्यावर आपण काम करणार आहोत. + +या फाइलच्या शीर्षस्थानी, तुम्हाला दिसेल की आमच्याकडे अनेक आयात विधाने आहेत जी आमचा प्रकल्प चालू करण्यासाठी आवश्यक आहेत, ज्यात React लायब्ररी, useEffect आणि useState हुक्स, `./util/interact.js` मधील काही आयटम (आम्ही त्यांना लवकरच अधिक तपशीलवार वर्णन करू!) आणि Alchemy लोगो समाविष्ट आहेत. + +```javascript +// HelloWorld.js + +import React from "react" +import { useEffect, useState } from "react" +import { + helloWorldContract, + connectWallet, + updateMessage, + loadCurrentMessage, + getCurrentWalletConnected, +} from "./util/interact.js" + +import alchemylogo from "./alchemylogo.svg" +``` + +पुढे, आमच्याकडे आमचे स्टेट व्हेरिएबल्स आहेत जे आम्ही विशिष्ट इव्हेंटनंतर अपडेट करू. + +```javascript +// HelloWorld.js + +//स्टेट व्हेरिएबल्स +const [walletAddress, setWallet] = useState("") +const [status, setStatus] = useState("") +const [message, setMessage] = useState("नेटवर्कशी कोणतेही कनेक्शन नाही.") +const [newMessage, setNewMessage] = useState("") +``` + +प्रत्येक व्हेरिएबल काय दर्शवते ते येथे आहे: + +- `walletAddress` - वापरकर्त्याचा वॉलेट ॲड्रेस साठवणारी एक स्ट्रिंग +- `status`- एक स्ट्रिंग जी वापरकर्त्याला डॅपशी कसे संवाद साधावा याबद्दल मार्गदर्शन करणारा उपयुक्त संदेश संग्रहित करते +- `message` - एक स्ट्रिंग जी स्मार्ट कॉन्ट्रॅक्टमधील सध्याचा संदेश संग्रहित करते +- `newMessage` - एक स्ट्रिंग जी स्मार्ट कॉन्ट्रॅक्टमध्ये लिहिला जाणारा नवीन संदेश संग्रहित करते + +स्टेट व्हेरिएबल्सनंतर, तुम्हाला पाच अंमलबजावणी न केलेली फंक्शन्स दिसतील: `useEffect`, `addSmartContractListener`, `addWalletListener`, `connectWalletPressed`, आणि `onUpdatePressed`. ते काय करतात ते आम्ही खाली स्पष्ट करू: + +```javascript +// HelloWorld.js + +//केवळ एकदाच कॉल केले जाते +useEffect(async () => { + //TODO: अंमलबजावणी करा +}, []) + +function addSmartContractListener() { + //TODO: अंमलबजावणी करा +} + +function addWalletListener() { + //TODO: अंमलबजावणी करा +} + +const connectWalletPressed = async () => { + //TODO: अंमलबजावणी करा +} + +const onUpdatePressed = async () => { + //TODO: अंमलबजावणी करा +} +``` + +- [`useEffect`](https://legacy.reactjs.org/docs/hooks-effect.html)- हा एक React हुक आहे जो तुमचा घटक प्रस्तुत झाल्यानंतर कॉल केला जातो. कारण त्यात एक रिकामा ॲरे `[]` प्रॉप पास केला आहे (ओळ ४ पहा), तो फक्त घटकाच्या _पहिल्या_ रेंडरवर कॉल केला जाईल. येथे आम्ही आमच्या स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला सध्याचा संदेश लोड करू, आमचे स्मार्ट कॉन्ट्रॅक्ट आणि वॉलेट श्रोत्यांना कॉल करू, आणि वॉलेट आधीच कनेक्ट केलेले आहे की नाही हे दर्शविण्यासाठी आमचे UI अपडेट करू. +- `addSmartContractListener`- हे फंक्शन एक श्रोता सेट करते जो आमच्या HelloWorld कॉन्ट्रॅक्टच्या `UpdatedMessages` इव्हेंटवर लक्ष ठेवेल आणि आमच्या स्मार्ट कॉन्ट्रॅक्टमधील संदेश बदलल्यावर आमचे UI अपडेट करेल. +- `addWalletListener`- हे फंक्शन एक श्रोता सेट करते जो वापरकर्त्याच्या MetaMask वॉलेटच्या स्थितीत बदल ओळखतो, जसे की वापरकर्ता त्यांचे वॉलेट डिस्कनेक्ट करतो किंवा पत्ते बदलतो. +- `connectWalletPressed`- हे फंक्शन वापरकर्त्याचे MetaMask वॉलेट आमच्या डॅपशी कनेक्ट करण्यासाठी कॉल केले जाईल. +- `onUpdatePressed` - हे फंक्शन तेव्हा कॉल केले जाईल जेव्हा वापरकर्त्याला स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला संदेश अपडेट करायचा असेल. + +या फाइलच्या शेवटी, आमच्याकडे आमच्या घटकाचा UI आहे. + +```javascript +// HelloWorld.js + +//आमच्या घटकाचे UI +return ( +
+ + + +

Current Message:

+

{message}

+ +

New Message:

+ +
+ setNewMessage(e.target.value)} + value={newMessage} + /> +

{status}

+ + +
+ +
+) +``` + +तुम्ही हा कोड काळजीपूर्वक स्कॅन केल्यास, तुम्हाला दिसेल की आम्ही आमच्या UI मध्ये आमचे विविध स्टेट व्हेरिएबल्स कुठे वापरतो: + +- ओळी ६-१२ वर, जर वापरकर्त्याचे वॉलेट कनेक्ट केलेले असेल (म्हणजे, `walletAddress.length > 0`), तर आम्ही "walletButton" आयडी असलेल्या बटणामध्ये वापरकर्त्याच्या `walletAddress` ची एक संक्षिप्त आवृत्ती प्रदर्शित करतो; अन्यथा ते फक्त "वॉलेट कनेक्ट करा" असे म्हणते. +- ओळ १७ वर, आम्ही स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला सध्याचा संदेश प्रदर्शित करतो, जो `message` स्ट्रिंगमध्ये कॅप्चर केला जातो. +- ओळी २३-२६ वर, टेक्स्ट फील्डमधील इनपुट बदलल्यावर आमचे `newMessage` स्टेट व्हेरिएबल अपडेट करण्यासाठी आम्ही [नियंत्रित घटक](https://legacy.reactjs.org/docs/forms.html#controlled-components) वापरतो. + +आमच्या स्टेट व्हेरिएबल्स व्यतिरिक्त, तुम्हाला दिसेल की `publishButton` आणि `walletButton` आयडी असलेली बटणे क्लिक केल्यावर अनुक्रमे `connectWalletPressed` आणि `onUpdatePressed` फंक्शन्स कॉल केली जातात. + +शेवटी, चला पाहूया की हा `HelloWorld.js` घटक कुठे जोडला आहे. + +तुम्ही `App.js` फाइलवर गेल्यास, जी React मधील मुख्य घटक आहे जी इतर सर्व घटकांसाठी कंटेनर म्हणून काम करते, तुम्हाला दिसेल की आमचा `HelloWorld.js` घटक ओळ ७ वर इंजेक्ट केला आहे. + +शेवटचे पण महत्त्वाचे, चला तुमच्यासाठी प्रदान केलेली आणखी एक फाइल पाहूया, `interact.js` फाइल. + +#### `interact.js` फाइल {#the-interact-js-file} + +कारण आम्हाला [M-V-C](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) पॅराडाइमचे पालन करायचे आहे, आम्हाला एक वेगळी फाइल हवी आहे ज्यात आमच्या डॅपच्या तर्कशास्त्र, डेटा आणि नियमांचे व्यवस्थापन करण्यासाठी आमची सर्व फंक्शन्स असतील, आणि नंतर ती फंक्शन्स आमच्या फ्रंटएंडवर (आमचा `HelloWorld.js` घटक) निर्यात करता येतील. + +👆🏽हाच आमच्या `interact.js` फाइलचा नेमका उद्देश आहे! + +तुमच्या `src` डिरेक्टरीमधील `util` फोल्डरवर नेव्हिगेट करा, आणि तुम्हाला दिसेल की आम्ही `interact.js` नावाची फाइल समाविष्ट केली आहे ज्यात आमची सर्व स्मार्ट कॉन्ट्रॅक्ट संवाद आणि वॉलेट फंक्शन्स आणि व्हेरिएबल्स असतील. + +```javascript +// interact.js + +//export const helloWorldContract; + +export const loadCurrentMessage = async () => {} + +export const connectWallet = async () => {} + +const getCurrentWalletConnected = async () => {} + +export const updateMessage = async (message) => {} +``` + +तुम्हाला फाइलच्या शीर्षस्थानी दिसेल की आम्ही `helloWorldContract` ऑब्जेक्टवर टिप्पणी केली आहे. नंतर या ट्युटोरियलमध्ये, आम्ही या ऑब्जेक्टवरील टिप्पणी काढून टाकू आणि या व्हेरिएबलमध्ये आमचे स्मार्ट कॉन्ट्रॅक्ट इन्स्टँटिएट करू, जे आम्ही नंतर आमच्या `HelloWorld.js` घटकामध्ये निर्यात करू. + +आमच्या `helloWorldContract` ऑब्जेक्टनंतरची चार अंमलबजावणी न केलेली फंक्शन्स खालीलप्रमाणे करतात: + +- `loadCurrentMessage` - हे फंक्शन स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला सध्याचा संदेश लोड करण्याच्या तर्कशास्त्राचे व्यवस्थापन करते. ते [Alchemy Web3 API](https://github.com/alchemyplatform/alchemy-web3) वापरून हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्टला _वाचण्याचा_ कॉल करेल. +- `connectWallet` - हे फंक्शन वापरकर्त्याचे MetaMask आमच्या डॅपशी कनेक्ट करेल. +- `getCurrentWalletConnected` - हे फंक्शन तपासेल की Ethereum खाते आधीपासूनच आमच्या डॅपशी पेज लोडवर कनेक्ट केलेले आहे की नाही आणि त्यानुसार आमचे UI अपडेट करेल. +- `updateMessage` - हे फंक्शन स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला संदेश अपडेट करेल. हे हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्टला _लिहिण्याचा_ कॉल करेल, त्यामुळे वापरकर्त्याच्या MetaMask वॉलेटला संदेश अपडेट करण्यासाठी Ethereum व्यवहारावर स्वाक्षरी करावी लागेल. + +आता आम्हाला समजले आहे की आम्ही कशावर काम करत आहोत, चला पाहूया की आमच्या स्मार्ट कॉन्ट्रॅक्टमधून कसे वाचायचे! + +### पायरी ३: तुमच्या स्मार्ट कॉन्ट्रॅक्टमधून वाचा {#step-3-read-from-your-smart-contract} + +तुमच्या स्मार्ट कॉन्ट्रॅक्टमधून वाचण्यासाठी, तुम्हाला यशस्वीरित्या सेट अप करावे लागेल: + +- Ethereum चेनशी एक API कनेक्शन +- तुमच्या स्मार्ट कॉन्ट्रॅक्टचे एक लोड केलेले उदाहरण +- तुमच्या स्मार्ट कॉन्ट्रॅक्ट फंक्शनला कॉल करण्यासाठी एक फंक्शन +- तुम्ही स्मार्ट कॉन्ट्रॅक्टमधून वाचत असलेल्या डेटामध्ये बदल झाल्यावर अपडेट्ससाठी पाहण्यासाठी एक श्रोता + +हे खूप पायऱ्या वाटू शकतात, पण काळजी करू नका! आम्ही तुम्हाला त्या प्रत्येक पायरीतून कसे जायचे हे टप्प्याटप्प्याने सांगू! :\) + +#### Ethereum चेनशी एक API कनेक्शन स्थापित करा {#establish-an-api-connection-to-the-ethereum-chain} + +तर लक्षात आहे का, या ट्युटोरियलच्या भाग २ मध्ये, आम्ही आमच्या स्मार्ट कॉन्ट्रॅक्टमधून वाचण्यासाठी आमची [Alchemy Web3 की वापरली होती](https://docs.alchemy.com/alchemy/tutorials/hello-world-smart-contract/interacting-with-a-smart-contract#step-1-install-web3-library)? तुमच्या डॅपमध्ये चेनवरून वाचण्यासाठी तुम्हाला Alchemy Web3 की ची देखील आवश्यकता असेल. + +तुमच्याकडे आधीपासून नसल्यास, प्रथम [Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) इन्स्टॉल करा, तुमच्या `starter-files` च्या रूट डिरेक्टरीवर नेव्हिगेट करून आणि तुमच्या टर्मिनलमध्ये खालील चालवून: + +```text +npm install @alch/alchemy-web3 +``` + +[Alchemy Web3](https://github.com/alchemyplatform/alchemy-web3) हे [Web3.js](https://docs.web3js.org/) च्या सभोवतालचे एक रॅपर आहे, जे एक वेब3 डेव्हलपर म्हणून तुमचे जीवन सोपे करण्यासाठी वर्धित API पद्धती आणि इतर महत्त्वपूर्ण फायदे प्रदान करते. हे कमीत कमी कॉन्फिगरेशन आवश्यक करण्यासाठी डिझाइन केलेले आहे जेणेकरून आपण आपल्या ॲपमध्ये लगेचच त्याचा वापर सुरू करू शकता! + +मग, तुमच्या प्रकल्प डिरेक्टरीमध्ये [dotenv](https://www.npmjs.com/package/dotenv) पॅकेज इन्स्टॉल करा, जेणेकरून आम्ही आमची API की मिळवल्यानंतर ती संग्रहित करण्यासाठी आमच्याकडे एक सुरक्षित जागा असेल. + +```text +npm install dotenv --save +``` + +आमच्या डॅपसाठी, **आम्ही आमची HTTP API की ऐवजी आमची Websockets API की वापरणार आहोत**, कारण ते आम्हाला एक श्रोता सेट करण्याची परवानगी देईल जो स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला संदेश बदलल्यावर ओळखतो. + +एकदा तुमच्याकडे तुमची API की आल्यावर, तुमच्या रूट डिरेक्टरीमध्ये `.env` फाइल तयार करा आणि त्यात तुमची Alchemy Websockets url जोडा. त्यानंतर, तुमची `.env` फाइल अशी दिसेल: + +```javascript +REACT_APP_ALCHEMY_KEY = wss://eth-goerli.ws.alchemyapi.io/v2/ +``` + +आता, आम्ही आमच्या डॅपमध्ये आमचा Alchemy Web3 एंडपॉइंट सेट करण्यासाठी तयार आहोत! चला आमच्या `util` फोल्डरमध्ये असलेल्या आमच्या `interact.js` फाइलवर परत जाऊया आणि फाइलच्या शीर्षस्थानी खालील कोड जोडूया: + +```javascript +// interact.js + +require("dotenv").config() +const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(alchemyKey) + +//export const helloWorldContract; +``` + +वर, आम्ही प्रथम आमच्या `.env` फाइलमधून Alchemy की आयात केली आणि नंतर आमचा Alchemy Web3 एंडपॉइंट स्थापित करण्यासाठी आमची `alchemyKey` `createAlchemyWeb3` ला पास केली. + +हा एंडपॉइंट तयार झाल्यावर, आमचे स्मार्ट कॉन्ट्रॅक्ट लोड करण्याची वेळ आली आहे! + +#### तुमचे हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट लोड करत आहे {#loading-your-hello-world-smart-contract} + +तुमचे हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट लोड करण्यासाठी, तुम्हाला त्याचा कॉन्ट्रॅक्ट पत्ता आणि ABI आवश्यक असेल, जे दोन्ही Etherscan वर आढळू शकतात जर तुम्ही [या ट्युटोरियलचा भाग ३ पूर्ण केला असेल.](/developers/tutorials/hello-world-smart-contract-fullstack/#part-3-publish-your-smart-contract-to-etherscan-part-3-publish-your-smart-contract-to-etherscan) + +#### Etherscan वरून तुमचे कॉन्ट्रॅक्ट ABI कसे मिळवायचे {#how-to-get-your-contract-abi-from-etherscan} + +तुम्ही या ट्युटोरियलचा भाग ३ वगळल्यास, तुम्ही [0x6f3f635A9762B47954229Ea479b4541eAF402A6A](https://goerli.etherscan.io/address/0x6f3f635a9762b47954229ea479b4541eaf402a6a#code) पत्त्यासह HelloWorld कॉन्ट्रॅक्ट वापरू शकता. त्याचे ABI [येथे](https://goerli.etherscan.io/address/0x6f3f635a9762b47954229ea479b4541eaf402a6a#code) आढळू शकते. + +एक कॉन्ट्रॅक्ट ABI हे निर्दिष्ट करण्यासाठी आवश्यक आहे की कॉन्ट्रॅक्ट कोणते फंक्शन कॉल करेल तसेच फंक्शन तुमच्या अपेक्षित स्वरूपात डेटा परत करेल याची खात्री करण्यासाठी. एकदा आम्ही आमचे कॉन्ट्रॅक्ट ABI कॉपी केल्यावर, चला ते तुमच्या `src` डिरेक्टरीमध्ये `contract-abi.json` नावाची JSON फाइल म्हणून सेव्ह करूया. + +तुमची contract-abi.json तुमच्या src फोल्डरमध्ये संग्रहित केली पाहिजे. + +आमच्या कॉन्ट्रॅक्ट पत्ता, ABI, आणि Alchemy Web3 एंडपॉइंटसह सज्ज, आम्ही आमच्या स्मार्ट कॉन्ट्रॅक्टचे एक उदाहरण लोड करण्यासाठी [कॉन्ट्रॅक्ट पद्धत](https://docs.web3js.org/api/web3-eth-contract/class/Contract) वापरू शकतो. तुमचे कॉन्ट्रॅक्ट ABI `interact.js` फाइलमध्ये आयात करा आणि तुमचा कॉन्ट्रॅक्ट पत्ता जोडा. + +```javascript +// interact.js + +const contractABI = require("../contract-abi.json") +const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A" +``` + +आम्ही आता अखेरीस आमच्या `helloWorldContract` व्हेरिएबलवरील टिप्पणी काढून टाकू शकतो, आणि आमचा AlchemyWeb3 एंडपॉइंट वापरून स्मार्ट कॉन्ट्रॅक्ट लोड करू शकतो: + +```javascript +// interact.js +export const helloWorldContract = new web3.eth.Contract( + contractABI, + contractAddress +) +``` + +रिकॅप करण्यासाठी, तुमच्या `interact.js` च्या पहिल्या १२ ओळी आता अशा दिसल्या पाहिजेत: + +```javascript +// interact.js + +require("dotenv").config() +const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(alchemyKey) + +const contractABI = require("../contract-abi.json") +const contractAddress = "0x6f3f635A9762B47954229Ea479b4541eAF402A6A" + +export const helloWorldContract = new web3.eth.Contract( + contractABI, + contractAddress +) +``` + +आता आमचे कॉन्ट्रॅक्ट लोड झाले आहे, आम्ही आमचे `loadCurrentMessage` फंक्शन अंमलात आणू शकतो! + +#### तुमच्या `interact.js` फाइलमध्ये `loadCurrentMessage` अंमलात आणणे {#implementing-loadCurrentMessage-in-your-interact-js-file} + +हे फंक्शन खूप सोपे आहे. आम्ही आमच्या कॉन्ट्रॅक्टमधून वाचण्यासाठी एक साधा असिंक वेब3 कॉल करणार आहोत. आमचे फंक्शन स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला संदेश परत करेल: + +तुमच्या `interact.js` फाइलमधील `loadCurrentMessage` खालीलप्रमाणे अपडेट करा: + +```javascript +// interact.js + +export const loadCurrentMessage = async () => { + const message = await helloWorldContract.methods.message().call() + return message +} +``` + +आम्हाला हा स्मार्ट कॉन्ट्रॅक्ट आमच्या UI मध्ये प्रदर्शित करायचा असल्याने, चला आमच्या `HelloWorld.js` घटकामधील `useEffect` फंक्शन खालीलप्रमाणे अपडेट करूया: + +```javascript +// HelloWorld.js + +//केवळ एकदाच कॉल केले जाते +useEffect(async () => { + const message = await loadCurrentMessage() + setMessage(message) +}, []) +``` + +लक्षात घ्या, आम्हाला आमचे `loadCurrentMessage` फक्त घटकाच्या पहिल्या रेंडर दरम्यान एकदाच कॉल करायचे आहे. स्मार्ट कॉन्ट्रॅक्टमधील संदेश बदलल्यानंतर UI आपोआप अपडेट करण्यासाठी आम्ही लवकरच `addSmartContractListener` अंमलात आणू. + +आमच्या श्रोत्यामध्ये जाण्यापूर्वी, चला पाहूया की आतापर्यंत आमच्याकडे काय आहे! तुमच्या `HelloWorld.js` आणि `interact.js` फायली सेव्ह करा, आणि नंतर [http://localhost:3000/](http://localhost:3000/) वर जा + +तुम्हाला दिसेल की सध्याचा संदेश आता "नेटवर्कशी कोणतेही कनेक्शन नाही" असे म्हणत नाही. त्याऐवजी ते स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला संदेश दर्शवते. छान! + +#### तुमचे UI आता स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला संदेश दर्शवला पाहिजे {#your-UI-should-now-reflect-the-message-stored-in-the-smart-contract} + +आता त्या श्रोत्याबद्दल बोलूया... + +#### `addSmartContractListener` अंमलात आणा {#implement-addsmartcontractlistener} + +जर तुम्ही या ट्युटोरियल मालिकेच्या [भाग १](https://docs.alchemy.com/alchemy/tutorials/hello-world-smart-contract#step-10-write-our-contract) मध्ये लिहिलेली `HelloWorld.sol` फाइल आठवत असाल, तर तुम्हाला आठवेल की `UpdatedMessages` नावाचा एक स्मार्ट कॉन्ट्रॅक्ट इव्हेंट आहे जो आमच्या स्मार्ट कॉन्ट्रॅक्टच्या `update` फंक्शनला कॉल केल्यानंतर उत्सर्जित होतो (ओळी ९ आणि २७ पहा): + +```javascript +// HelloWorld.sol + +// सिमेंटिक व्हर्जनिंग वापरून, Solidity ची आवृत्ती निर्दिष्ट करते. +// अधिक जाणून घ्या: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +pragma solidity ^0.7.3; + +// `HelloWorld` नावाचे एक कॉन्ट्रॅक्ट परिभाषित करते. +// एक कॉन्ट्रॅक्ट म्हणजे फंक्शन्स आणि डेटा (त्याची स्थिती) यांचा संग्रह. एकदा तैनात झाल्यावर, एक कॉन्ट्रॅक्ट Ethereum ब्लॉकचेनवर एका विशिष्ट पत्त्यावर राहते. अधिक जाणून घ्या: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +contract HelloWorld { + + //जेव्हा अपडेट फंक्शन कॉल केले जाते तेव्हा उत्सर्जित होते + //स्मार्ट कॉन्ट्रॅक्ट इव्हेंट्स हे तुमच्या कॉन्ट्रॅक्टसाठी तुमच्या ॲपच्या फ्रंट-एंडला ब्लॉकचेनवर काहीतरी घडल्याचे कळवण्याचा एक मार्ग आहे, जे काही विशिष्ट इव्हेंट्ससाठी 'ऐकत' असू शकते आणि ते घडल्यावर कारवाई करू शकते. + event UpdatedMessages(string oldStr, string newStr); + + // `string` प्रकारचा `message` नावाचा एक स्टेट व्हेरिएबल घोषित करते. + // स्टेट व्हेरिएबल्स असे व्हेरिएबल्स आहेत ज्यांची मूल्ये कॉन्ट्रॅक्ट स्टोरेजमध्ये कायमस्वरूपी संग्रहित केली जातात. `public` कीवर्ड व्हेरिएबल्सला कॉन्ट्रॅक्टच्या बाहेरून प्रवेशयोग्य बनवतो आणि एक फंक्शन तयार करतो ज्याला इतर कॉन्ट्रॅक्ट्स किंवा क्लायंट मूल्यामध्ये प्रवेश करण्यासाठी कॉल करू शकतात. + string public message; + + // अनेक वर्ग-आधारित ऑब्जेक्ट-ओरिएंटेड भाषांप्रमाणे, कंस्ट्रक्टर एक विशेष फंक्शन आहे जे फक्त कॉन्ट्रॅक्ट निर्मितीवर कार्यान्वित होते. + // कंस्ट्रक्टरचा वापर कॉन्ट्रॅक्टचा डेटा सुरू करण्यासाठी केला जातो. अधिक जाणून घ्या:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + constructor(string memory initMessage) { + + // एक स्ट्रिंग युक्तिवाद `initMessage` स्वीकारते आणि कॉन्ट्रॅक्टच्या `message` स्टोरेज व्हेरिएबलमध्ये मूल्य सेट करते). + message = initMessage; + } + + // एक सार्वजनिक फंक्शन जे स्ट्रिंग युक्तिवाद स्वीकारते आणि `message` स्टोरेज व्हेरिएबल अपडेट करते. + function update(string memory newMessage) public { + string memory oldMsg = message; + message = newMessage; + emit UpdatedMessages(oldMsg, newMessage); + } +} +``` + +स्मार्ट कॉन्ट्रॅक्ट इव्हेंट्स हे तुमच्या कॉन्ट्रॅक्टसाठी तुमच्या फ्रंट-एंड ॲप्लिकेशनला ब्लॉकचेनवर काहीतरी घडल्याचे (म्हणजे, एक _इव्हेंट_ होता) कळवण्याचा एक मार्ग आहे, जे विशिष्ट इव्हेंटसाठी 'ऐकत' असू शकते आणि ते घडल्यावर कारवाई करू शकते. + +`addSmartContractListener` फंक्शन विशेषतः आमच्या हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्टच्या `UpdatedMessages` इव्हेंटसाठी ऐकेल, आणि नवीन संदेश प्रदर्शित करण्यासाठी आमचे UI अपडेट करेल. + +`addSmartContractListener` खालीलप्रमाणे सुधारित करा: + +```javascript +// HelloWorld.js + +function addSmartContractListener() { + helloWorldContract.events.UpdatedMessages({}, (error, data) => { + if (error) { + setStatus("😥 " + error.message) + } else { + setMessage(data.returnValues[1]) + setNewMessage("") + setStatus("🎉 तुमचा संदेश अपडेट झाला आहे!") + } + }) +} +``` + +चला पाहूया की श्रोता इव्हेंट ओळखल्यावर काय होते: + +- इव्हेंट उत्सर्जित झाल्यावर त्रुटी आढळल्यास, ते आमच्या `status` स्टेट व्हेरिएबलद्वारे UI मध्ये दिसेल. +- अन्यथा, आम्ही परत आलेला `data` ऑब्जेक्ट वापरू. `data.returnValues` हा एक ॲरे आहे जो शून्यावर अनुक्रमित आहे जिथे ॲरेमधील पहिला घटक मागील संदेश आणि दुसरा घटक अपडेट केलेला संदेश संग्रहित करतो. एकत्रितपणे, यशस्वी इव्हेंटवर आम्ही आमची `message` स्ट्रिंग अपडेट केलेल्या संदेशावर सेट करू, `newMessage` स्ट्रिंग साफ करू, आणि आमच्या स्मार्ट कॉन्ट्रॅक्टवर नवीन संदेश प्रकाशित झाला आहे हे दर्शविण्यासाठी आमची `status` स्टेट व्हेरिएबल अपडेट करू. + +शेवटी, चला आमच्या `useEffect` फंक्शनमध्ये आमच्या श्रोत्याला कॉल करूया जेणेकरून ते `HelloWorld.js` घटकाच्या पहिल्या रेंडरवर सुरू होईल. एकत्रितपणे, तुमचे `useEffect` फंक्शन असे दिसले पाहिजे: + +```javascript +// HelloWorld.js + +useEffect(async () => { + const message = await loadCurrentMessage() + setMessage(message) + addSmartContractListener() +}, []) +``` + +आता आम्ही आमच्या स्मार्ट कॉन्ट्रॅक्टमधून वाचू शकतो, त्यावर कसे लिहायचे हे शोधणे छान होईल! तथापि, आमच्या डॅपवर लिहिण्यासाठी, आमच्याकडे प्रथम एक Ethereum वॉलेट कनेक्ट केलेले असणे आवश्यक आहे. + +तर, पुढे आम्ही आमचे Ethereum वॉलेट (MetaMask) सेट अप करू आणि नंतर ते आमच्या डॅपशी कनेक्ट करू! + +### पायरी ४: तुमचे Ethereum वॉलेट सेट करा {#step-4-set-up-your-ethereum-wallet} + +Ethereum चेनवर काहीही लिहिण्यासाठी, वापरकर्त्यांना त्यांच्या व्हर्च्युअल वॉलेटच्या खाजगी की वापरून व्यवहारांवर स्वाक्षरी करावी लागेल. या ट्युटोरियलसाठी, आम्ही [MetaMask](https://metamask.io/) वापरू, जो ब्राउझरमधील एक व्हर्च्युअल वॉलेट आहे जो तुमच्या Ethereum खात्याचा पत्ता व्यवस्थापित करण्यासाठी वापरला जातो, कारण तो अंतिम-वापरकर्त्यासाठी हे व्यवहार स्वाक्षरी करणे खूप सोपे करतो. + +तुम्हाला Ethereum वरील व्यवहार कसे कार्य करतात याबद्दल अधिक समजून घ्यायचे असल्यास, Ethereum फाउंडेशनचे [हे पेज](/developers/docs/transactions/) पहा. + +#### MetaMask डाउनलोड करा {#download-metamask} + +तुम्ही [येथे](https://metamask.io/download) विनामूल्य MetaMask खाते डाउनलोड आणि तयार करू शकता. तुम्ही खाते तयार करत असताना, किंवा तुमच्याकडे आधीपासूनच खाते असल्यास, वरच्या उजवीकडील “Goerli टेस्ट नेटवर्क” वर स्विच करण्याची खात्री करा (जेणेकरून आपण खऱ्या पैशांशी व्यवहार करत नाही आहोत). + +#### फॉसेटमधून इथर जोडा {#add-ether-from-a-faucet} + +Ethereum ब्लॉकचेनवर व्यवहारावर स्वाक्षरी करण्यासाठी, आम्हाला काही बनावट Eth ची आवश्यकता असेल. Eth मिळवण्यासाठी तुम्ही [FaucETH](https://fauceth.komputing.org) वर जाऊन तुमचा Goerli खात्याचा पत्ता प्रविष्ट करू शकता, “निधीची विनंती करा” वर क्लिक करा, नंतर ड्रॉपडाउनमध्ये “Ethereum टेस्टनेट Goerli” निवडा आणि शेवटी पुन्हा “निधीची विनंती करा” बटणावर क्लिक करा. त्यानंतर लगेचच तुम्हाला तुमच्या MetaMask खात्यात Eth दिसेल! + +#### तुमची शिल्लक तपासा {#check-your-balance} + +आमची शिल्लक आहे की नाही हे पुन्हा तपासण्यासाठी, चला [Alchemy’s composer tool](https://composer.alchemyapi.io/?composer_state=%7B%22network%22%3A0%2C%22methodName%22%3A%22eth_getBalance%22%2C%22paramValues%22%3A%5B%22%22%2C%22latest%22%5D%7D) वापरून एक [eth_getBalance](https://docs.alchemyapi.io/alchemy/documentation/alchemy-api-reference/json-rpc#eth_getbalance) विनंती करूया. हे आमच्या वॉलेटमधील Eth ची रक्कम परत करेल. तुम्ही तुमच्या MetaMask खात्याचा पत्ता इनपुट केल्यानंतर आणि “Send Request” वर क्लिक केल्यानंतर, तुम्हाला असा प्रतिसाद दिसेल: + +```text +{"jsonrpc": "2.0", "id": 0, "result": "0xde0b6b3a7640000"} +``` + +**सूचना:** हा निकाल eth मध्ये नसून wei मध्ये आहे. Wei हे इथरचे सर्वात लहान एकक म्हणून वापरले जाते. wei चे eth मध्ये रूपांतर: 1 eth = 10¹⁸ wei. म्हणून जर आपण 0xde0b6b3a7640000 ला दशांश मध्ये रूपांतरित केले तर आपल्याला 1\*10¹⁸ मिळते, जे 1 eth च्या बरोबर आहे. + +हुश्श! आपले बनावट पैसे तिथेच आहेत! 🤑 + +### पायरी ५: MetaMask ला तुमच्या UI शी कनेक्ट करा {#step-5-connect-metamask-to-your-UI} + +आता आपले MetaMask वॉलेट सेट झाले आहे, चला आपला dapp त्याच्याशी कनेक्ट करूया! + +#### `connectWallet` फंक्शन {#the-connectWallet-function} + +आमच्या `interact.js` फाइलमध्ये, चला `connectWallet` फंक्शन अंमलात आणूया, जे आम्ही नंतर आमच्या `HelloWorld.js` घटकामध्ये कॉल करू शकतो. + +चला `connectWallet` खालीलप्रमाणे सुधारित करूया: + +```javascript +// interact.js + +export const connectWallet = async () => { + if (window.ethereum) { + try { + const addressArray = await window.ethereum.request({ + method: "eth_requestAccounts", + }) + const obj = { + status: "👆🏽 वरील टेक्स्ट-फील्डमध्ये एक संदेश लिहा.", + address: addressArray[0], + } + return obj + } catch (err) { + return { + address: "", + status: "😥 " + err.message, + } + } + } else { + return { + address: "", + status: ( + +

+ {" "} + 🦊 + तुम्ही तुमच्या ब्राउझरमध्ये MetaMask, एक व्हर्च्युअल Ethereum वॉलेट, इंस्टॉल करणे आवश्यक आहे. + +

+
+ ), + } + } +} +``` + +तर या मोठ्या कोड ब्लॉकचा नेमका काय उपयोग आहे? + +बरं, प्रथम, ते तुमच्या ब्राउझरमध्ये `window.ethereum` सक्षम आहे की नाही हे तपासते. + +`window.ethereum` हे MetaMask आणि इतर वॉलेट प्रदात्यांद्वारे इंजेक्ट केलेले एक ग्लोबल API आहे जे वेबसाइट्सना वापरकर्त्यांच्या Ethereum खात्यांची विनंती करण्याची परवानगी देते. मंजूर झाल्यास, ते वापरकर्ता कनेक्ट केलेल्या ब्लॉकचेनमधून डेटा वाचू शकते, आणि वापरकर्त्याला संदेश आणि व्यवहारांवर स्वाक्षरी करण्याचे सुचवू शकते. अधिक माहितीसाठी [MetaMask डॉक्स](https://docs.metamask.io/guide/ethereum-provider.html#table-of-contents) तपासा! + +जर `window.ethereum` उपस्थित _नसेल_, तर याचा अर्थ MetaMask स्थापित नाही. यामुळे एक JSON ऑब्जेक्ट परत येतो, जिथे परत केलेला `address` एक रिकामा स्ट्रिंग असतो आणि `status` JSX ऑब्जेक्ट वापरकर्त्याला MetaMask स्थापित करणे आवश्यक असल्याचे सांगतो. + +आता जर `window.ethereum` उपस्थित _असेल_, तर गोष्टी मनोरंजक होतात. + +try/catch लूप वापरून, आम्ही [`window.ethereum.request({ method: "eth_requestAccounts" });`](https://docs.metamask.io/guide/rpc-api.html#eth-requestaccounts) कॉल करून MetaMask शी कनेक्ट करण्याचा प्रयत्न करू. हे फंक्शन कॉल केल्याने ब्राउझरमध्ये MetaMask उघडेल, जिथे वापरकर्त्याला त्यांचे वॉलेट तुमच्या dapp शी कनेक्ट करण्यास सांगितले जाईल. + +- जर वापरकर्त्याने कनेक्ट करणे निवडले, तर `method: "eth_requestAccounts"` एक ॲरे परत करेल ज्यात डॅपशी कनेक्ट केलेल्या वापरकर्त्याच्या सर्व खात्यांचे पत्ते असतील. एकूणच, आमचे `connectWallet` फंक्शन एक JSON ऑब्जेक्ट परत करेल ज्यात या ॲरेमधील _पहिला_ `address` (ओळ 9 पहा) आणि एक `status` संदेश असेल जो वापरकर्त्याला स्मार्ट कॉन्ट्रॅक्टला संदेश लिहिण्यास सांगेल. +- जर वापरकर्त्याने कनेक्शन नाकारले, तर JSON ऑब्जेक्टमध्ये परत केलेल्या `address` साठी एक रिकामा स्ट्रिंग आणि एक `status` संदेश असेल जो वापरकर्त्याने कनेक्शन नाकारले असल्याचे दर्शवेल. + +आता आम्ही हे `connectWallet` फंक्शन लिहिले आहे, पुढची पायरी म्हणजे ते आमच्या `HelloWorld.js` घटकामध्ये कॉल करणे. + +#### `connectWallet` फंक्शन तुमच्या `HelloWorld.js` UI घटकामध्ये जोडा {#add-the-connectWallet-function-to-your-HelloWorld-js-ui-component} + +`HelloWorld.js` मधील `connectWalletPressed` फंक्शनवर नेव्हिगेट करा, आणि ते खालीलप्रमाणे अपडेट करा: + +```javascript +// HelloWorld.js + +const connectWalletPressed = async () => { + const walletResponse = await connectWallet() + setStatus(walletResponse.status) + setWallet(walletResponse.address) +} +``` + +आमच्या `HelloWorld.js` घटकामधून `interact.js` फाइलमधून आमची बहुतेक कार्यक्षमता कशी दूर केली जाते हे लक्षात घ्या? हे असे आहे की आम्ही M-V-C पॅराडाइमचे पालन करतो! + +`connectWalletPressed` मध्ये, आम्ही फक्त आमच्या आयात केलेल्या `connectWallet` फंक्शनला एक await कॉल करतो आणि त्याच्या प्रतिसादाचा वापर करून, आम्ही आमचे `status` आणि `walletAddress` व्हेरिएबल्स त्यांच्या स्टेट हुक्सद्वारे अपडेट करतो. + +आता, चला दोन्ही फायली (`HelloWorld.js` आणि `interact.js`) सेव्ह करूया आणि आतापर्यंत आमच्या UI ची चाचणी घेऊया. + +तुमचा ब्राउझर [http://localhost:3000/](http://localhost:3000/) पेजवर उघडा, आणि पेजच्या वरच्या उजवीकडील "वॉलेट कनेक्ट करा" बटण दाबा. + +तुमच्याकडे MetaMask स्थापित असल्यास, तुम्हाला तुमचे वॉलेट तुमच्या dapp शी जोडण्यास सांगितले जाईल. कनेक्ट करण्याची आमंत्रणे स्वीकारा. + +तुम्हाला दिसेल की वॉलेट बटण आता तुमचा पत्ता कनेक्ट झाला आहे हे दर्शवते! व्वा 🔥 + +पुढे, पृष्ठ रिफ्रेश करण्याचा प्रयत्न करा... हे विचित्र आहे. आमचे वॉलेट बटण आम्हाला MetaMask कनेक्ट करण्यास सांगत आहे, जरी ते आधीच कनेक्ट केलेले असले तरी... + +तथापि, घाबरू नका! आम्ही ते सहजपणे सोडवू शकतो (समजले?) `getCurrentWalletConnected` अंमलात आणून, जे तपासेल की पत्ता आधीपासूनच आमच्या डॅपशी कनेक्ट केलेला आहे की नाही आणि त्यानुसार आमचे UI अपडेट करेल! + +#### `getCurrentWalletConnected` फंक्शन {#the-getcurrentwalletconnected-function} + +`interact.js` फाइलमधील तुमचे `getCurrentWalletConnected` फंक्शन खालीलप्रमाणे अपडेट करा: + +```javascript +// interact.js + +export const getCurrentWalletConnected = async () => { + if (window.ethereum) { + try { + const addressArray = await window.ethereum.request({ + method: "eth_accounts", + }) + if (addressArray.length > 0) { + return { + address: addressArray[0], + status: "👆🏽 वरील टेक्स्ट-फील्डमध्ये एक संदेश लिहा.", + } + } else { + return { + address: "", + status: "🦊 वरच्या उजव्या बटणाचा वापर करून MetaMask शी कनेक्ट करा.", + } + } + } catch (err) { + return { + address: "", + status: "😥 " + err.message, + } + } + } else { + return { + address: "", + status: ( + +

+ {" "} + 🦊 + तुम्ही तुमच्या ब्राउझरमध्ये MetaMask, एक व्हर्च्युअल Ethereum वॉलेट, इंस्टॉल करणे आवश्यक आहे. + +

+
+ ), + } + } +} +``` + +हा कोड आम्ही मागील पायरीमध्ये लिहिलेल्या `connectWallet` फंक्शनसारखाच _खूप_ आहे. + +मुख्य फरक असा आहे की `eth_requestAccounts` या पद्धतीला कॉल करण्याऐवजी, जे वापरकर्त्याला त्यांचे वॉलेट कनेक्ट करण्यासाठी MetaMask उघडते, येथे आपण `eth_accounts` ही पद्धत कॉल करतो, जी सध्या आपल्या dapp शी कनेक्ट केलेल्या MetaMask ॲड्रेसची एक ॲरे परत करते. + +हे फंक्शन कृतीत पाहण्यासाठी, चला ते आमच्या `HelloWorld.js` घटकाच्या `useEffect` फंक्शनमध्ये कॉल करूया: + +```javascript +// HelloWorld.js + +useEffect(async () => { + const message = await loadCurrentMessage() + setMessage(message) + addSmartContractListener() + + const { address, status } = await getCurrentWalletConnected() + setWallet(address) + setStatus(status) +}, []) +``` + +लक्षात घ्या, आम्ही आमच्या `getCurrentWalletConnected` च्या कॉलच्या प्रतिसादाचा वापर आमचे `walletAddress` आणि `status` स्टेट व्हेरिएबल्स अपडेट करण्यासाठी करतो. + +आता तुम्ही हा कोड जोडला आहे, चला आमचे ब्राउझर विंडो रिफ्रेश करून पाहूया. + +छान! बटण तुम्हाला कनेक्ट झाल्याचे सांगेल आणि तुमच्या कनेक्ट केलेल्या वॉलेटच्या ॲड्रेसचे पूर्वावलोकन दाखवेल - जरी तुम्ही रिफ्रेश केले तरी! + +#### `addWalletListener` अंमलात आणा {#implement-addwalletlistener} + +आमच्या dapp वॉलेट सेटअपमधील शेवटची पायरी म्हणजे वॉलेट लिसनर लागू करणे जेणेकरून आमच्या वॉलेटची स्थिती बदलल्यावर आमचे UI अपडेट होईल, जसे की वापरकर्ता डिस्कनेक्ट झाल्यावर किंवा खाती बदलल्यावर. + +तुमच्या `HelloWorld.js` फाइलमध्ये, तुमचे `addWalletListener` फंक्शन खालीलप्रमाणे सुधारित करा: + +```javascript +// HelloWorld.js + +function addWalletListener() { + if (window.ethereum) { + window.ethereum.on("accountsChanged", (accounts) => { + if (accounts.length > 0) { + setWallet(accounts[0]) + setStatus("👆🏽 वरील टेक्स्ट-फील्डमध्ये एक संदेश लिहा.") + } else { + setWallet("") + setStatus("🦊 वरच्या उजव्या बटणाचा वापर करून MetaMask शी कनेक्ट करा.") + } + }) + } else { + setStatus( +

+ {" "} + 🦊 + तुम्ही तुमच्या ब्राउझरमध्ये MetaMask, एक व्हर्च्युअल Ethereum वॉलेट, इंस्टॉल करणे आवश्यक आहे. + +

+ ) + } +} +``` + +मला खात्री आहे की तुम्हाला या टप्प्यावर काय चालले आहे हे समजून घेण्यासाठी आमच्या मदतीची गरज नाही, परंतु संपूर्णतेच्या उद्देशाने, चला ते पटकन पाहूया: + +- प्रथम, आमचे फंक्शन तपासते की `window.ethereum` सक्षम आहे का (म्हणजे MetaMask स्थापित आहे का). + - जर ते नसेल, तर आम्ही फक्त आमचे `status` स्टेट व्हेरिएबल एका JSX स्ट्रिंगवर सेट करतो जे वापरकर्त्याला MetaMask स्थापित करण्यास सांगते. + - जर ते सक्षम असेल, तर आम्ही ओळ 3 वर `window.ethereum.on("accountsChanged")` हा लिसनर सेट करतो जो MetaMask वॉलेटमधील स्टेट बदलांसाठी ऐकतो, ज्यात वापरकर्ता dapp शी अतिरिक्त खाते जोडतो, खाती बदलतो किंवा खाते डिस्कनेक्ट करतो. जर किमान एक खाते कनेक्ट केलेले असेल, तर `walletAddress` स्टेट व्हेरिएबल लिसनरद्वारे परत केलेल्या `accounts` ॲरेमधील पहिले खाते म्हणून अपडेट केले जाते. अन्यथा, `walletAddress` एक रिकामा स्ट्रिंग म्हणून सेट केला जातो. + +शेवटचे पण महत्त्वाचे, आम्ही ते आमच्या `useEffect` फंक्शनमध्ये कॉल करणे आवश्यक आहे: + +```javascript +// HelloWorld.js + +useEffect(async () => { + const message = await loadCurrentMessage() + setMessage(message) + addSmartContractListener() + + const { address, status } = await getCurrentWalletConnected() + setWallet(address) + setStatus(status) + + addWalletListener() +}, []) +``` + +आणि झाले! आम्ही आमच्या सर्व वॉलेट कार्यक्षमतेचे प्रोग्रामिंग यशस्वीरित्या पूर्ण केले आहे! आता आमच्या शेवटच्या कार्याकडे: आमच्या स्मार्ट कॉन्ट्रॅक्टमध्ये संग्रहित केलेला संदेश अपडेट करणे! + +### पायरी ६: `updateMessage` फंक्शन अंमलात आणा {#step-6-implement-the-updateMessage-function} + +ठीक आहे मित्रांनो, आपण अंतिम टप्प्यात आलो आहोत! तुमच्या `interact.js` फाइलच्या `updateMessage` मध्ये, आम्ही खालील गोष्टी करणार आहोत: + +1. आम्हाला आमच्या स्मार्ट संपर्कात प्रकाशित करायचा असलेला संदेश वैध असल्याची खात्री करा +2. MetaMask वापरून आमच्या व्यवहारावर स्वाक्षरी करा +3. या फंक्शनला आमच्या `HelloWorld.js` फ्रंटएंड घटकामधून कॉल करा + +याला जास्त वेळ लागणार नाही; चला हा डॅप पूर्ण करूया! + +#### इनपुट एरर हाताळणी {#input-error-handling} + +स्वाभाविकच, फंक्शनच्या सुरुवातीला काही प्रकारचे इनपुट त्रुटी हाताळणी असणे अर्थपूर्ण आहे. + +आम्ही इच्छितो की जर MetaMask विस्तार स्थापित नसेल, कोणतेही वॉलेट कनेक्ट केलेले नसेल (म्हणजे, पास केलेला `address` एक रिकामा स्ट्रिंग आहे), किंवा `message` एक रिकामा स्ट्रिंग असेल तर आमचे फंक्शन लवकर परत यावे. चला `updateMessage` मध्ये खालील त्रुटी हाताळणी जोडूया: + +```javascript +// interact.js + +export const updateMessage = async (address, message) => { + if (!window.ethereum || address === null) { + return { + status: + "💡 ब्लॉकचेनवरील संदेश अपडेट करण्यासाठी तुमचे MetaMask वॉलेट कनेक्ट करा.", + } + } + + if (message.trim() === "") { + return { + status: "❌ तुमचा संदेश रिकामा स्ट्रिंग असू शकत नाही.", + } + } +} +``` + +आता त्यात योग्य इनपुट त्रुटी हाताळणी आहे, MetaMask द्वारे व्यवहारावर स्वाक्षरी करण्याची वेळ आली आहे! + +#### आमच्या व्यवहारावर स्वाक्षरी करणे {#signing-our-transaction} + +तुम्ही आधीपासूनच पारंपरिक वेब3 Ethereum व्यवहारांशी परिचित असाल, तर आम्ही पुढे लिहिणारा कोड खूप परिचित असेल. तुमच्या इनपुट त्रुटी हाताळणी कोडच्या खाली, `updateMessage` मध्ये खालील जोडा: + +```javascript +// interact.js + +//व्यवहार पॅरामीटर्स सेट करा +const transactionParameters = { + to: contractAddress, // कॉन्ट्रॅक्ट प्रकाशनांशिवाय आवश्यक. + from: address, // वापरकर्त्याच्या सक्रिय पत्त्याशी जुळले पाहिजे. + data: helloWorldContract.methods.update(message).encodeABI(), +} + +//व्यवहारावर स्वाक्षरी करा +try { + const txHash = await window.ethereum.request({ + method: "eth_sendTransaction", + params: [transactionParameters], + }) + return { + status: ( + + ✅{" "} + + Etherscan वर तुमच्या व्यवहाराची स्थिती पहा! + +
+ ℹ️ एकदा नेटवर्कद्वारे व्यवहाराची पडताळणी झाल्यावर, संदेश आपोआप अपडेट होईल. +
+ ), + } +} catch (error) { + return { + status: "😥 " + error.message, + } +} +``` + +चला पाहूया की काय चालले आहे. प्रथम, आम्ही आमचे व्यवहार पॅरामीटर्स सेट करतो, जिथे: + +- `to` प्राप्तकर्ता ॲड्रेस (आमचा स्मार्ट कॉन्ट्रॅक्ट) निर्दिष्ट करतो +- `from` व्यवहाराच्या स्वाक्षरीकर्त्याला निर्दिष्ट करते, आम्ही आमच्या फंक्शनमध्ये पास केलेला `address` व्हेरिएबल +- `data` मध्ये आमच्या हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्टच्या `update` पद्धतीचा कॉल आहे, जो आमचा `message` स्ट्रिंग व्हेरिएबल इनपुट म्हणून घेतो + +मग, आम्ही एक await कॉल करतो, `window.ethereum.request`, जिथे आम्ही MetaMask ला व्यवहारावर स्वाक्षरी करण्यास सांगतो. लक्षात घ्या, ओळी ११ आणि १२ वर, आम्ही आमची eth पद्धत, `eth_sendTransaction` निर्दिष्ट करत आहोत आणि आमचे `transactionParameters` पास करत आहोत. + +या टप्प्यावर, MetaMask ब्राउझरमध्ये उघडेल आणि वापरकर्त्याला व्यवहारावर सही करण्यास किंवा नाकारण्यास सांगेल. + +- जर व्यवहार यशस्वी झाला, तर फंक्शन एक JSON ऑब्जेक्ट परत करेल जिथे `status` JSX स्ट्रिंग वापरकर्त्याला त्यांच्या व्यवहाराबद्दल अधिक माहितीसाठी Etherscan तपासण्यास सांगते. +- जर व्यवहार अयशस्वी झाला, तर फंक्शन एक JSON ऑब्जेक्ट परत करेल जिथे `status` स्ट्रिंग त्रुटी संदेश प्रसारित करते. + +एकत्रितपणे, आमचे `updateMessage` फंक्शन असे दिसले पाहिजे: + +```javascript +// interact.js + +export const updateMessage = async (address, message) => { + //इनपुट त्रुटी हाताळणी + if (!window.ethereum || address === null) { + return { + status: + "💡 ब्लॉकचेनवरील संदेश अपडेट करण्यासाठी तुमचे MetaMask वॉलेट कनेक्ट करा.", + } + } + + if (message.trim() === "") { + return { + status: "❌ तुमचा संदेश रिकामा स्ट्रिंग असू शकत नाही.", + } + } + + //व्यवहार पॅरामीटर्स सेट करा + const transactionParameters = { + to: contractAddress, // कॉन्ट्रॅक्ट प्रकाशनांशिवाय आवश्यक. + from: address, // वापरकर्त्याच्या सक्रिय पत्त्याशी जुळले पाहिजे. + data: helloWorldContract.methods.update(message).encodeABI(), + } + + //व्यवहारावर स्वाक्षरी करा + try { + const txHash = await window.ethereum.request({ + method: "eth_sendTransaction", + params: [transactionParameters], + }) + return { + status: ( + + ✅{" "} + + Etherscan वर तुमच्या व्यवहाराची स्थिती पहा! + +
+ ℹ️ एकदा नेटवर्कद्वारे व्यवहाराची पडताळणी झाल्यावर, संदेश आपोआप अपडेट होईल. +
+ ), + } + } catch (error) { + return { + status: "😥 " + error.message, + } + } +} +``` + +शेवटचे पण महत्त्वाचे, आम्हाला आमचे `updateMessage` फंक्शन आमच्या `HelloWorld.js` घटकाशी कनेक्ट करणे आवश्यक आहे. + +#### `updateMessage` ला `HelloWorld.js` फ्रंटएंडशी कनेक्ट करा {#connect-updatemessage-to-the-helloworld-js-frontend} + +आमच्या `onUpdatePressed` फंक्शनने आयात केलेल्या `updateMessage` फंक्शनला एक await कॉल करावा आणि आमचा व्यवहार यशस्वी झाला की अयशस्वी हे दर्शविण्यासाठी `status` स्टेट व्हेरिएबल सुधारित करावे: + +```javascript +// HelloWorld.js + +const onUpdatePressed = async () => { + const { status } = await updateMessage(walletAddress, newMessage) + setStatus(status) +} +``` + +हे खूप स्वच्छ आणि सोपे आहे. आणि अंदाज लावा... तुमचा डॅप पूर्ण झाला आहे!!! + +पुढे जा आणि **अपडेट** बटणाची चाचणी घ्या! + +### तुमचा स्वतःचा सानुकूल डॅप बनवा {#make-your-own-custom-dapp} + +व्वा, तुम्ही ट्युटोरियलच्या शेवटपर्यंत पोहोचलात! रिकॅप करण्यासाठी, तुम्ही शिकलात की कसे: + +- तुमच्या डॅप प्रकल्पाला MetaMask वॉलेट कनेक्ट करा +- [Alchemy Web3](https://docs.alchemy.com/alchemy/documentation/alchemy-web3) API वापरून तुमच्या स्मार्ट कॉन्ट्रॅक्टमधून डेटा वाचा +- MetaMask वापरून Ethereum व्यवहारांवर स्वाक्षरी करा + +आता तुम्ही तुमचा स्वतःचा सानुकूल डॅप प्रकल्प तयार करण्यासाठी या ट्युटोरियलमधील कौशल्ये लागू करण्यासाठी पूर्णपणे सुसज्ज आहात! नेहमीप्रमाणे, तुम्हाला काही प्रश्न असल्यास, [Alchemy Discord](https://discord.gg/gWuC7zB) मध्ये मदतीसाठी आमच्याशी संपर्क साधण्यास अजिबात संकोच करू नका. 🧙‍♂️ + +एकदा तुम्ही हे ट्युटोरियल पूर्ण केल्यावर, आम्हाला Twitter [@alchemyplatform](https://twitter.com/AlchemyPlatform) वर टॅग करून तुमचा अनुभव कसा होता किंवा तुमचा काही अभिप्राय असल्यास आम्हाला कळवा! diff --git a/public/content/translations/mr/developers/tutorials/hello-world-smart-contract/index.md b/public/content/translations/mr/developers/tutorials/hello-world-smart-contract/index.md new file mode 100644 index 00000000000..637ec6384c2 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/hello-world-smart-contract/index.md @@ -0,0 +1,366 @@ +--- +title: "नवशिक्यांसाठी हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट" +description: "Ethereum वर एक साधे स्मार्ट कॉन्ट्रॅक्ट लिहिण्यावर आणि उपयोजित करण्यावर एक प्रास्ताविक ट्युटोरियल." +author: "elanh" +tags: + [ + "सॉलिडिटी", + "hardhat", + "alchemy", + "स्मार्ट कॉन्ट्रॅक्ट", + "डिप्लॉयिंग" + ] +skill: beginner +lang: mr +published: 2021-03-31 +--- + +जर तुम्ही ब्लॉकचेन डेव्हलपमेंटमध्ये नवीन असाल आणि कुठून सुरुवात करावी हे माहित नसेल, किंवा जर तुम्हाला फक्त स्मार्ट कॉन्ट्रॅक्ट कसे उपयोजित करायचे आणि त्यांच्याशी संवाद कसा साधायचा हे समजून घ्यायचे असेल, तर हा मार्गदर्शक तुमच्यासाठी आहे. आपण व्हर्च्युअल वॉलेट [MetaMask](https://metamask.io/), [Solidity](https://docs.soliditylang.org/en/v0.8.0/), [Hardhat](https://hardhat.org/), आणि [Alchemy](https://www.alchemy.com/eth) वापरून सेपोलिया टेस्ट नेटवर्कवर एक साधे स्मार्ट कॉन्ट्रॅक्ट तयार करण्याची आणि उपयोजित करण्याची प्रक्रिया पाहू (यापैकी कशाचाही अर्थ तुम्हाला अजून समजत नसेल, तर काळजी करू नका, आम्ही ते स्पष्ट करू). + +या ट्युटोरियलच्या [भाग २](https://docs.alchemy.com/docs/interacting-with-a-smart-contract) मध्ये, एकदा आपले स्मार्ट कॉन्ट्रॅक्ट येथे उपयोजित झाल्यावर आपण त्याच्याशी संवाद कसा साधू शकतो हे पाहू, आणि [भाग ३](https.www.alchemy.com/docs/submitting-your-smart-contract-to-etherscan) मध्ये आपण ते Etherscan वर कसे प्रकाशित करायचे हे पाहू. + +तुम्हाला कोणत्याही वेळी प्रश्न पडल्यास [Alchemy Discord](https://discord.gg/gWuC7zB) मध्ये मोकळेपणाने संपर्क साधा! + +## पायरी १: Ethereum नेटवर्कशी कनेक्ट करा {#step-1} + +Ethereum चेनला विनंत्या करण्याचे अनेक मार्ग आहेत. सोपेपणासाठी, आपण Alchemy वर एक विनामूल्य खाते वापरू, जो एक ब्लॉकचेन डेव्हलपर प्लॅटफॉर्म आणि API आहे, ज्यामुळे आपल्याला आपले स्वतःचे नोड्स चालवल्याशिवाय Ethereum चेनशी संवाद साधता येतो. या प्लॅटफॉर्ममध्ये मॉनिटरिंग आणि ॲनालिटिक्ससाठी डेव्हलपर साधने देखील आहेत, ज्यांचा आपण या ट्युटोरियलमध्ये फायदा घेऊ, जेणेकरून आपल्या स्मार्ट कॉन्ट्रॅक्टच्या उपयोजनात पडद्यामागे काय चालले आहे हे समजेल. जर तुमचे आधीच Alchemy खाते नसेल, तर [तुम्ही येथे विनामूल्य साइन अप करू शकता](https://dashboard.alchemy.com/signup). + +## पायरी २: तुमचे ॲप (आणि API की) तयार करा {#step-2} + +एकदा तुम्ही Alchemy खाते तयार केल्यावर, तुम्ही ॲप तयार करून API की तयार करू शकता. हे आम्हाला Sepolia चाचणी नेटवर्कवर विनंत्या करण्याची परवानगी देईल. जर तुम्ही टेस्टनेटशी परिचित नसाल, तर [हे पृष्ठ](/developers/docs/networks/) पहा. + +1. तुमच्या Alchemy डॅशबोर्डमधील "Create new app" पृष्ठावर जाण्यासाठी नेव्ह बारमध्ये "Select an app" निवडा आणि "Create new app" वर क्लिक करा. + +![हॅलो वर्ल्ड ॲप तयार करा](./hello-world-create-app.png) + +2. तुमच्या ॲपला “Hello World” असे नाव द्या, एक छोटे वर्णन द्या, आणि एक उपयोग-केस निवडा, उदा., "Infra & Tooling." पुढे, "Ethereum" साठी शोधा आणि नेटवर्क निवडा. + +![ॲप व्ह्यू हॅलो वर्ल्ड तयार करा](./create-app-view-hello-world.png) + +3. पुढे जाण्यासाठी "Next" वर क्लिक करा, नंतर “Create app” आणि बस्स! तुमचे ॲप नेव्ह बार ड्रॉपडाउन मेन्यूमध्ये दिसले पाहिजे, जिथे कॉपी करण्यासाठी API की उपलब्ध असेल. + +## पायरी ३: एक Ethereum खाते (पत्ता) तयार करा {#step-3} + +आम्हाला व्यवहार पाठवण्यासाठी आणि प्राप्त करण्यासाठी Ethereum खात्याची आवश्यकता आहे. या ट्यूटोरियलसाठी, आम्ही MetaMask वापरू, जे ब्राउझरमधील एक व्हर्च्युअल वॉलेट आहे, जे तुमचा Ethereum खाते पत्ता व्यवस्थापित करण्यासाठी वापरले जाते. [व्यवहारांविषयी](/developers/docs/transactions/) अधिक. + +तुम्ही MetaMask डाउनलोड करू शकता आणि [येथे](https://metamask.io/download) विनामूल्य Ethereum खाते तयार करू शकता. तुम्ही खाते तयार करत असताना, किंवा तुमचे खाते आधीच असल्यास, नेटवर्क ड्रॉपडाउन मेनू वापरून "Sepolia" टेस्ट नेटवर्कवर स्विच केल्याची खात्री करा (जेणेकरून आपण खऱ्या पैशांशी व्यवहार करणार नाही). + +जर तुम्हाला Sepolia सूचीबद्ध दिसत नसेल, तर मेन्यूमध्ये जा, नंतर Advanced मध्ये जाऊन खाली स्क्रोल करा आणि "Show test networks" चालू करण्यासाठी टॉगल करा. नेटवर्क निवड मेन्यूमध्ये, टेस्टनेटची सूची शोधण्यासाठी "Custom" टॅब निवडा आणि "Sepolia" निवडा. + +![metamask sepolia उदाहरण](./metamask-sepolia-example.png) + +## पायरी ४: फॉसेटमधून इथर मिळवा {#step-4} + +आपले स्मार्ट कॉन्ट्रॅक्ट टेस्ट नेटवर्कवर उपयोजित करण्यासाठी, आपल्याला काही बनावट Eth ची आवश्यकता असेल. Sepolia ETH मिळवण्यासाठी, विविध फॉसेटची सूची पाहण्यासाठी तुम्ही [Sepolia नेटवर्क तपशील](/developers/docs/networks/#sepolia) वर जाऊ शकता. एक काम करत नसल्यास, दुसरा प्रयत्न करा, कारण ते कधीकधी रिकामे होऊ शकतात. नेटवर्क ट्रॅफिकमुळे तुमचा बनावट ETH मिळण्यास थोडा वेळ लागू शकतो. त्यानंतर लवकरच तुमच्या Metamask खात्यात ETH दिसेल! + +## पायरी ५: तुमची शिल्लक तपासा {#step-5} + +आपली शिल्लक आहे की नाही, हे पुन्हा तपासण्यासाठी, चला [Alchemy च्या कंपोझर टूल](https://sandbox.alchemy.com/?network=ETH_SEPOLIA&method=eth_getBalance&body.id=1&body.jsonrpc=2.0&body.method=eth_getBalance&body.params%5B0%5D=&body.params%5B1%5D=latest) वापरून एक [eth_getBalance](/developers/docs/apis/json-rpc/#eth_getbalance) विनंती करूया. हे आमच्या वॉलेटमधील ETH ची रक्कम परत करेल. तुम्ही तुमच्या MetaMask खात्याचा पत्ता इनपुट केल्यानंतर आणि “Send Request” वर क्लिक केल्यानंतर, तुम्हाला असा प्रतिसाद दिसेल: + +```json +{ "jsonrpc": "2.0", "id": 0, "result": "0x2B5E3AF16B1880000" } +``` + +> **टीप:** हा निकाल ETH मध्ये नसून wei मध्ये आहे. Wei हे इथरचे सर्वात लहान एकक म्हणून वापरले जाते. wei चे ETH मध्ये रूपांतर असे आहे: 1 eth = 1018 wei. म्हणून जर आपण 0x2B5E3AF16B1880000 चे दशांश मध्ये रूपांतर केले, तर आपल्याला 5\*10¹⁸ मिळतात जे 5 ETH च्या बरोबर आहे. +> +> हुश्श! आपले बनावट पैसे पूर्णपणे तिथे आहेत . + +## पायरी ६: आपला प्रकल्प सुरू करा {#step-6} + +प्रथम, आपल्याला आपल्या प्रोजेक्टसाठी एक फोल्डर तयार करण्याची आवश्यकता असेल. तुमच्या कमांड लाइनवर नेव्हिगेट करा आणि टाइप करा: + +``` +mkdir hello-world +cd hello-world +``` + +आता आपण आपल्या प्रोजेक्ट फोल्डरमध्ये आहोत, आपण प्रोजेक्ट सुरू करण्यासाठी `npm init` वापरू. जर तुमच्याकडे आधीपासून npm इंस्टॉल केलेले नसेल, तर [या सूचनांचे](https://docs.alchemyapi.io/alchemy/guides/alchemy-for-macs#1-install-nodejs-and-npm) पालन करा (आपल्याला Node.js ची देखील आवश्यकता असेल, म्हणून ते देखील डाउनलोड करा!). + +``` +npm init +``` + +तुम्ही इन्स्टॉलेशनच्या प्रश्नांची उत्तरे कशी देता हे खरोखर महत्त्वाचे नाही, संदर्भासाठी आम्ही ते कसे केले ते येथे आहे: + +``` +package name: (hello-world) +version: (1.0.0) +description: hello world smart contract +entry point: (index.js) +test command: +git repository: +keywords: +author: +license: (ISC) +About to write to /Users/.../.../.../hello-world/package.json: + +{ + "name": "hello-world", + "version": "1.0.0", + "description": "hello world smart contract", + "main": "index.js", + "scripts": { + "test": "echo \\"Error: no test specified\\" && exit 1" + }, + "author": "", + "license": "ISC" +} +``` + +package.json ला मंजूर करा आणि आपण पुढे जाण्यास तयार आहोत! + +## पायरी ७: [Hardhat](https://hardhat.org/getting-started/#overview) डाउनलोड करा {#step-7} + +Hardhat हे तुमचे Ethereum सॉफ्टवेअर संकलित (compile), उपयोजित (deploy), चाचणी (test) आणि डीबग (debug) करण्यासाठी एक विकास वातावरण आहे. हे डेव्हलपर्सना थेट चेनवर उपयोजित करण्यापूर्वी स्थानिक पातळीवर स्मार्ट कॉन्ट्रॅक्ट्स आणि dApps तयार करताना मदत करते. + +आपल्या `hello-world` प्रोजेक्टमध्ये चालवा: + +``` +npm install --save-dev hardhat +``` + +[इन्स्टॉलेशन सूचनांविषयी](https://hardhat.org/getting-started/#overview) अधिक तपशीलांसाठी हे पेज पहा. + +## पायरी ८: Hardhat प्रोजेक्ट तयार करा {#step-8} + +आपल्या प्रोजेक्ट फोल्डरमध्ये चालवा: + +``` +npx hardhat +``` + +त्यानंतर तुम्हाला एक स्वागत संदेश आणि तुम्हाला काय करायचे आहे यासाठी पर्याय दिसेल. “create an empty hardhat.config.js” निवडा: + +``` +888 888 888 888 888 +888 888 888 888 888 +888 888 888 888 888 +8888888888 8888b. 888d888 .d88888 88888b. 8888b. 888888 +888 888 "88b 888P" d88" 888 888 "88b "88b 888 +888 888 .d888888 888 888 888 888 888 .d888888 888 +888 888 888 888 888 Y88b 888 888 888 888 888 Y88b. +888 888 "Y888888 888 "Y88888 888 888 "Y888888 "Y888 + +👷 Welcome to Hardhat v2.0.11 👷‍? + +What do you want to do? … +Create a sample project +❯ Create an empty hardhat.config.js +Quit +``` + +यामुळे आपल्यासाठी `hardhat.config.js` फाईल तयार होईल, जिथे आपण आपल्या प्रोजेक्टसाठी सर्व सेटअप निर्दिष्ट करू (पायरी १३ वर). + +## पायरी ९: प्रोजेक्ट फोल्डर्स जोडा {#step-9} + +आपला प्रोजेक्ट सुव्यवस्थित ठेवण्यासाठी आपण दोन नवीन फोल्डर्स तयार करू. तुमच्या कमांड लाइनमधील प्रोजेक्टच्या मूळ डिरेक्टरीवर नेव्हिगेट करा आणि टाइप करा: + +``` +mkdir contracts +mkdir scripts +``` + +- `contracts/` मध्ये आपण आपली हॅलो वर्ल्ड स्मार्ट कॉन्ट्रॅक्ट कोड फाईल ठेवू +- `scripts/` मध्ये आपण आपले कॉन्ट्रॅक्ट उपयोजित करण्यासाठी आणि त्याच्याशी संवाद साधण्यासाठी स्क्रिप्ट्स ठेवू + +## पायरी १०: आपले कॉन्ट्रॅक्ट लिहा {#step-10} + +तुम्ही स्वतःला विचारत असाल, की आपण कोड कधी लिहिणार आहोत?? तर, आपण पायरी १० वर आलो आहोत. + +hello-world प्रोजेक्ट तुमच्या आवडत्या एडिटरमध्ये उघडा (आम्हाला [VSCode](https://code.visualstudio.com/) आवडते). स्मार्ट कॉन्ट्रॅक्ट्स Solidity नावाच्या भाषेत लिहिले जातात, जी आपण आपले HelloWorld.sol स्मार्ट कॉन्ट्रॅक्ट लिहिण्यासाठी वापरू.‌ + +1. "contracts" फोल्डरमध्ये नेव्हिगेट करा आणि HelloWorld.sol नावाची नवीन फाईल तयार करा +2. खाली Ethereum फाउंडेशनकडून एक नमुना Hello World स्मार्ट कॉन्ट्रॅक्ट आहे, जो आपण या ट्युटोरियलसाठी वापरणार आहोत. खालील मजकूर तुमच्या HelloWorld.sol फाईलमध्ये कॉपी आणि पेस्ट करा, आणि हे कॉन्ट्रॅक्ट काय करते हे समजून घेण्यासाठी कमेंट्स नक्की वाचा: + +```solidity +// सिमेंटिक व्हर्जनिंग वापरून सॉलिडिटीची आवृत्ती निर्दिष्ट करते. +// अधिक जाणून घ्या: https://solidity.readthedocs.io/en/v0.5.10/layout-of-source-files.html#pragma +pragma solidity ^0.7.0; + +// `HelloWorld` नावाचे एक कॉन्ट्रॅक्ट परिभाषित करते. +// कॉन्ट्रॅक्ट हे फंक्शन्स आणि डेटा (त्याची स्थिती) यांचा संग्रह आहे. एकदा उपयोजित झाल्यावर, कॉन्ट्रॅक्ट Ethereum ब्लॉकचेनवर एका विशिष्ट पत्त्यावर राहते. अधिक जाणून घ्या: https://solidity.readthedocs.io/en/v0.5.10/structure-of-a-contract.html +contract HelloWorld { + + // `string` प्रकाराचे एक स्टेट व्हेरिएबल `message` घोषित करते. + // स्टेट व्हेरिएबल्स असे व्हेरिएबल्स आहेत ज्यांची मूल्ये कॉन्ट्रॅक्ट स्टोरेजमध्ये कायमची संग्रहित केली जातात. `public` कीवर्ड व्हेरिएबल्सना कॉन्ट्रॅक्टच्या बाहेरून ॲक्सेस करण्यायोग्य बनवतो आणि एक फंक्शन तयार करतो ज्याला इतर कॉन्ट्रॅक्ट्स किंवा क्लायंट्स मूल्य ॲक्सेस करण्यासाठी कॉल करू शकतात. + string public message; + + // अनेक क्लास-आधारित ऑब्जेक्ट-ओरिएंटेड भाषांप्रमाणे, कन्स्ट्रक्टर हे एक विशेष फंक्शन आहे जे फक्त कॉन्ट्रॅक्ट तयार झाल्यावर कार्यान्वित होते. + // कन्स्ट्रक्टरचा वापर कॉन्ट्रॅक्टचा डेटा सुरू करण्यासाठी केला जातो. अधिक जाणून घ्या:https://solidity.readthedocs.io/en/v0.5.10/contracts.html#constructors + constructor(string memory initMessage) { + + // एक स्ट्रिंग युक्तिवाद `initMessage` स्वीकारतो आणि कॉन्ट्रॅक्टच्या `message` स्टोरेज व्हेरिएबलमध्ये मूल्य सेट करतो). + message = initMessage; + } + + // एक पब्लिक फंक्शन जे एक स्ट्रिंग युक्तिवाद स्वीकारते आणि `message` स्टोरेज व्हेरिएबल अपडेट करते. + function update(string memory newMessage) public { + message = newMessage; + } +} +``` + +हे एक अत्यंत सोपे स्मार्ट कॉन्ट्रॅक्ट आहे जे तयार झाल्यावर एक संदेश संग्रहित करते आणि `update` फंक्शनला कॉल करून अपडेट केले जाऊ शकते. + +## पायरी ११: तुमच्या प्रोजेक्टला MetaMask आणि Alchemy कनेक्ट करा {#step-11} + +आपण MetaMask वॉलेट, Alchemy खाते तयार केले आहे आणि आपले स्मार्ट कॉन्ट्रॅक्ट लिहिले आहे, आता या तिन्हीना जोडण्याची वेळ आली आहे. + +तुमच्या व्हर्च्युअल वॉलेटमधून पाठवलेल्या प्रत्येक व्यवहारासाठी तुमच्या युनिक प्रायव्हेट की वापरून स्वाक्षरी आवश्यक आहे. आमच्या प्रोग्रामला ही परवानगी देण्यासाठी, आम्ही आमची प्रायव्हेट की (आणि Alchemy API की) एका एन्व्हायर्नमेंट फाइलमध्ये सुरक्षितपणे संग्रहित करू शकतो. + +> व्यवहार पाठवण्याबद्दल अधिक जाणून घेण्यासाठी, वेब3 वापरून व्यवहार पाठवण्यावरील [हे ट्यूटोरियल](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) पहा. + +प्रथम, तुमच्या प्रोजेक्ट डिरेक्टरीमध्ये dotenv पॅकेज इंस्टॉल करा: + +``` +npm install dotenv --save +``` + +त्यानंतर, आमच्या प्रोजेक्टच्या रूट डिरेक्टरीमध्ये एक `.env` फाइल तयार करा आणि त्यात तुमची MetaMask प्रायव्हेट की आणि HTTP Alchemy API URL जोडा. + +- तुमची प्रायव्हेट की एक्सपोर्ट करण्यासाठी [या सूचनांचे](https://support.metamask.io/configure/accounts/how-to-export-an-accounts-private-key/) पालन करा +- HTTP Alchemy API URL मिळवण्यासाठी खाली पहा + +![अल्केमी एपीआय की मिळवा](./get-alchemy-api-key.png) + +Alchemy API URL कॉपी करा + +तुमचे `.env` असे दिसले पाहिजे: + +``` +API_URL = "https://eth-sepolia.g.alchemy.com/v2/your-api-key" +PRIVATE_KEY = "your-metamask-private-key" +``` + +हे प्रत्यक्षात आपल्या कोडशी जोडण्यासाठी, आपण या व्हेरिएबल्सचा संदर्भ आपल्या `hardhat.config.js` फाईलमध्ये पायरी १३ वर देऊ. + + + + +.env कमिट करू नका! कृपया तुमची .env फाईल कोणासोबतही शेअर किंवा उघड करू नका, कारण असे केल्याने तुम्ही तुमची गुपिते धोक्यात आणत आहात याची खात्री करा. जर तुम्ही व्हर्जन कंट्रोल वापरत असाल, तर तुमची .env फाईल gitignore फाईलमध्ये जोडा. + + + + +## पायरी १२: Ethers.js इंस्टॉल करा {#step-12-install-ethersjs} + +Ethers.js ही एक लायब्ररी आहे जी अधिक वापरकर्ता-अनुकूल पद्धतींसह [प्रमाणित JSON-RPC पद्धती](/developers/docs/apis/json-rpc/) गुंडाळून Ethereum शी संवाद साधणे आणि विनंत्या करणे सोपे करते. + +Hardhat अतिरिक्त टूलिंग आणि विस्तारित कार्यक्षमतेसाठी [प्लगइन्स](https://hardhat.org/plugins/) समाकलित करणे खूप सोपे करते. आम्ही कॉन्ट्रॅक्ट डिप्लॉयमेंटसाठी [Ethers प्लगइन](https://hardhat.org/docs/plugins/official-plugins#hardhat-ethers) चा फायदा घेणार आहोत ([Ethers.js](https://github.com/ethers-io/ethers.js/) मध्ये काही अत्यंत स्वच्छ कॉन्ट्रॅक्ट डिप्लॉयमेंट पद्धती आहेत). + +आपल्या प्रोजेक्ट डिरेक्टरीमध्ये टाइप करा: + +``` +npm install --save-dev @nomiclabs/hardhat-ethers "ethers@^5.0.0" +``` + +आपण पुढील पायरीमध्ये आपल्या `hardhat.config.js` मध्ये ethers ची आवश्यकता देखील दर्शवू. + +## पायरी १३: hardhat.config.js अद्ययावत करा {#step-13-update-hardhatconfigjs} + +आतापर्यंत आपण अनेक डिपेंडेंसी आणि प्लगइन जोडले आहेत, आता आपल्याला `hardhat.config.js` अद्यतनित करण्याची आवश्यकता आहे जेणेकरून आपल्या प्रोजेक्टला त्या सर्वांबद्दल माहिती मिळेल. + +तुमचे `hardhat.config.js` याप्रमाणे दिसण्यासाठी अद्यतनित करा: + +``` +require('dotenv').config(); + +require("@nomiclabs/hardhat-ethers"); +const { API_URL, PRIVATE_KEY } = process.env; + +/** +* @type import('hardhat/config').HardhatUserConfig +*/ +module.exports = { + solidity: "0.7.3", + defaultNetwork: "sepolia", + networks: { + hardhat: {}, + sepolia: { + url: API_URL, + accounts: [`0x${PRIVATE_KEY}`] + } + }, +} +``` + +## पायरी १४: आपले कॉन्ट्रॅक्ट कंपाईल करा {#step-14-compile-our-contracts} + +आतापर्यंत सर्व काही कार्यरत आहे याची खात्री करण्यासाठी, चला आमचा कॉन्ट्रॅक्ट संकलित करूया. `compile` कार्य हे बिल्ट-इन हार्डहॅट कार्यांपैकी एक आहे. + +कमांड लाइनमधून चालवा: + +``` +npx hardhat compile +``` + +तुम्हाला `SPDX license identifier not provided in source file` बद्दल एक चेतावणी मिळू शकते, परंतु त्याबद्दल काळजी करण्याची गरज नाही — आशा आहे की इतर सर्व काही ठीक दिसेल! नसल्यास, तुम्ही नेहमी [Alchemy discord](https://discord.gg/u72VCg3) मध्ये संदेश पाठवू शकता. + +## पायरी १५: आमची डिप्लॉय स्क्रिप्ट लिहा {#step-15-write-our-deploy-scripts} + +आता आमचा कॉन्ट्रॅक्ट लिहिला आहे आणि आमची कॉन्फिगरेशन फाइल तयार आहे, आता आमच्या कॉन्ट्रॅक्टची उपयोजन स्क्रिप्ट लिहिण्याची वेळ आली आहे. + +`scripts/` फोल्डरवर नेव्हिगेट करा आणि `deploy.js` नावाची एक नवीन फाइल तयार करा, त्यात खालील सामग्री जोडा: + +``` +async function main() { + const HelloWorld = await ethers.getContractFactory("HelloWorld"); + + // उपयोजन सुरू करा, जे एक प्रॉमिस परत करते जे कॉन्ट्रॅक्ट ऑब्जेक्टमध्ये रूपांतरित होते + const hello_world = await HelloWorld.deploy("Hello World!"); + console.log("Contract deployed to address:", hello_world.address);} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); +``` + +Hardhat त्यांच्या [कॉन्ट्रॅक्ट्स ट्यूटोरियल](https://hardhat.org/tutorial/testing-contracts.html#writing-tests) मध्ये या प्रत्येक कोड ओळी काय करते हे आश्चर्यकारकपणे स्पष्ट करते, आम्ही त्यांचे स्पष्टीकरण येथे स्वीकारले आहे. + +``` +const HelloWorld = await ethers.getContractFactory("HelloWorld"); +``` + +ethers.js मधील `ContractFactory` हे नवीन स्मार्ट कॉन्ट्रॅक्ट उपयोजित करण्यासाठी वापरले जाणारे एक ॲब्स्ट्रॅक्शन आहे, म्हणून येथे `HelloWorld` हे आपल्या हॅलो वर्ल्ड कॉन्ट्रॅक्टच्या इन्स्टन्ससाठी एक फॅक्टरी आहे. `hardhat-ethers` प्लगइन वापरताना `ContractFactory` आणि `Contract` इन्स्टन्स डीफॉल्टनुसार पहिल्या स्वाक्षरीकर्त्याशी जोडलेले असतात. + +``` +const hello_world = await HelloWorld.deploy(); +``` + +`ContractFactory` वर `deploy()` कॉल केल्याने उपयोजन सुरू होईल, आणि एक `Promise` परत येईल जो `Contract` मध्ये रिझॉल्व्ह होईल. हे ते ऑब्जेक्ट आहे ज्यामध्ये आमच्या प्रत्येक स्मार्ट कॉन्ट्रॅक्ट फंक्शनसाठी एक पद्धत आहे. + +## पायरी १६: आपले कॉन्ट्रॅक्ट उपयोजित करा {#step-16-deploy-our-contract} + +आम्ही अखेरीस आमचा स्मार्ट कॉन्ट्रॅक्ट उपयोजित करण्यास तयार आहोत! कमांड लाइनवर नेव्हिगेट करा आणि चालवा: + +``` +npx hardhat run scripts/deploy.js --network sepolia +``` + +तुम्हाला त्यानंतर असे काहीतरी दिसेल: + +``` +Contract deployed to address: 0x6cd7d44516a20882cEa2DE9f205bF401c0d23570 +``` + +जर आपण [Sepolia etherscan](https://sepolia.etherscan.io/) वर गेलो आणि आपल्या कॉन्ट्रॅक्ट पत्त्यासाठी शोधले तर ते यशस्वीरित्या उपयोजित झाले आहे हे आपण पाहू शकू. व्यवहार असा काहीतरी दिसेल: + +![etherscan कॉन्ट्रॅक्ट](./etherscan-contract.png) + +`From` पत्ता तुमच्या MetaMask खात्याच्या पत्त्याशी जुळला पाहिजे आणि To पत्त्यावर “Contract Creation” असे दिसेल, परंतु जर आपण व्यवहारात क्लिक केले तर आपल्याला `To` फील्डमध्ये आपला कॉन्ट्रॅक्ट पत्ता दिसेल: + +![एथरस्कॅन व्यवहार](./etherscan-transaction.png) + +अभिनंदन! तुम्ही नुकतेच Ethereum चेनवर एक स्मार्ट कॉन्ट्रॅक्ट उपयोजित केले आहे 🎉 + +पडद्यामागे काय चालले आहे हे समजून घेण्यासाठी, चला आमच्या [Alchemy dashboard](https://dashboard.alchemyapi.io/explorer) मधील Explorer टॅबवर नेव्हिगेट करूया. तुमच्याकडे अनेक Alchemy ॲप्स असल्यास, ॲपनुसार फिल्टर केल्याची खात्री करा आणि “Hello World” निवडा. +![हॅलो वर्ल्ड एक्सप्लोरर](./hello-world-explorer.png) + +येथे तुम्हाला मुठभर JSON-RPC कॉल्स दिसतील जे Hardhat/Ethers ने `.deploy()` फंक्शन कॉल केल्यावर पडद्याआड आपल्यासाठी केले. येथे दोन महत्त्वाचे मुद्दे म्हणजे [`eth_sendRawTransaction`](https://www.alchemy.com/docs/node/abstract/abstract-api-endpoints/eth-send-raw-transaction), जे प्रत्यक्षात सेपोलिया चेनवर आपले कॉन्ट्रॅक्ट लिहिण्याची विनंती आहे, आणि [`eth_getTransactionByHash`](https://www.alchemy.com/docs/node/abstract/abstract-api-endpoints/eth-get-transaction-by-hash) जे हॅश दिल्यावर आपल्या व्यवहाराबद्दल माहिती वाचण्याची विनंती आहे (व्यवहार करताना एक सामान्य नमुना). व्यवहार पाठविण्याबद्दल अधिक जाणून घेण्यासाठी, [Web3 आणि Alchemy वापरून व्यवहार पाठविण्यावरील](/developers/tutorials/sending-transactions-using-web3-and-alchemy/) हे ट्युटोरियल पहा. + +या ट्युटोरियलच्या भाग १ साठी एवढेच, भाग २ मध्ये आपण आपला सुरुवातीचा संदेश अपडेट करून [आपल्या स्मार्ट कॉन्ट्रॅक्टशी संवाद साधू](https://www.alchemy.com/docs/interacting-with-a-smart-contract) आणि भाग ३ मध्ये आपण [आपले स्मार्ट कॉन्ट्रॅक्ट Etherscan वर प्रकाशित करू](https://www.alchemy.com/docs/submitting-your-smart-contract-to-etherscan) जेणेकरून प्रत्येकाला त्याच्याशी संवाद कसा साधायचा हे कळेल. + +\*\*Alchemy बद्दल अधिक जाणून घ्यायचे आहे? आमची [वेबसाइट](https://www.alchemy.com/eth) तपासा. एकही अपडेट चुकवायचे नाही? [येथे](https://www.alchemy.com/newsletter) आमच्या वृत्तपत्राची सदस्यता घ्या! आमच्या [Discord](https://discord.gg/u72VCg3) मध्ये सामील होण्याची खात्री करा. \*\* diff --git a/public/content/translations/mr/developers/tutorials/how-to-implement-an-erc721-market/index.md b/public/content/translations/mr/developers/tutorials/how-to-implement-an-erc721-market/index.md new file mode 100644 index 00000000000..8997ff14d37 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/how-to-implement-an-erc721-market/index.md @@ -0,0 +1,151 @@ +--- +title: "ERC-721 मार्केट कसे लागू करावे" +description: "विकेंद्रीकृत क्लासिफाइड्स बोर्डवर टोकनाइज्ड वस्तू विक्रीसाठी कशा ठेवायच्या" +author: "Alberto Cuesta Cañada" +tags: + [ + "स्मार्ट कॉन्ट्रॅक्ट", + "erc-721", + "सॉलिडिटी", + "tokens" + ] +skill: intermediate +lang: mr +published: 2020-03-19 +source: Hackernoon +sourceUrl: https://hackernoon.com/how-to-implement-an-erc721-market-1e1a32j9 +--- + +या लेखात, मी तुम्हाला Ethereum blockchain साठी Craigslist कसे कोड करायचे हे दाखवणार आहे. + +Gumtree, Ebay आणि Craigslist पूर्वी, क्लासिफाइड्स बोर्ड बहुतेक कॉर्क किंवा कागदाचे बनलेले होते. शाळेच्या कॉरिडॉरमध्ये, वर्तमानपत्रांमध्ये, रस्त्यावरील दिव्यांवर, दुकानांच्या दर्शनी भागात क्लासिफाइड्स बोर्ड होते. + +इंटरनेटमुळे हे सर्व बदलले. एखादा विशिष्ट क्लासिफाइड्स बोर्ड पाहू शकणाऱ्या लोकांची संख्या अनेक पटींनी वाढली. त्यामुळे, ते ज्या बाजारांचे प्रतिनिधित्व करतात ते अधिक कार्यक्षम बनले आणि जागतिक स्तरावर विस्तारले. Ebay हा एक मोठा व्यवसाय आहे ज्याची मुळे या भौतिक क्लासिफाइड्स बोर्डांमध्ये आहेत. + +Blockchain मुळे हे बाजार पुन्हा एकदा बदलणार आहेत, मी तुम्हाला दाखवतो कसे. + +## कमाई {#monetization} + +सार्वजनिक blockchain क्लासिफाइड्स बोर्डचे व्यवसाय मॉडेल Ebay आणि कंपनीच्या मॉडेलपेक्षा वेगळे असणे आवश्यक आहे. + +प्रथम, [विकेंद्रीकरणाचा दृष्टिकोन](/developers/docs/web2-vs-web3/) आहे. विद्यमान प्लॅटफॉर्मला त्यांचे स्वतःचे सर्व्हर सांभाळावे लागतात. एक विकेंद्रित प्लॅटफॉर्म त्याच्या वापरकर्त्यांद्वारे सांभाळला जातो, त्यामुळे प्लॅटफॉर्म मालकासाठी मूळ प्लॅटफॉर्म चालवण्याचा खर्च शून्यावर येतो. + +त्यानंतर फ्रंट एंड आहे, म्हणजेच वेबसाइट किंवा इंटरफेस जो प्लॅटफॉर्मवर प्रवेश देतो. येथे अनेक पर्याय आहेत. प्लॅटफॉर्मचे मालक प्रवेश प्रतिबंधित करू शकतात आणि प्रत्येकाला त्यांचा इंटरफेस वापरण्यास भाग पाडू शकतात, त्यासाठी शुल्क आकारू शकतात. प्लॅटफॉर्मचे मालक प्रवेश खुला करण्याचा निर्णय घेऊ शकतात (पॉवर टू द पीपल!) आणि कोणालाही प्लॅटफॉर्मसाठी इंटरफेस तयार करण्याची परवानगी देऊ शकतात. किंवा मालक या दोन टोकांच्या मधला कोणताही दृष्टिकोन ठरवू शकतात. + +_माझ्यापेक्षा अधिक दूरदृष्टी असलेले व्यावसायिक नेते यातून कमाई कशी करायची हे जाणतील._ _मला फक्त एवढेच दिसते की हे सध्याच्या स्थितीपेक्षा वेगळे आहे आणि कदाचित फायदेशीर आहे._ + +शिवाय, ऑटोमेशन आणि पेमेंट्सचा दृष्टिकोन आहे. काही गोष्टी खूप [प्रभावीपणे टोकनाइज्ड](https://hackernoon.com/tokenization-of-digital-assets-g0ffk3v8s?ref=hackernoon.com) केल्या जाऊ शकतात आणि क्लासिफाइड्स बोर्डमध्ये त्यांचा व्यापार केला जाऊ शकतो. टोकनाइज्ड मालमत्ता blockchain मध्ये सहजपणे हस्तांतरित केल्या जातात. अत्यंत गुंतागुंतीच्या पेमेंट पद्धती blockchain मध्ये सहजपणे लागू केल्या जाऊ शकतात. + +मला येथे फक्त व्यवसायाच्या संधीचा वास येत आहे. कोणत्याही चालू खर्चाशिवाय क्लासिफाइड्स बोर्ड सहजपणे लागू केला जाऊ शकतो, ज्यामध्ये प्रत्येक व्यवहारात गुंतागुंतीचे पेमेंट मार्ग समाविष्ट असतील. मला खात्री आहे की याचा उपयोग कशासाठी करायचा याबद्दल कोणालातरी कल्पना सुचेल. + +मी फक्त ते तयार करण्यात आनंदी आहे. चला कोडवर एक नजर टाकूया. + +## अंमलबजावणी {#implementation} + +काही काळापूर्वी आम्ही बिझनेस केसच्या उदाहरणांच्या अंमलबजावणी आणि इतर चांगल्या गोष्टींसह एक [ओपन सोर्स रिपॉझिटरी](https://github.com/HQ20/contracts?ref=hackernoon.com) सुरू केली आहे, कृपया एक नजर टाका. + +या [Ethereum Classifieds Board](https://github.com/HQ20/contracts/tree/master/contracts/classifieds?ref=hackernoon.com) साठीचा कोड तिथे आहे, कृपया त्याचा वापर करा आणि त्याचा भरपूर वापर करा. फक्त हे लक्षात ठेवा की कोडचे ऑडिट केलेले नाही आणि त्यात पैसे गुंतवण्यापूर्वी तुम्हाला स्वतःची योग्य तपासणी करणे आवश्यक आहे. + +बोर्डच्या मूलभूत गोष्टी गुंतागुंतीच्या नाहीत. बोर्डमधील सर्व जाहिराती फक्त काही फील्ड्ससह एक struct असतील: + +```solidity +struct Trade { + address poster; + uint256 item; + uint256 price; + bytes32 status; // उघडा, कार्यान्वित, रद्द +} +``` + +म्हणजे जाहिरात पोस्ट करणारी कोणीतरी व्यक्ती आहे. विक्रीसाठी एक वस्तू. वस्तूसाठी एक किंमत. व्यापाराची स्थिती जी उघडी, कार्यान्वित किंवा रद्द केली जाऊ शकते. + +हे सर्व व्यवहार एका मॅपिंगमध्ये ठेवले जातील. कारण Solidity मध्ये सर्व काही मॅपिंगच असल्याचे दिसते. तसेच ते सोयीचे असल्यामुळे. + +```solidity +mapping(uint256 => Trade) public trades; +``` + +मॅपिंग वापरण्याचा अर्थ असा आहे की प्रत्येक जाहिरात पोस्ट करण्यापूर्वी आपल्याला त्यासाठी एक आयडी तयार करावा लागेल, आणि त्यावर प्रक्रिया करण्यापूर्वी आपल्याला त्या जाहिरातीचा आयडी माहित असणे आवश्यक असेल. स्मार्ट कॉन्ट्रॅक्टमध्ये किंवा फ्रंट-एंडमध्ये यावर काम करण्याचे अनेक मार्ग आहेत. तुम्हाला काही सूचना हव्या असल्यास कृपया विचारा. + +पुढे प्रश्न येतो की आपण ज्या वस्तूंचा व्यवहार करतो त्या कोणत्या आहेत आणि व्यवहारासाठी पैसे देण्यासाठी वापरले जाणारे चलन कोणते आहे. + +वस्तूंसाठी, आम्ही फक्त त्यांना [ERC-721](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721.sol?ref=hackernoon.com) इंटरफेस लागू करण्यास सांगणार आहोत, जो वास्तविक जगातील वस्तू blockchain मध्ये दर्शविण्याचा एक मार्ग आहे, जरी ते [डिजिटल मालमत्तेसह सर्वोत्तम कार्य करते](https://hackernoon.com/tokenization-of-digital-assets-g0ffk3v8s?ref=hackernoon.com). आम्ही कन्स्ट्रक्टरमध्ये आमचा स्वतःचा ERC721 कॉन्ट्रॅक्ट निर्दिष्ट करणार आहोत, याचा अर्थ आमच्या क्लासिफाइड्स बोर्डमधील कोणत्याही मालमत्तेचे आधीच टोकनायझेशन करणे आवश्यक आहे. + +पेमेंट्ससाठी, आम्ही असेच काहीतरी करणार आहोत. बहुतेक blockchain प्रकल्प स्वतःची [ERC-20](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol?ref=hackernoon.com) क्रिप्टोकरन्सी परिभाषित करतात. काहीजण DAI सारखे मुख्य प्रवाहातील चलन वापरण्यास प्राधान्य देतात. या क्लासिफाइड्स बोर्डमध्ये, तुम्हाला फक्त निर्मितीच्या वेळी ठरवायचे आहे की तुमचे चलन कोणते असेल. सोपे. + +```solidity +constructor ( + address _currencyTokenAddress, address _itemTokenAddress +) public { + currencyToken = IERC20(_currencyTokenAddress); + itemToken = IERC721(_itemTokenAddress); + tradeCounter = 0; +} +``` + +आपण तिथे पोहोचत आहोत. आपल्याकडे जाहिराती, व्यापारासाठी वस्तू आणि पेमेंटसाठी चलन आहे. जाहिरात तयार करणे म्हणजे तुमच्याकडे ती वस्तू आहे आणि तुम्ही ती दोनदा पोस्ट केलेली नाही, शक्यतो वेगळ्या बोर्डवर, हे दाखवण्यासाठी ती वस्तू एस्क्रोमध्ये ठेवणे. + +खालील कोड नेमके तेच करतो. वस्तू एस्क्रोमध्ये ठेवतो, जाहिरात तयार करतो, काही हाउसकीपिंगची कामे करतो. + +```solidity +function openTrade(uint256 _item, uint256 _price) + public +{ + itemToken.transferFrom(msg.sender, address(this), _item); + trades[tradeCounter] = Trade({ + poster: msg.sender, + item: _item, + price: _price, + status: "Open" + }); + tradeCounter += 1; + emit TradeStatusChange(tradeCounter - 1, "Open"); +} +``` + +व्यापार स्वीकारणे म्हणजे एक जाहिरात (व्यापार) निवडणे, किंमत भरणे, वस्तू मिळवणे. खालील कोड एक व्यापार पुनर्प्राप्त करतो. तो उपलब्ध आहे का ते तपासतो. वस्तूसाठी पैसे देतो. वस्तू परत मिळवतो. जाहिरात अपडेट करतो. + +```solidity +function executeTrade(uint256 _trade) + public +{ + Trade memory trade = trades[_trade]; + require(trade.status == "Open", "व्यापार खुला नाही."); + currencyToken.transferFrom(msg.sender, trade.poster, trade.price); + itemToken.transferFrom(address(this), msg.sender, trade.item); + trades[_trade].status = "Executed"; + emit TradeStatusChange(_trade, "Executed"); +} +``` + +शेवटी, विक्रेत्यांसाठी खरेदीदाराने व्यापार स्वीकारण्यापूर्वी त्यातून बाहेर पडण्याचा पर्याय आहे. काही मॉडेल्समध्ये, जाहिराती कालबाह्य होण्यापूर्वी काही कालावधीसाठी थेट (live) राहतील. तुमच्या बाजाराच्या डिझाइनवर अवलंबून, ही तुमची निवड आहे. + +हा कोड व्यापार कार्यान्वित करण्यासाठी वापरलेल्या कोडसारखाच आहे, फक्त यात चलनाची देवाणघेवाण होत नाही आणि वस्तू जाहिरात पोस्ट करणाऱ्याकडे परत जाते. + +```solidity +function cancelTrade(uint256 _trade) + public +{ + Trade memory trade = trades[_trade]; + require( + msg.sender == trade.poster, + "व्यापार फक्त पोस्ट करणाऱ्याद्वारे रद्द केला जाऊ शकतो." + ); + require(trade.status == "Open", "व्यापार खुला नाही."); + itemToken.transferFrom(address(this), trade.poster, trade.item); + trades[_trade].status = "Cancelled"; + emit TradeStatusChange(_trade, "Cancelled"); +} +``` + +बस इतकेच. तुम्ही अंमलबजावणीच्या शेवटपर्यंत पोहोचला आहात. काही व्यावसायिक संकल्पना कोडमध्ये व्यक्त केल्यावर किती संक्षिप्त असतात हे आश्चर्यकारक आहे, आणि हे त्यापैकीच एक उदाहरण आहे. संपूर्ण कॉन्ट्रॅक्ट [आमच्या रेपॉजिटरीमध्ये](https://github.com/HQ20/contracts/blob/master/contracts/classifieds/Classifieds.sol) तपासा. + +## निष्कर्ष {#conclusion} + +क्लासिफाइड्स बोर्ड हे एक सामान्य बाजारपेठेचे स्वरूप आहे जे इंटरनेटमुळे मोठ्या प्रमाणावर विस्तारले, आणि काही मक्तेदारी विजेत्यांसह एक प्रचंड लोकप्रिय व्यवसाय मॉडेल बनले. + +क्लासिफाइड्स बोर्ड हे blockchain वातावरणात प्रतिकृती बनवण्यासाठी एक सोपे साधन आहे, ज्यात खूप विशिष्ट वैशिष्ट्ये आहेत जी विद्यमान दिग्गजांना आव्हान देणे शक्य करतील. + +या लेखात, मी क्लासिफाइड्स बोर्ड व्यवसायाच्या व्यावसायिक वास्तवाला तांत्रिक अंमलबजावणीशी जोडण्याचा प्रयत्न केला आहे. जर तुमच्याकडे योग्य कौशल्ये असतील तर हे ज्ञान तुम्हाला अंमलबजावणीसाठी एक दूरदृष्टी आणि रोडमॅप तयार करण्यास मदत करेल. + +नेहमीप्रमाणे, जर तुम्ही काहीतरी मजेदार तयार करत असाल आणि तुम्हाला काही सल्ला हवा असेल, तर कृपया [मला संपर्क साधा](https://albertocuesta.es/)! मला मदत करायला नेहमीच आनंद होतो. diff --git a/public/content/translations/mr/developers/tutorials/how-to-mint-an-nft/index.md b/public/content/translations/mr/developers/tutorials/how-to-mint-an-nft/index.md new file mode 100644 index 00000000000..62ec6d3a132 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/how-to-mint-an-nft/index.md @@ -0,0 +1,335 @@ +--- +title: "NFT कसे मिंट करावे (NFT ट्युटोरियल मालिकेचा भाग 2/3)" +description: "हे ट्युटोरियल आमचा स्मार्ट कॉन्ट्रॅक्ट आणि Web3 वापरून Ethereum ब्लॉकचेनवर NFT कसे मिंट करायचे याचे वर्णन करते." +author: "Sumi Mudgil" +tags: + [ + "ERC-721", + "alchemy", + "सॉलिडिटी", + "स्मार्ट कॉन्ट्रॅक्ट" + ] +skill: beginner +lang: mr +published: 2021-04-22 +--- + +[बीपल](https://www.nytimes.com/2021/03/11/arts/design/nft-auction-christies-beeple.html): $69 दशलक्ष +[3LAU](https://www.forbes.com/sites/abrambrown/2021/03/03/3lau-nft-nonfungible-tokens-justin-blau/?sh=5f72ef64643b): $11 दशलक्ष +[ग्राइम्स](https://www.theguardian.com/music/2021/mar/02/grimes-sells-digital-art-collection-non-fungible-tokens): $6 दशलक्ष + +त्या सर्वांनी Alchemy च्या शक्तिशाली API चा वापर करून त्यांचे NFTs मिंट केले. या ट्युटोरियलमध्ये, आम्ही तुम्हाला \<10 मिनिटांत तेच कसे करायचे हे शिकवू. + +"NFT मिंट करणे" म्हणजे ब्लॉकचेनवर तुमच्या ERC-721 टोकनची एक अद्वितीय प्रत प्रकाशित करण्याची क्रिया. [या NFT ट्युटोरियल मालिकेच्या भाग १](/developers/tutorials/how-to-write-and-deploy-an-nft/) मधील आमचा स्मार्ट कॉन्ट्रॅक्ट वापरून, चला आपले Web3 कौशल्य दाखवूया आणि एक NFT मिंट करूया. या ट्युटोरियलच्या शेवटी, तुम्ही तुमच्या मनाला (आणि वॉलेटला) हवे तितके NFTs मिंट करू शकाल! + +चला सुरू करूया! + +## पायरी १: Web3 इंस्टॉल करा {#install-web3} + +जर तुम्ही तुमचा NFT स्मार्ट कॉन्ट्रॅक्ट तयार करण्यावरील पहिले ट्युटोरियल फॉलो केले असेल, तर तुम्हाला Ethers.js वापरण्याचा अनुभव आधीच आहे. Web3 हे Ethers सारखेच आहे, कारण ही एक लायब्ररी आहे जी Ethereum ब्लॉकचेनला विनंत्या करणे सोपे करण्यासाठी वापरली जाते. या ट्युटोरियलमध्ये आपण [Alchemy Web3](https://docs.alchemyapi.io/alchemy/documentation/alchemy-web3) वापरणार आहोत, जी एक वर्धित Web3 लायब्ररी आहे जी स्वयंचलित पुनर्प्रयत्न आणि मजबूत WebSocket सपोर्ट देते. + +तुमच्या प्रोजेक्ट होम डिरेक्टरीमध्ये चालवा: + +``` +npm install @alch/alchemy-web3 +``` + +## पायरी २: `mint-nft.js` फाईल तयार करा {#create-mintnftjs} + +तुमच्या स्क्रिप्ट्स डिरेक्टरीमध्ये, `mint-nft.js` फाईल तयार करा आणि कोडच्या खालील ओळी जोडा: + +```js +require("dotenv").config() +const API_URL = process.env.API_URL +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(API_URL) +``` + +## पायरी ३: तुमचा कॉन्ट्रॅक्ट ABI मिळवा {#contract-abi} + +आमचा कॉन्ट्रॅक्ट ABI (ऍप्लिकेशन बायनरी इंटरफेस) हा आमच्या स्मार्ट कॉन्ट्रॅक्टशी संवाद साधण्यासाठी इंटरफेस आहे. तुम्ही कॉन्ट्रॅक्ट ABI बद्दल अधिक माहिती [येथे](https://docs.alchemyapi.io/alchemy/guides/eth_getlogs#what-are-ab-is) मिळवू शकता. Hardhat आमच्यासाठी आपोआप एक ABI तयार करते आणि ते `MyNFT.json` फाईलमध्ये सेव्ह करते. हे वापरण्यासाठी, आपल्याला आपल्या `mint-nft.js` फाईलमध्ये कोडच्या खालील ओळी जोडून मजकूर पार्स करणे आवश्यक आहे: + +```js +const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json") +``` + +जर तुम्हाला ABI पाहायचा असेल तर तुम्ही ते तुमच्या कन्सोलवर प्रिंट करू शकता: + +```js +console.log(JSON.stringify(contract.abi)) +``` + +`mint-nft.js` चालवण्यासाठी आणि तुमचा ABI कन्सोलवर प्रिंट झालेला पाहण्यासाठी तुमच्या टर्मिनलवर नेव्हिगेट करा आणि चालवा: + +```js +node scripts/mint-nft.js +``` + +## पायरी ४: IPFS वापरून तुमच्या NFT साठी मेटाडेटा कॉन्फिगर करा {#config-meta} + +तुम्हाला भाग 1 मधील आमच्या ट्युटोरियलमधून आठवत असेल तर, आमचे `mintNFT` स्मार्ट कॉन्ट्रॅक्ट फंक्शन एक tokenURI पॅरामीटर घेते जे NFT च्या मेटाडेटाचे वर्णन करणाऱ्या JSON डॉक्युमेंटमध्ये रिझॉल्व्ह झाले पाहिजे — जे खरोखर NFT ला जिवंत करते, त्याला नाव, वर्णन, प्रतिमा आणि इतर गुणधर्मांसारखे कॉन्फिगर करण्यायोग्य गुणधर्म ठेवण्याची परवानगी देते. + +> _इंटरप्लॅनेटरी फाईल सिस्टम (IPFS) हा एक विकेंद्रित प्रोटोकॉल आणि पीअर-टू-पीअर नेटवर्क आहे, जो वितरित फाईल सिस्टममध्ये डेटा संग्रहित आणि शेअर करण्यासाठी आहे._ + +आपला NFT खरोखर विकेंद्रित आहे याची खात्री करण्यासाठी, आपण आपली NFT मालमत्ता आणि मेटाडेटा संग्रहित करण्यासाठी Pinata, एक सोयीस्कर IPFS API आणि टूलकिट वापरणार आहोत. तुमचे Pinata खाते नसल्यास, [येथे](https://app.pinata.cloud) विनामूल्य खात्यासाठी साइन अप करा आणि तुमचा ईमेल सत्यापित करण्यासाठी पायऱ्या पूर्ण करा. + +एकदा तुम्ही खाते तयार केल्यानंतर: + +- "फाईल्स" पेजवर नेव्हिगेट करा आणि पेजच्या वरच्या-डाव्या कोपऱ्यात असलेल्या निळ्या "अपलोड" बटणावर क्लिक करा. + +- Pinata वर एक प्रतिमा अपलोड करा — ही तुमच्या NFT साठी प्रतिमा मालमत्ता असेल. मालमत्तेला तुम्हाला हवे ते नाव देण्यास मोकळे आहात + +- तुम्ही अपलोड केल्यानंतर, तुम्हाला "फाईल्स" पेजवरील टेबलमध्ये फाईलची माहिती दिसेल. तुम्हाला एक CID स्तंभ देखील दिसेल. तुम्ही त्याच्या पुढील कॉपी बटणावर क्लिक करून CID कॉपी करू शकता. तुम्ही तुमचे अपलोड येथे पाहू शकता: `https://gateway.pinata.cloud/ipfs/`. उदाहरणार्थ, आम्ही IPFS वर वापरलेली प्रतिमा तुम्ही [येथे](https://gateway.pinata.cloud/ipfs/QmZdd5KYdCFApWn7eTZJ1qgJu18urJrP9Yh1TZcZrZxxB5) शोधू शकता. + +अधिक दृष्य शिकणाऱ्यांसाठी, वरील पायऱ्या येथे सारांशित केल्या आहेत: + +![तुमची प्रतिमा Pinata वर कशी अपलोड करावी](./instructionsPinata.gif) + +आता, आम्हाला Pinata वर आणखी एक दस्तऐवज अपलोड करायचा आहे. पण ते करण्यापूर्वी, आपल्याला ते तयार करणे आवश्यक आहे! + +तुमच्या रूट डिरेक्टरीमध्ये, `nft-metadata.json` नावाची एक नवीन फाईल बनवा आणि खालील json कोड जोडा: + +```json +{ + "attributes": [ + { + "trait_type": "जात", + "value": "Maltipoo" + }, + { + "trait_type": "डोळ्यांचा रंग", + "value": "Mocha" + } + ], + "description": "जगातील सर्वात मोहक आणि संवेदनशील पिल्लू.", + "image": "ipfs://QmWmvTJmJU3pozR9ZHFmQC2DNDwi2XJtf3QGyYiiagFSWb", + "name": "Ramses" +} +``` + +json मधील डेटा बदलण्यास मोकळे आहात. तुम्ही ऍट्रिब्युट्स विभागातून काढू किंवा त्यात भर घालू शकता. सर्वात महत्त्वाचे म्हणजे, इमेज फील्ड तुमच्या IPFS प्रतिमेच्या स्थानाकडे निर्देश करते याची खात्री करा — अन्यथा, तुमच्या NFT मध्ये एका (खूप गोंडस!) कुत्र्याचा फोटो समाविष्ट असेल. + +एकदा तुम्ही JSON फाईल संपादित करणे पूर्ण केले की, ती सेव्ह करा आणि प्रतिमा अपलोड करण्यासाठी आम्ही केलेल्या त्याच पायऱ्यांचे अनुसरण करून Pinata वर अपलोड करा. + +![तुमचे nft-metadata.json Pinata वर कसे अपलोड करायचे](./uploadPinata.gif) + +## पायरी ५: तुमच्या कॉन्ट्रॅक्टची एक प्रत तयार करा {#instance-contract} + +आता, आमच्या कॉन्ट्रॅक्टशी संवाद साधण्यासाठी, आपल्याला आमच्या कोडमध्ये त्याची एक प्रत तयार करणे आवश्यक आहे. असे करण्यासाठी आम्हाला आमच्या कॉन्ट्रॅक्ट ॲड्रेसची आवश्यकता असेल, जो आपण डिप्लॉयमेंटमधून किंवा [Blockscout](https://eth-sepolia.blockscout.com/) वरून तुम्ही कॉन्ट्रॅक्ट डिप्लॉय करण्यासाठी वापरलेला ॲड्रेस शोधून मिळवू शकतो. + +![Etherscan वर तुमचा कॉन्ट्रॅक्ट ॲड्रेस पहा](./view-contract-etherscan.png) + +वरील उदाहरणात, आमचा कॉन्ट्रॅक्ट ॲड्रेस 0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778 आहे. + +पुढे आपण ABI आणि ॲड्रेस वापरून आपला कॉन्ट्रॅक्ट तयार करण्यासाठी Web3 [कॉन्ट्रॅक्ट पद्धत](https://docs.web3js.org/api/web3-eth-contract/class/Contract) वापरू. तुमच्या `mint-nft.js` फाईलमध्ये, खालील गोष्टी जोडा: + +```js +const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" + +const nftContract = new web3.eth.Contract(contract.abi, contractAddress) +``` + +## पायरी ६: `.env` फाईल अपडेट करा {#update-env} + +आता, Ethereum चेनवर व्यवहार तयार करण्यासाठी आणि पाठवण्यासाठी, आम्ही खाते नॉन्स (खाली स्पष्ट करू) मिळवण्यासाठी तुमचा सार्वजनिक Ethereum खाते ॲड्रेस वापरू. + +तुमची सार्वजनिक की तुमच्या `.env` फाईलमध्ये जोडा — जर तुम्ही ट्युटोरियलचा भाग १ पूर्ण केला असेल, तर आमची `.env` फाईल आता अशी दिसेल: + +```js +API_URL = "https://eth-sepolia.g.alchemy.com/v2/तुमची-api-की" +PRIVATE_KEY = "तुमचा-खाजगी-खाते-ॲड्रेस" +PUBLIC_KEY = "तुमचा-सार्वजनिक-खाते-ॲड्रेस" +``` + +## पायरी ७: तुमचा व्यवहार तयार करा {#create-txn} + +प्रथम, `mintNFT(tokenData)` नावाचे एक फंक्शन परिभाषित करूया आणि खालील गोष्टी करून आपला व्यवहार तयार करूया: + +1. `.env` फाईलमधून तुमची _PRIVATE_KEY_ आणि _PUBLIC_KEY_ मिळवा. + +2. पुढे, आपल्याला खाते नॉन्स शोधण्याची आवश्यकता असेल. नॉन्स स्पेसिफिकेशनचा वापर तुमच्या ॲड्रेसवरून पाठवलेल्या व्यवहारांच्या संख्येचा मागोवा ठेवण्यासाठी केला जातो — ज्याची आम्हाला सुरक्षिततेच्या उद्देशाने आणि [रिप्ले हल्ले](https://docs.alchemyapi.io/resources/blockchain-glossary#account-nonce) टाळण्यासाठी आवश्यकता आहे. तुमच्या ॲड्रेसवरून पाठवलेल्या व्यवहारांची संख्या मिळवण्यासाठी, आम्ही [getTransactionCount](https://docs.alchemyapi.io/documentation/alchemy-api-reference/json-rpc#eth_gettransactioncount) वापरतो. + +3. शेवटी आम्ही खालील माहितीसह आमचा व्यवहार सेट करू: + +- `'from': PUBLIC_KEY` — आमच्या व्यवहाराचा उगम आमचा सार्वजनिक ॲड्रेस आहे + +- `'to': contractAddress` — ज्या कॉन्ट्रॅक्टशी आम्ही संवाद साधू आणि व्यवहार पाठवू इच्छितो + +- `'nonce': nonce` — आमच्या ॲड्रेसवरून पाठवलेल्या व्यवहारांच्या संख्येसह खाते नॉन्स + +- `'gas': estimatedGas` — व्यवहार पूर्ण करण्यासाठी लागणारा अंदाजित गॅस + +- `'data': nftContract.methods.mintNFT(PUBLIC_KEY, md).encodeABI()` — या व्यवहारामध्ये आपण जी गणना करू इच्छितो — जी या प्रकरणात NFT मिंट करणे आहे + +तुमची `mint-nft.js` फाईल आता अशी दिसेल: + +```js + require('dotenv').config(); + const API_URL = process.env.API_URL; + const PUBLIC_KEY = process.env.PUBLIC_KEY; + const PRIVATE_KEY = process.env.PRIVATE_KEY; + + const { createAlchemyWeb3 } = require("@alch/alchemy-web3"); + const web3 = createAlchemyWeb3(API_URL); + + const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json"); + const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778"; + const nftContract = new web3.eth.Contract(contract.abi, contractAddress); + + async function mintNFT(tokenURI) { + const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, 'latest'); //नवीनतम नॉन्स मिळवा + + //व्यवहार + const tx = { + 'from': PUBLIC_KEY, + 'to': contractAddress, + 'nonce': nonce, + 'gas': 500000, + 'data': nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI() + }; + }​ +``` + +## पायरी ८: व्यवहारावर सही करा {#sign-txn} + +आता आपण आपला व्यवहार तयार केला आहे, तो पाठवण्यासाठी आपल्याला त्यावर सही करणे आवश्यक आहे. येथे आपण आपली खाजगी की वापरू. + +`web3.eth.sendSignedTransaction` आपल्याला व्यवहाराचा हॅश देईल, ज्याचा वापर आपण आपला व्यवहार माइन झाला आहे आणि नेटवर्कद्वारे तो ड्रॉप झाला नाही याची खात्री करण्यासाठी करू शकतो. तुमच्या लक्षात येईल की व्यवहार स्वाक्षरी विभागात, आम्ही काही त्रुटी तपासणी जोडली आहे जेणेकरून आपला व्यवहार यशस्वीरित्या पार पडला की नाही हे आपल्याला कळेल. + +```js +require("dotenv").config() +const API_URL = process.env.API_URL +const PUBLIC_KEY = process.env.PUBLIC_KEY +const PRIVATE_KEY = process.env.PRIVATE_KEY + +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(API_URL) + +const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json") +const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" +const nftContract = new web3.eth.Contract(contract.abi, contractAddress) + +async function mintNFT(tokenURI) { + const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, "latest") //नवीनतम नॉन्स मिळवा + + //व्यवहार + const tx = { + from: PUBLIC_KEY, + to: contractAddress, + nonce: nonce, + gas: 500000, + data: nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI(), + } + + const signPromise = web3.eth.accounts.signTransaction(tx, PRIVATE_KEY) + signPromise + .then((signedTx) => { + web3.eth.sendSignedTransaction( + signedTx.rawTransaction, + function (err, hash) { + if (!err) { + console.log( + "तुमच्या व्यवहाराचा हॅश आहे: ", + hash, + "\nतुमच्या व्यवहाराची स्थिती पाहण्यासाठी Alchemy's Mempool तपासा!" + ) + } else { + console.log( + "तुमचा व्यवहार सबमिट करताना काहीतरी चूक झाली:", + err + ) + } + } + ) + }) + .catch((err) => { + console.log(" Promise अयशस्वी झाले:", err) + }) +} +``` + +## पायरी ९: `mintNFT` ला कॉल करा आणि नोड `mint-nft.js` चालवा {#call-mintnft-fn} + +तुम्ही Pinata वर अपलोड केलेली `metadata.json` आठवते का? Pinata वरून त्याचा हॅशकोड मिळवा आणि `mintNFT` फंक्शनला पॅरामीटर म्हणून `https://gateway.pinata.cloud/ipfs/<मेटाडेटा-हॅश-कोड>` पास करा + +हॅशकोड कसा मिळवायचा ते येथे आहे: + +![Pinata वर तुमच्या nft मेटाडेटाचा हॅशकोड कसा मिळवायचा](./metadataPinata.gif)_Pinata वर तुमच्या nft मेटाडेटाचा हॅशकोड कसा मिळवायचा_ + +> स्वतंत्र विंडोमध्ये `https://gateway.pinata.cloud/ipfs/<मेटाडेटा-हॅश-कोड>` लोड करून तुम्ही कॉपी केलेला हॅशकोड तुमच्या **metadata.json** शी लिंक आहे का हे पुन्हा तपासा. हे पेज खालील स्क्रीनशॉटसारखे दिसावे: + +![तुमच्या पेजवर json मेटाडेटा प्रदर्शित झाला पाहिजे](./metadataJSON.png)_तुमच्या पेजवर json मेटाडेटा प्रदर्शित झाला पाहिजे_ + +एकूण, तुमचा कोड काहीसा असा दिसेल: + +```js +require("dotenv").config() +const API_URL = process.env.API_URL +const PUBLIC_KEY = process.env.PUBLIC_KEY +const PRIVATE_KEY = process.env.PRIVATE_KEY + +const { createAlchemyWeb3 } = require("@alch/alchemy-web3") +const web3 = createAlchemyWeb3(API_URL) + +const contract = require("../artifacts/contracts/MyNFT.sol/MyNFT.json") +const contractAddress = "0x5a738a5c5fe46a1fd5ee7dd7e38f722e2aef7778" +const nftContract = new web3.eth.Contract(contract.abi, contractAddress) + +async function mintNFT(tokenURI) { + const nonce = await web3.eth.getTransactionCount(PUBLIC_KEY, "latest") //नवीनतम नॉन्स मिळवा + + //व्यवहार + const tx = { + from: PUBLIC_KEY, + to: contractAddress, + nonce: nonce, + gas: 500000, + data: nftContract.methods.mintNFT(PUBLIC_KEY, tokenURI).encodeABI(), + } + + const signPromise = web3.eth.accounts.signTransaction(tx, PRIVATE_KEY) + signPromise + .then((signedTx) => { + web3.eth.sendSignedTransaction( + signedTx.rawTransaction, + function (err, hash) { + if (!err) { + console.log( + "तुमच्या व्यवहाराचा हॅश आहे: ", + hash, + "\nतुमच्या व्यवहाराची स्थिती पाहण्यासाठी Alchemy's Mempool तपासा!" + ) + } else { + console.log( + "तुमचा व्यवहार सबमिट करताना काहीतरी चूक झाली:", + err + ) + } + } + ) + }) + .catch((err) => { + console.log("Promise अयशस्वी झाले:", err) + }) +} + +mintNFT("ipfs://QmYueiuRNmL4MiA2GwtVMm6ZagknXnSpQnB3z2gWbz36hP") +``` + +आता, तुमचा NFT डिप्लॉय करण्यासाठी `node scripts/mint-nft.js` चालवा. काही सेकंदांनंतर, तुम्हाला तुमच्या टर्मिनलमध्ये असा प्रतिसाद दिसेल: + + ``` + तुमच्या व्यवहाराचा हॅश आहे: 0x301791fdf492001fcd9d5e5b12f3aa1bbbea9a88ed24993a8ab2cdae2d06e1e8 + + तुमच्या व्यवहाराची स्थिती पाहण्यासाठी Alchemy's Mempool तपासा! + ``` + +पुढे, तुमच्या व्यवहाराची स्थिती (तो प्रलंबित आहे, माइन झाला आहे, किंवा नेटवर्कद्वारे ड्रॉप झाला आहे) पाहण्यासाठी तुमच्या [Alchemy mempool](https://dashboard.alchemyapi.io/mempool) ला भेट द्या. तुमचा व्यवहार ड्रॉप झाला असल्यास, [Blockscout](https://eth-sepolia.blockscout.com/) तपासणे आणि तुमच्या व्यवहाराचा हॅश शोधणे देखील उपयुक्त आहे. + +![Etherscan वर तुमचा NFT व्यवहाराचा हॅश पहा](./view-nft-etherscan.png)_Etherscan वर तुमचा NFT व्यवहाराचा हॅश पहा_ + +आणि बस्स! तुम्ही आता Ethereum ब्लॉकचेनवर एक NFT डिप्लॉय आणि मिंट केला आहे + +`mint-nft.js` वापरून तुम्ही तुमच्या मनाला (आणि वॉलेटला) हवे तितके NFTs मिंट करू शकता! फक्त NFT च्या मेटाडेटाचे वर्णन करणारा एक नवीन tokenURI पास करण्याची खात्री करा (अन्यथा, तुम्ही फक्त वेगवेगळ्या आयडीसह सारख्याच अनेक प्रती तयार कराल). + +साहजिकच, तुम्हाला तुमच्या वॉलेटमध्ये तुमचा NFT दाखवायला आवडेल — म्हणून [भाग ३: तुमच्या वॉलेटमध्ये तुमचा NFT कसा पाहावा](/developers/tutorials/how-to-view-nft-in-metamask/) नक्की पहा! diff --git a/public/content/translations/mr/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md b/public/content/translations/mr/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md new file mode 100644 index 00000000000..5faf8882a82 --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/how-to-mock-solidity-contracts-for-testing/index.md @@ -0,0 +1,108 @@ +--- +title: "चाचणीसाठी Solidity स्मार्ट कॉन्ट्रॅक्ट्सना मॉक कसे करावे" +description: "चाचणी करताना तुम्ही तुमच्या कॉन्ट्रॅक्ट्सची गंमत का करावी" +author: Markus Waas +lang: mr +tags: + [ + "सॉलिडिटी", + "स्मार्ट कॉन्ट्रॅक्ट", + "चाचणी", + "मॉक करणे" + ] +skill: intermediate +published: 2020-05-02 +source: soliditydeveloper.com +sourceUrl: https://soliditydeveloper.com/mocking-contracts +--- + +[मॉक ऑब्जेक्ट्स](https://wikipedia.org/wiki/Mock_object) हे ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंगमधील एक सामान्य डिझाइन पॅटर्न आहे. जुन्या फ्रेंच शब्द 'mocquer' ज्याचा अर्थ 'गमतीचा विषय बनवणे' आहे, त्यापासून विकसित होऊन त्याचा अर्थ 'खऱ्या गोष्टीची नक्कल करणे' असा झाला, जे आपण प्रोग्रामिंगमध्ये प्रत्यक्षात करत आहोत. तुम्हाला हवे असल्यास कृपया तुमच्या स्मार्ट कॉन्ट्रॅक्ट्सची गंमत करा, परंतु जेव्हा शक्य असेल तेव्हा त्यांना मॉक करा. हे तुमचे जीवन सोपे करते. + +## मॉकसह कॉन्ट्रॅक्ट्सची युनिट-चाचणी {#unit-testing-contracts-with-mocks} + +कॉन्ट्रॅक्ट मॉक करणे म्हणजे मूलतः त्या कॉन्ट्रॅक्टची दुसरी आवृत्ती तयार करणे जी मूळ आवृत्तीसारखीच वागते, परंतु अशा प्रकारे की डेव्हलपरद्वारे ती सहजपणे नियंत्रित केली जाऊ शकते. तुमच्याकडे अनेकदा गुंतागुंतीचे कॉन्ट्रॅक्ट्स असतात जिथे तुम्हाला फक्त [कॉन्ट्रॅक्टच्या छोट्या भागांची युनिट-चाचणी](/developers/docs/smart-contracts/testing/) करायची असते. समस्या ही आहे की, जर या छोट्या भागाची चाचणी करण्यासाठी एका विशिष्ट कॉन्ट्रॅक्ट स्थितीची आवश्यकता असेल ज्यात पोहोचणे कठीण आहे, तर काय? + +तुम्ही प्रत्येक वेळी गुंतागुंतीचे चाचणी सेटअप लॉजिक लिहू शकता जे कॉन्ट्रॅक्टला आवश्यक स्थितीत आणेल किंवा तुम्ही मॉक लिहू शकता. इनहेरिटन्ससह कॉन्ट्रॅक्ट मॉक करणे सोपे आहे. फक्त एक दुसरा मॉक कॉन्ट्रॅक्ट तयार करा जो मूळ कॉन्ट्रॅक्टमधून इनहेरिट करतो. आता तुम्ही तुमच्या मॉकसाठी फंक्शन्स ओव्हरराइड करू शकता. चला एका उदाहरणासह पाहूया. + +## उदाहरण: प्रायव्हेट ERC20 {#example-private-erc20} + +आपण एका उदाहरणादाखल ERC-20 कॉन्ट्रॅक्टचा वापर करतो ज्यामध्ये सुरुवातीला एक खाजगी वेळ असतो. मालक खाजगी वापरकर्त्यांना व्यवस्थापित करू शकतो आणि सुरुवातीला फक्त त्यांनाच टोकन मिळवण्याची परवानगी असेल. एकदा ठराविक वेळ निघून गेल्यावर, प्रत्येकाला टोकन वापरण्याची परवानगी दिली जाईल. तुम्हाला उत्सुकता असल्यास, आम्ही नवीन OpenZeppelin contracts v3 मधून [`_beforeTokenTransfer`](https://docs.openzeppelin.com/contracts/5.x/extending-contracts#using-hooks) हुक वापरत आहोत. + +```solidity +pragma solidity ^0.6.0; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract PrivateERC20 is ERC20, Ownable { + mapping (address => bool) public isPrivateUser; + uint256 private publicAfterTime; + + constructor(uint256 privateERC20timeInSec) ERC20("PrivateERC20", "PRIV") public { + publicAfterTime = now + privateERC20timeInSec; + } + + function addUser(address user) external onlyOwner { + isPrivateUser[user] = true; + } + + function isPublic() public view returns (bool) { + return now >= publicAfterTime; + } + + function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { + super._beforeTokenTransfer(from, to, amount); + + require(_validRecipient(to), "PrivateERC20: invalid recipient"); + } + + function _validRecipient(address to) private view returns (bool) { + if (isPublic()) { + return true; + } + + return isPrivateUser[to]; + } +} +``` + +आणि आता आपण ते मॉक करूया. + +```solidity +pragma solidity ^0.6.0; +import "../PrivateERC20.sol"; + +contract PrivateERC20Mock is PrivateERC20 { + bool isPublicConfig; + + constructor() public PrivateERC20(0) {} + + function setIsPublic(bool isPublic) external { + isPublicConfig = isPublic; + } + + function isPublic() public view returns (bool) { + return isPublicConfig; + } +} +``` + +तुम्हाला खालीलपैकी एक त्रुटी संदेश मिळेल: + +- `PrivateERC20Mock.sol: TypeError: Overriding function is missing "override" specifier.` +- `PrivateERC20.sol: TypeError: Trying to override non-virtual function. Did you forget to add "virtual"?.` + +आपण नवीन Solidity आवृत्ती 0.6 वापरत असल्यामुळे, ओव्हरराइड केल्या जाऊ शकणार्‍या फंक्शन्ससाठी `virtual` कीवर्ड आणि ओव्हरराइडिंग फंक्शनसाठी `override` कीवर्ड जोडावा लागेल. तर चला, हे दोन्ही `isPublic` फंक्शन्समध्ये जोडूया. + +आता तुमच्या युनिट चाचण्यांमध्ये, तुम्ही त्याऐवजी `PrivateERC20Mock` वापरू शकता. जेव्हा तुम्हाला खाजगी वापराच्या वेळेतील वर्तनाची चाचणी करायची असेल, तेव्हा `setIsPublic(false)` वापरा आणि त्याचप्रमाणे सार्वजनिक वापराच्या वेळेची चाचणी करण्यासाठी `setIsPublic(true)` वापरा. अर्थातच आपल्या उदाहरणात, आपण वेळ बदलण्यासाठी [टाइम हेल्पर्स](https://docs.openzeppelin.com/test-helpers/0.5/api#increase) देखील वापरू शकलो असतो. पण आता मॉक करण्याची कल्पना स्पष्ट झाली असेल आणि तुम्ही अशा परिस्थितीची कल्पना करू शकता जिथे फक्त वेळ पुढे नेण्याइतके सोपे नसते. + +## अनेक कॉन्ट्रॅक्ट्सना मॉक करणे {#mocking-many-contracts} + +प्रत्येक मॉकसाठी तुम्हाला दुसरा कॉन्ट्रॅक्ट तयार करावा लागल्यास ते गोंधळात टाकणारे असू शकते. जर तुम्हाला याचा त्रास होत असेल, तर तुम्ही [MockContract](https://github.com/gnosis/mock-contract) लायब्ररी पाहू शकता. हे तुम्हाला कॉन्ट्रॅक्ट्सचे वर्तन त्वरित ओव्हरराइड आणि बदलण्याची परवानगी देते. तथापि, हे फक्त दुसऱ्या कॉन्ट्रॅक्टला कॉल मॉक करण्यासाठी कार्य करते, त्यामुळे ते आपल्या उदाहरणासाठी कार्य करणार नाही. + +## मॉक करणे आणखी शक्तिशाली असू शकते {#mocking-can-be-even-more-powerful} + +मॉक करण्याची शक्ती इथेच संपत नाही. + +- फंक्शन्स जोडणे: केवळ एखादे विशिष्ट फंक्शन ओव्हरराइड करणेच उपयुक्त नाही, तर अतिरिक्त फंक्शन्स जोडणे देखील उपयुक्त आहे. टोकन्ससाठी एक चांगले उदाहरण म्हणजे फक्त एक अतिरिक्त `mint` फंक्शन असणे जे कोणत्याही वापरकर्त्याला विनामूल्य नवीन टोकन मिळविण्याची परवानगी देते. +- टेस्टनेटमध्ये वापर: जेव्हा तुम्ही तुमच्या dApp सह टेस्टनेटवर तुमचे कॉन्ट्रॅक्ट्स तैनात आणि चाचणी करता, तेव्हा मॉक केलेली आवृत्ती वापरण्याचा विचार करा. खरोखरच गरज असल्याशिवाय फंक्शन्स ओव्हरराइड करणे टाळा. शेवटी, तुम्हाला खऱ्या लॉजिकची चाचणी करायची आहे. परंतु उदाहरणार्थ, रीसेट फंक्शन जोडणे उपयुक्त ठरू शकते जे फक्त कॉन्ट्रॅक्टची स्थिती सुरुवातीला रीसेट करते, नवीन तैनातीची आवश्यकता नाही. अर्थातच तुम्हाला Mainnet कॉन्ट्रॅक्टमध्ये ते नको असेल. diff --git a/public/content/translations/mr/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md b/public/content/translations/mr/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md new file mode 100644 index 00000000000..c8ed9c7deff --- /dev/null +++ b/public/content/translations/mr/developers/tutorials/how-to-use-echidna-to-test-smart-contracts/index.md @@ -0,0 +1,708 @@ +--- +title: "स्मार्ट कॉन्ट्रॅक्ट्सची चाचणी घेण्यासाठी Echidna चा वापर कसा करावा" +description: "स्मार्ट कॉन्ट्रॅक्ट्सची आपोआप चाचणी घेण्यासाठी Echidna चा वापर कसा करावा" +author: "Trailofbits" +lang: mr +tags: + [ + "सॉलिडिटी", + "स्मार्ट कॉन्ट्रॅक्ट", + "सुरक्षा", + "चाचणी", + "fuzzing" + ] +skill: advanced +published: 2020-04-10 +source: Building secure contracts +sourceUrl: https://github.com/crytic/building-secure-contracts/tree/master/program-analysis/echidna +--- + +## इन्स्टॉलेशन {#installation} + +Echidna डॉकरद्वारे किंवा प्री-कंपाइल बायनरी वापरून इन्स्टॉल केले जाऊ शकते. + +### डॉकरद्वारे Echidna {#echidna-through-docker} + +```bash +docker pull trailofbits/eth-security-toolbox +docker run -it -v "$PWD":/home/training trailofbits/eth-security-toolbox +``` + +_शेवटचा कमांड तुमच्या सध्याच्या डिरेक्टरीमध्ये ऍक्सेस असलेल्या docker मध्ये eth-security-toolbox चालवतो. तुम्ही तुमच्या होस्टमधून फाइल्स बदलू शकता, आणि docker मधून फाइल्सवर टूल्स चालवू शकता_ + +डॉकरमध्ये, चालवा : + +```bash +solc-select 0.5.11 +cd /home/training +``` + +### बायनरी {#binary} + +[https://github.com/crytic/echidna/releases/tag/v1.4.0.0](https://github.com/crytic/echidna/releases/tag/v1.4.0.0) + +## प्रॉपर्टी-आधारित फझिंगची ओळख {#introduction-to-property-based-fuzzing} + +Echidna एक प्रॉपर्टी-आधारित फझर आहे, ज्याचे वर्णन आम्ही आमच्या मागील ब्लॉगपोस्टमध्ये केले आहे ([1](https://blog.trailofbits.com/2018/03/09/echidna-a-smart-fuzzer-for-ethereum/), [2](https://blog.trailofbits.com/2018/05/03/state-machine-testing-with-echidna/), [3](https://blog.trailofbits.com/2020/03/30/an-echidna-for-all-seasons/)). + +### फझिंग {#fuzzing} + +[Fuzzing](https://wikipedia.org/wiki/Fuzzing) हे सुरक्षा समुदायामध्ये एक सुप्रसिद्ध तंत्र आहे. यात प्रोग्राममधील बग शोधण्यासाठी कमी-अधिक प्रमाणात यादृच्छिक इनपुट तयार करणे समाविष्ट आहे. पारंपारिक सॉफ्टवेअरसाठी फझर्स (जसे की [AFL](http://lcamtuf.coredump.cx/afl/) किंवा [LibFuzzer](https://llvm.org/docs/LibFuzzer.html)) बग शोधण्यासाठी कार्यक्षम साधने म्हणून ओळखले जातात. + +केवळ यादृच्छिक इनपुट तयार करण्यापलीकडे, चांगले इनपुट तयार करण्यासाठी अनेक तंत्रे आणि धोरणे आहेत, ज्यात खालील गोष्टींचा समावेश आहे: + +- प्रत्येक अंमलबजावणीतून अभिप्राय मिळवा आणि त्याचा वापर करून पिढीला मार्गदर्शन करा. उदाहरणार्थ, जर नवीन तयार केलेल्या इनपुटमुळे नवीन मार्ग सापडला, तर त्याच्या जवळ नवीन इनपुट तयार करणे अर्थपूर्ण ठरू शकते. +- रचनात्मक मर्यादांचा आदर करून इनपुट तयार करणे. उदाहरणार्थ, जर तुमच्या इनपुटमध्ये चेकसमसह हेडर असेल, तर फझरला चेकसम प्रमाणित करणारे इनपुट तयार करू देणे अर्थपूर्ण ठरेल. +- नवीन इनपुट तयार करण्यासाठी ज्ञात इनपुट वापरणे: जर तुमच्याकडे वैध इनपुटच्या मोठ्या डेटासेटमध्ये प्रवेश असेल, तर तुमचा फझर सुरवातीपासून त्याची निर्मिती सुरू करण्याऐवजी त्यातून नवीन इनपुट तयार करू शकतो. यांना सहसा _seeds_ म्हटले जाते. + +### प्रॉपर्टी-आधारित फझिंग {#property-based-fuzzing} + +Echidna फझरच्या एका विशिष्ट कुटुंबाशी संबंधित आहे: [QuickCheck](https://wikipedia.org/wiki/QuickCheck) द्वारे मोठ्या प्रमाणावर प्रेरित प्रॉपर्टी-आधारित फझिंग. क्रॅश शोधण्याचा प्रयत्न करणाऱ्या क्लासिक फझरच्या विपरीत, Echidna वापरकर्ता-परिभाषित इनव्हेरियंट्स तोडण्याचा प्रयत्न करेल. + +स्मार्ट कॉन्ट्रॅक्ट्समध्ये, इनव्हेरियंट्स हे Solidity फंक्शन्स असतात, जे कॉन्ट्रॅक्ट पोहोचू शकणाऱ्या कोणत्याही चुकीच्या किंवा अवैध स्थितीचे प्रतिनिधित्व करू शकतात, ज्यात खालील गोष्टींचा समावेश आहे: + +- चुकीचे प्रवेश नियंत्रण: आक्रमणकर्ता कॉन्ट्रॅक्टचा मालक बनला. +- चुकीचे स्टेट मशीन: कॉन्ट्रॅक्ट थांबवलेले असताना टोकन हस्तांतरित केले जाऊ शकतात. +- चुकीचे अंकगणित: वापरकर्ता त्याचे शिल्लक कमी करू शकतो आणि अमर्यादित विनामूल्य टोकन मिळवू शकतो. + +### Echidna सह प्रॉपर्टीची चाचणी करणे {#testing-a-property-with-echidna} + +आम्ही Echidna सह स्मार्ट कॉन्ट्रॅक्टची चाचणी कशी करायची ते पाहू. लक्ष्य खालील स्मार्ट कॉन्ट्रॅक्ट आहे [`token.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol): + +```solidity +contract Token{ + mapping(address => uint) public balances; + function airdrop() public{ + balances[msg.sender] = 1000; + } + function consume() public{ + require(balances[msg.sender]>0); + balances[msg.sender] -= 1; + } + function backdoor() public{ + balances[msg.sender] += 1; + } +} +``` + +आम्ही असे गृहीत धरू की या टोकनमध्ये खालील गुणधर्म असणे आवश्यक आहे: + +- कोणाकडेही जास्तीत जास्त 1000 टोकन असू शकतात +- टोकन हस्तांतरित केले जाऊ शकत नाही (ते ERC20 टोकन नाही) + +### एक प्रॉपर्टी लिहा {#write-a-property} + +Echidna प्रॉपर्टीज या Solidity फंक्शन्स आहेत. एका प्रॉपर्टीमध्ये हे असणे आवश्यक आहे: + +- कोणतेही आर्ग्युमेंट नसावे +- यशस्वी झाल्यास `true` परत करा +- त्याचे नाव `echidna` ने सुरू झाले पाहिजे + +Echidna हे करेल: + +- प्रॉपर्टीची चाचणी घेण्यासाठी आपोआप अनियंत्रित व्यवहार तयार करा. +- एखाद्या प्रॉपर्टीला `false` परत करण्यास किंवा त्रुटी निर्माण करण्यास कारणीभूत ठरलेल्या कोणत्याही व्यवहारांची तक्रार करा. +- प्रॉपर्टी कॉल करताना साईड-इफेक्ट टाळा (म्हणजे, जर प्रॉपर्टी स्टेट व्हेरिएबल बदलत असेल, तर चाचणीनंतर ते टाकून दिले जाते) + +खालील प्रॉपर्टी तपासते की कॉलरकडे 1000 पेक्षा जास्त टोकन नाहीत: + +```solidity +function echidna_balance_under_1000() public view returns(bool){ + return balances[msg.sender] <= 1000; +} +``` + +तुमच्या कॉन्ट्रॅक्टला तुमच्या प्रॉपर्टीजपासून वेगळे करण्यासाठी इनहेरिटन्स वापरा: + +```solidity +contract TestToken is Token{ + function echidna_balance_under_1000() public view returns(bool){ + return balances[msg.sender] <= 1000; + } + } +``` + +[`token.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/token.sol) प्रॉपर्टी लागू करते आणि टोकनमधून इनहेरिट करते. + +### एक कॉन्ट्रॅक्ट सुरू करा {#initiate-a-contract} + +Echidna ला आर्ग्युमेंटशिवाय [constructor](/developers/docs/smart-contracts/anatomy/#constructor-functions) ची आवश्यकता आहे. जर तुमच्या कॉन्ट्रॅक्टला विशिष्ट इनिशिएलायझेशनची आवश्यकता असेल, तर तुम्हाला ते कन्स्ट्रक्टरमध्ये करावे लागेल. + +Echidna मध्ये काही विशिष्ट ॲड्रेसेस आहेत: + +- `0x00a329c0648769A73afAc7F9381E08FB43dBEA72` जे कन्स्ट्रक्टरला कॉल करते. +- `0x10000`, `0x20000`, आणि `0x00a329C0648769a73afAC7F9381e08fb43DBEA70` जे यादृच्छिकपणे इतर फंक्शन्सना कॉल करतात. + +आमच्या सध्याच्या उदाहरणात आम्हाला कोणत्याही विशिष्ट इनिशिएलायझेशनची आवश्यकता नाही, परिणामी आमचा कन्स्ट्रक्टर रिकामा आहे. + +### Echidna चालवा {#run-echidna} + +Echidna यासह लॉन्च केले जाते: + +```bash +echidna-test contract.sol +``` + +जर contract.sol मध्ये अनेक कॉन्ट्रॅक्ट्स असतील, तर तुम्ही लक्ष्य निर्दिष्ट करू शकता: + +```bash +echidna-test contract.sol --contract MyContract +``` + +### सारांश: एका प्रॉपर्टीची चाचणी करणे {#summary-testing-a-property} + +खालील आमच्या उदाहरणावरील Echidna च्या रनचा सारांश देते: + +```solidity +contract TestToken is Token{ + constructor() public {} + function echidna_balance_under_1000() public view returns(bool){ + return balances[msg.sender] <= 1000; + } + } +``` + +```bash +echidna-test testtoken.sol --contract TestToken +... + +echidna_balance_under_1000: failed!💥 + Call sequence, shrinking (1205/5000): + airdrop() + backdoor() + +... +``` + +Echidna ला आढळले की जर `backdoor` कॉल केला तर प्रॉपर्टीचे उल्लंघन होते. + +## फझिंग मोहिमेदरम्यान कॉल करण्यासाठी फंक्शन्स फिल्टर करणे {#filtering-functions-to-call-during-a-fuzzing-campaign} + +आम्ही फझ करण्यासाठी फंक्शन्स कसे फिल्टर करायचे ते पाहू. +लक्ष्य खालील स्मार्ट कॉन्ट्रॅक्ट आहे: + +```solidity +contract C { + bool state1 = false; + bool state2 = false; + bool state3 = false; + bool state4 = false; + + function f(uint x) public { + require(x == 12); + state1 = true; + } + + function g(uint x) public { + require(state1); + require(x == 8); + state2 = true; + } + + function h(uint x) public { + require(state2); + require(x == 42); + state3 = true; + } + + function i() public { + require(state3); + state4 = true; + } + + function reset1() public { + state1 = false; + state2 = false; + state3 = false; + return; + } + + function reset2() public { + state1 = false; + state2 = false; + state3 = false; + return; + } + + function echidna_state4() public returns (bool) { + return (!state4); + } +} +``` + +हे लहान उदाहरण Echidna ला स्टेट व्हेरिएबल बदलण्यासाठी व्यवहारांचा एक विशिष्ट क्रम शोधण्यास भाग पाडते. +हे फझरसाठी कठीण आहे (यासाठी [Manticore](https://github.com/trailofbits/manticore) सारखे सिम्बॉलिक एक्झिक्युशन टूल वापरण्याची शिफारस केली जाते). +हे तपासण्यासाठी आपण Echidna चालवू शकतो: + +```bash +echidna-test multi.sol +... +echidna_state4: passed! 🎉 +Seed: -3684648582249875403 +``` + +### फिल्टरिंग फंक्शन्स {#filtering-functions} + +Echidna ला या कॉन्ट्रॅक्टची चाचणी घेण्यासाठी योग्य क्रम शोधण्यात अडचण येत आहे कारण दोन रीसेट फंक्शन्स (`reset1` आणि `reset2`) सर्व स्टेट व्हेरिएबल्स `false` वर सेट करतील. +तथापि, आपण एक विशेष Echidna वैशिष्ट्य वापरू शकतो, एकतर रीसेट फंक्शनला ब्लॅकलिस्ट करण्यासाठी किंवा फक्त `f`, `g`, +`h` आणि `i` फंक्शन्सना व्हाइटलिस्ट करण्यासाठी. + +फंक्शन्स ब्लॅकलिस्ट करण्यासाठी, आम्ही ही कॉन्फिगरेशन फाइल वापरू शकतो: + +```yaml +filterBlacklist: true +filterFunctions: ["reset1", "reset2"] +``` + +फंक्शन्स फिल्टर करण्याचा दुसरा दृष्टिकोन म्हणजे व्हाइटलिस्ट केलेल्या फंक्शन्सची यादी करणे. ते करण्यासाठी, आम्ही ही कॉन्फिगरेशन फाइल वापरू शकतो: + +```yaml +filterBlacklist: false +filterFunctions: ["f", "g", "h", "i"] +``` + +- `filterBlacklist` हे डीफॉल्टनुसार `true` असते. +- फिल्टरिंग केवळ नावाने केले जाईल (पॅरामीटर्सशिवाय). जर तुमच्याकडे `f()` आणि `f(uint256)` असेल, तर `"f"` फिल्टर दोन्ही फंक्शन्सना जुळेल. + +### Echidna चालवा {#run-echidna-1} + +`blacklist.yaml` कॉन्फिगरेशन फाइलसह Echidna चालवण्यासाठी: + +```bash +echidna-test multi.sol --config blacklist.yaml +... +echidna_state4: failed!💥 + Call sequence: + f(12) + g(8) + h(42) + i() +``` + +Echidna जवळजवळ त्वरित प्रॉपर्टीला खोटे ठरवण्यासाठी व्यवहारांचा क्रम शोधेल. + +### सारांश: फिल्टरिंग फंक्शन्स {#summary-filtering-functions} + +Echidna फझिंग मोहिमेदरम्यान कॉल करण्यासाठी फंक्शन्स ब्लॅकलिस्ट किंवा व्हाइटलिस्ट करू शकते: + +```yaml +filterBlacklist: true +filterFunctions: ["f1", "f2", "f3"] +``` + +```bash +echidna-test contract.sol --config config.yaml +... +``` + +`filterBlacklist` बुलियनच्या मूल्यांनुसार Echidna `f1`, `f2` आणि `f3` ला ब्लॅकलिस्ट करून किंवा फक्त त्यांना कॉल करून फझिंग मोहीम सुरू करते. + +## Echidna सह Solidity's assert ची चाचणी कशी करावी {#how-to-test-soliditys-assert-with-echidna} + +या लहान ट्युटोरियलमध्ये, आम्ही कॉन्ट्रॅक्ट्समध्ये अॅसर्शन चेकिंगची चाचणी घेण्यासाठी Echidna चा वापर कसा करायचा हे दाखवणार आहोत. समजा आपल्याकडे यासारखा एक कॉन्ट्रॅक्ट आहे: + +```solidity +contract Incrementor { + uint private counter = 2**200; + + function inc(uint val) public returns (uint){ + uint tmp = counter; + counter += val; + // tmp <= counter + return (counter - tmp); + } +} +``` + +### एक अॅसर्शन लिहा {#write-an-assertion} + +त्यातील फरक परत केल्यानंतर `tmp` हे `counter` पेक्षा कमी किंवा समान आहे याची आम्ही खात्री करू इच्छितो. आपण Echidna +प्रॉपर्टी लिहू शकतो, पण आपल्याला `tmp` मूल्य कुठेतरी साठवावे लागेल. त्याऐवजी, आपण यासारखे अॅसर्शन वापरू शकतो: + +```solidity +contract Incrementor { + uint private counter = 2**200; + + function inc(uint val) public returns (uint){ + uint tmp = counter; + counter += val; + assert (tmp <= counter); + return (counter - tmp); + } +} +``` + +### Echidna चालवा {#run-echidna-2} + +अॅसर्शन अयशस्वी चाचणी सक्षम करण्यासाठी, एक [Echidna कॉन्फिगरेशन फाइल](https://github.com/crytic/echidna/wiki/Config) `config.yaml` तयार करा: + +```yaml +checkAsserts: true +``` + +जेव्हा आपण Echidna मध्ये हा कॉन्ट्रॅक्ट चालवतो, तेव्हा आपल्याला अपेक्षित परिणाम मिळतात: + +```bash +echidna-test assert.sol --config config.yaml +Analyzing contract: assert.sol:Incrementor +assertion in inc: failed!💥 + Call sequence, shrinking (2596/5000): + inc(21711016731996786641919559689128982722488122124807605757398297001483711807488) + inc(7237005577332262213973186563042994240829374041602535252466099000494570602496) + inc(86844066927987146567678238756515930889952488499230423029593188005934847229952) + +Seed: 1806480648350826486 +``` + +तुम्ही बघू शकता, Echidna `inc` फंक्शनमध्ये काही अॅसर्शन अयशस्वी झाल्याची तक्रार करते. प्रत्येक फंक्शनमध्ये एकापेक्षा जास्त अॅसर्शन जोडणे शक्य आहे, परंतु कोणते अॅसर्शन अयशस्वी झाले हे Echidna सांगू शकत नाही. + +### अॅसर्शन्स केव्हा आणि कसे वापरावे {#when-and-how-use-assertions} + +अॅसर्शन्स स्पष्ट प्रॉपर्टीजसाठी पर्याय म्हणून वापरले जाऊ शकतात, विशेषतः जर तपासण्याची परिस्थिती थेट काही ऑपरेशन `f` च्या योग्य वापराशी संबंधित असेल. काही कोडनंतर अॅसर्शन्स जोडल्याने हे सुनिश्चित होईल की तपासणी त्याच्या अंमलबजावणीनंतर लगेच होईल: + +```solidity +function f(..) public { + // काही जटिल कोड + ... + assert (condition); + ... +} + +``` + +याउलट, स्पष्ट Echidna प्रॉपर्टी वापरल्याने व्यवहार यादृच्छिकपणे अंमलात येतील आणि ते केव्हा तपासले जाईल हे लागू करण्याचा कोणताही सोपा मार्ग नाही. हा वर्कअराउंड करणे अजूनही शक्य आहे: + +```solidity +function echidna_assert_after_f() public returns (bool) { + f(..); + return(condition); +} +``` + +तथापि, काही समस्या आहेत: + +- जर `f` हे `internal` किंवा `external` म्हणून घोषित केले असेल तर ते अयशस्वी होते. +- `f` ला कॉल करण्यासाठी कोणते आर्ग्युमेंट्स वापरावे हे अस्पष्ट आहे. +- जर `f` रिव्हर्ट झाले, तर प्रॉपर्टी अयशस्वी होईल. + +सर्वसाधारणपणे, आम्ही अॅसर्शन्स कसे वापरावे यावर [जॉन रेगेहर यांच्या शिफारसीचे](https://blog.regehr.org/archives/1091) पालन करण्याची शिफारस करतो: + +- अॅसर्शन तपासणी दरम्यान कोणताही साईड इफेक्ट जबरदस्तीने करू नका. उदाहरणार्थ: `assert(ChangeStateAndReturn() == 1)` +- स्पष्ट विधाने निश्चित करू नका. उदाहरणार्थ, `assert(var >= 0)` जेथे `var` हे `uint` म्हणून घोषित केले आहे. + +शेवटी, कृपया `assert` ऐवजी `require` **वापरू नका**, कारण Echidna ते शोधू शकणार नाही (परंतु कॉन्ट्रॅक्ट तरीही रिव्हर्ट होईल). + +### सारांश: अॅसर्शन चेकिंग {#summary-assertion-checking} + +खालील आमच्या उदाहरणावरील Echidna च्या रनचा सारांश देते: + +```solidity +contract Incrementor { + uint private counter = 2**200; + + function inc(uint val) public returns (uint){ + uint tmp = counter; + counter += val; + assert (tmp <= counter); + return (counter - tmp); + } +} +``` + +```bash +echidna-test assert.sol --config config.yaml +Analyzing contract: assert.sol:Incrementor +assertion in inc: failed!💥 + Call sequence, shrinking (2596/5000): + inc(21711016731996786641919559689128982722488122124807605757398297001483711807488) + inc(7237005577332262213973186563042994240829374041602535252466099000494570602496) + inc(86844066927987146567678238756515930889952488499230423029593188005934847229952) + +Seed: 1806480648350826486 +``` + +Echidna ला आढळले की `inc` मधील अॅसर्शन अयशस्वी होऊ शकते जर हे फंक्शन मोठ्या आर्ग्युमेंट्ससह अनेक वेळा कॉल केले गेले. + +## Echidna कॉर्पस गोळा करणे आणि त्यात बदल करणे {#collecting-and-modifying-an-echidna-corpus} + +आम्ही Echidna सह व्यवहारांचा कॉर्पस कसा गोळा करायचा आणि वापरायचा ते पाहू. लक्ष्य खालील स्मार्ट कॉन्ट्रॅक्ट आहे [`magic.sol`](https://github.com/crytic/building-secure-contracts/blob/master/program-analysis/echidna/example/magic.sol): + +```solidity +contract C { + bool value_found = false; + function magic(uint magic_1, uint magic_2, uint magic_3, uint magic_4) public { + require(magic_1 == 42); + require(magic_2 == 129); + require(magic_3 == magic_4+333); + value_found = true; + return; + } + + function echidna_magic_values() public returns (bool) { + return !value_found; + } + +} +``` + +हे लहान उदाहरण Echidna ला स्टेट व्हेरिएबल बदलण्यासाठी काही विशिष्ट मूल्ये शोधण्यास भाग पाडते. हे फझरसाठी कठीण आहे +(यासाठी [Manticore](https://github.com/trailofbits/manticore) सारखे सिम्बॉलिक एक्झिक्युशन टूल वापरण्याची शिफारस केली जाते). +हे तपासण्यासाठी आपण Echidna चालवू शकतो: + +```bash +echidna-test magic.sol +... + +echidna_magic_values: passed! 🎉 + +Seed: 2221503356319272685 +``` + +तथापि, ही फझिंग मोहीम चालवताना कॉर्पस गोळा करण्यासाठी आम्ही अजूनही Echidna वापरू शकतो. + +### कॉर्पस गोळा करणे {#collecting-a-corpus} + +कॉर्पस संकलन सक्षम करण्यासाठी, एक कॉर्पस डिरेक्टरी तयार करा: + +```bash +mkdir corpus-magic +``` + +आणि एक [Echidna कॉन्फिगरेशन फाइल](https://github.com/crytic/echidna/wiki/Config) `config.yaml`: + +```yaml +coverage: true +corpusDir: "corpus-magic" +``` + +आता आपण आपले टूल चालवू शकतो आणि गोळा केलेला कॉर्पस तपासू शकतो: + +```bash +echidna-test magic.sol --config config.yaml +``` + +Echidna अजूनही योग्य मॅजिक व्हॅल्यूज शोधू शकत नाही, परंतु आपण त्याने गोळा केलेल्या कॉर्पसवर एक नजर टाकू शकतो. +उदाहरणार्थ, यापैकी एक फाइल होती: + +```json +[ + { + "_gas'": "0xffffffff", + "_delay": ["0x13647", "0xccf6"], + "_src": "00a329c0648769a73afac7f9381e08fb43dbea70", + "_dst": "00a329c0648769a73afac7f9381e08fb43dbea72", + "_value": "0x0", + "_call": { + "tag": "SolCall", + "contents": [ + "magic", + [ + { + "contents": [ + 256, + "93723985220345906694500679277863898678726808528711107336895287282192244575836" + ], + "tag": "AbiUInt" + }, + { + "contents": [256, "334"], + "tag": "AbiUInt" + }, + { + "contents": [ + 256, + "68093943901352437066264791224433559271778087297543421781073458233697135179558" + ], + "tag": "AbiUInt" + }, + { + "tag": "AbiUInt", + "contents": [256, "332"] + } + ] + ] + }, + "_gasprice'": "0xa904461f1" + } +] +``` + +स्पष्टपणे, हे इनपुट आमच्या प्रॉपर्टीमध्ये अपयश आणणार नाही. तथापि, पुढील चरणात, आम्ही त्यासाठी त्यात कसे बदल करायचे ते पाहू. + +### कॉर्पस सीडिंग करणे {#seeding-a-corpus} + +`magic` फंक्शन हाताळण्यासाठी Echidna ला काही मदतीची गरज आहे. आम्ही इनपुट कॉपी करणार आहोत आणि त्यासाठी योग्य +पॅरामीटर्स वापरण्यासाठी त्यात बदल करणार आहोत: + +```bash +cp corpus/2712688662897926208.txt corpus/new.txt +``` + +आम्ही `magic(42,129,333,0)` ला कॉल करण्यासाठी `new.txt` मध्ये बदल करू. आता, आपण Echidna पुन्हा चालवू शकतो: + +```bash +echidna-test magic.sol --config config.yaml +... +echidna_magic_values: failed!💥 + Call sequence: + magic(42,129,333,0) + + +Unique instructions: 142 +Unique codehashes: 1 +Seed: -7293830866560616537 + +``` + +यावेळी, त्याला आढळले की प्रॉपर्टीचे त्वरित उल्लंघन झाले आहे. + +## उच्च गॅस वापरासह व्यवहार शोधणे {#finding-transactions-with-high-gas-consumption} + +आम्ही Echidna सह उच्च गॅस वापरासह व्यवहार कसे शोधायचे ते पाहू. लक्ष्य खालील स्मार्ट कॉन्ट्रॅक्ट आहे: + +```solidity +contract C { + uint state; + + function expensive(uint8 times) internal { + for(uint8 i=0; i < times; i++) + state = state + i; + } + + function f(uint x, uint y, uint8 times) public { + if (x == 42 && y == 123) + expensive(times); + else + state = 0; + } + + function echidna_test() public returns (bool) { + return true; + } + +} +``` + +येथे `expensive` मध्ये मोठा गॅस वापर असू शकतो. + +सध्या, Echidna ला नेहमी चाचणीसाठी एक प्रॉपर्टीची आवश्यकता असते: येथे `echidna_test` नेहमी `true` परत करते. +हे तपासण्यासाठी आपण Echidna चालवू शकतो: + +``` +echidna-test gas.sol +... +echidna_test: passed! 🎉 + +Seed: 2320549945714142710 +``` + +### गॅस वापर मोजणे {#measuring-gas-consumption} + +Echidna सह गॅस वापर सक्षम करण्यासाठी, एक कॉन्फिगरेशन फाइल `config.yaml` तयार करा: + +```yaml +estimateGas: true +``` + +या उदाहरणात, आम्ही परिणाम समजण्यास सोपे करण्यासाठी व्यवहार क्रमाचा आकार देखील कमी करू: + +```yaml +seqLen: 2 +estimateGas: true +``` + +### Echidna चालवा {#run-echidna-3} + +एकदा आम्ही कॉन्फिगरेशन फाइल तयार केल्यावर, आम्ही Echidna याप्रमाणे चालवू शकतो: + +```bash +echidna-test gas.sol --config config.yaml +... +echidna_test: passed! 🎉 + +f used a maximum of 1333608 gas + Call sequence: + f(42,123,249) Gas price: 0x10d5733f0a Time delay: 0x495e5 Block delay: 0x88b2 + +Unique instructions: 157 +Unique codehashes: 1 +Seed: -325611019680165325 + +``` + +- दाखवलेला गॅस हा [HEVM](https://github.com/dapphub/dapptools/tree/master/src/hevm#hevm-) द्वारे प्रदान केलेला एक अंदाज आहे. + +### गॅस-कमी करणारे कॉल्स फिल्टर करणे {#filtering-out-gas-reducing-calls} + +वरील **फझिंग मोहिमेदरम्यान कॉल करण्यासाठी फंक्शन्स फिल्टर करणे** यावरील ट्युटोरियल तुमच्या चाचणीमधून काही फंक्शन्स कसे काढायचे हे दाखवते. +अचूक गॅस अंदाज मिळवण्यासाठी हे महत्त्वपूर्ण असू शकते. +खालील उदाहरण विचारात घ्या: + +```solidity +contract C { + address [] addrs; + function push(address a) public { + addrs.push(a); + } + function pop() public { + addrs.pop(); + } + function clear() public{ + addrs.length = 0; + } + function check() public{ + for(uint256 i = 0; i < addrs.length; i++) + for(uint256 j = i+1; j < addrs.length; j++) + if (addrs[i] == addrs[j]) + addrs[j] = address(0x0); + } + function echidna_test() public returns (bool) { + return true; + } +} +``` + +जर Echidna सर्व फंक्शन्सना कॉल करू शकत असेल, तर त्याला उच्च गॅस खर्चासह व्यवहार सहज सापडणार नाहीत: + +``` +echidna-test pushpop.sol --config config.yaml +... +pop used a maximum of 10746 gas +... +check used a maximum of 23730 gas +... +clear used a maximum of 35916 gas +... +push used a maximum of 40839 gas +``` + +कारण खर्च `addrs` च्या आकारावर अवलंबून असतो आणि यादृच्छिक कॉल्समुळे ॲरे जवळजवळ रिकामा राहतो. +तथापि, `pop` आणि `clear` ला ब्लॅकलिस्ट केल्याने आम्हाला बरेच चांगले परिणाम मिळतात: + +```yaml +filterBlacklist: true +filterFunctions: ["pop", "clear"] +``` + +``` +echidna-test pushpop.sol --config config.yaml +... +push used a maximum of 40839 gas +... +check used a maximum of 1484472 gas +``` + +### सारांश: उच्च गॅस वापरासह व्यवहार शोधणे {#summary-finding-transactions-with-high-gas-consumption} + +`estimateGas` कॉन्फिगरेशन पर्याय वापरून Echidna उच्च गॅस वापरासह व्यवहार शोधू शकते: + +```yaml +estimateGas: true +``` + +```bash +echidna-test contract.sol --config config.yaml +... +``` + +एकदा फझिंग मोहीम संपली की, Echidna प्रत्येक फंक्शनसाठी कमाल गॅस वापरासह एक क्रम नोंदवेल.