<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های Ali Naghiee</title><link>https://virgool.ir/feed/@ali-naghiee</link><description></description><language>fa</language><pubDate>2026-11-11 08:59:02</pubDate><image><url>https://files.virgool.ir/upload/users/2882980/avatar/jvFcc6.jpg</url><title>Ali Naghiee</title><link>https://virgool.ir/@ali-naghiee</link></image><item><title>توسعه اپلیکیشن اتریوم با استفاده از Go - کیف پول - 3</title><link>https://virgool.ir/@ali-naghiee/توسعه-اپلیکیشن-اتریوم-با-استفاده-از-go-کیف-پول-3-kdrdiovf6o5g</link><description>فهرست مقدمه و کلاینتاکانتکیف پول &lt;-ایجاد کیف پول جدیدبرای ساختن یک کیف پول جدید، اول باید پکیج crypto از go-ethereum رو ایمپورت کنیم، داخل این پکیج متد GenerateKey هست که یه کلید خصوصی رندوم تولید می‌کنه.privateKey, err := crypto.GenerateKey()بعدش می‌تونیم این کلید رو به بایت تبدیل کنیم. برای این کار باید پکیج crypto/ecdsa رو ایمپورت کنیم و از متد FromECDSA‌ استفاده کنیم.privateKeyBytes := crypto.FromECDSA(privateKey)حالا می‌تونیم این بایت‌ها رو به یک string مبنای ۱۶ تبدیل کنیم. برای این کار از پکیج hexutil از go-ethereum استفاده می‌کنیم که متد Encode توش هست و یه آرایه بایت می‌گیره. بعد از Encode کردن به مبنای ۱۶، 0x اول رشته یا دو کاراکتر اولش رو حذف می‌کنیم.fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) // fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19این کلید خصوصی هست که برای امضای تراکنش‌ها استفاده میشه و باید مثل رمزعبور حفاظت بشه و هرگز به اشتراک گذاشته نشه، چون هر کسی که به این کلید دسترسی داشته باشه، می‌تونه به تمام موجودی شما دسترسی پیدا کنه.از اونجایی که کلید عمومی از کلید خصوصی به دست میاد، کلید خصوصی توی go-ethereum یه متد به اسم Public داره که کلید عمومی رو برمی‌گردونه.publicKey := privateKey.Public()تبدیل این کلید عمومی به مبنای 16 مشابه فرایندی هست که برای کلید خصوصی انجام دادیم. اول نوعش رو به ecdsa.PublicKey تغییر میدیم، 0x اول رشته و 2 کاراکتر دیگه 04 که پیشوند EC هست و نیازی بهشون نداریم رو حذف می‌کنیم.publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)&#xA;if !ok {&#xA;  log.Fatal(&#34;cannot assert type: publicKey is not of type *ecdsa.PublicKey&#34;)&#xA;}&#xA;&#xA;publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)&#xA;fmt.Println(hexutil.Encode(publicKeyBytes)[4:]) // 9a7df67f79246283fdc93af76d4f8cdd62c4886e8cd870944e817dd0b97934fdd7719d0810951e03418205868a5c1b40b192451367f28e0088dd75e15de40c05حالا که کلید عمومی رو داریم، می‌تونیم به راحتی آدرس عمومی رو هم تولید کنیم، این آدرس همون چیزیه که معمولا عادت داریم ببینیم. برای این کار، پکیج crypto توی go-ethereum یه متد PubkeyToAddress داره که کلید عمومی ECDSA می‌گیره و آدرس عمومی مربوط به اون رو برمی‌گردونه.address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()&#xA;fmt.Println(address) // 0x96216849c49358B10257cb55b28eA603c874b05Eآدرس عمومی فقط هش Keccak-256 کلید عمومی هست که از اون 40 کاراکتر آخر (20 بایت) رو انتخاب می‌کنیم و 0x رو به اولش اضافه می‌کنیم. اینجا نحوه انجام دستی این کار با استفاده از تابع keccak256 تو پکیج crypto/sha3 رو نشون دادیم.hash := sha3.NewLegacyKeccak256()&#xA;hash.Write(publicKeyBytes[1:])&#xA;fmt.Println(hexutil.Encode(hash.Sum(nil)[12:])) // 0x96216849c49358b10257cb55b28ea603c874b05eکد کاملpackage main&#xA;&#xA;import (&#xA;&#x9;&#34;crypto/ecdsa&#34;&#xA;&#x9;&#34;fmt&#34;&#xA;&#x9;&#34;log&#34;&#xA;&#xA;&#x9;&#34;github.com/ethereum/go-ethereum/common/hexutil&#34;&#xA;&#x9;&#34;github.com/ethereum/go-ethereum/crypto&#34;&#xA;&#x9;&#34;golang.org/x/crypto/sha3&#34;&#xA;)&#xA;&#xA;func main() {&#xA;&#x9;privateKey, err := crypto.GenerateKey()&#xA;&#x9;if err != nil {&#xA;&#x9;&#x9;log.Fatal(err)&#xA;&#x9;}&#xA;&#xA;&#x9;privateKeyBytes := crypto.FromECDSA(privateKey)&#xA;&#x9;fmt.Println(hexutil.Encode(privateKeyBytes)[2:]) // fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19&#xA;&#xA;&#x9;publicKey := privateKey.Public()&#xA;&#x9;publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)&#xA;&#x9;if !ok {&#xA;&#x9;&#x9;log.Fatal(&#34;cannot assert type: publicKey is not of type *ecdsa.PublicKey&#34;)&#xA;&#x9;}&#xA;&#xA;&#x9;publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)&#xA;&#x9;fmt.Println(&#xA;&#x9;&#x9;hexutil.Encode(publicKeyBytes)[4:],&#xA;&#x9;) //&#xA;9a7df67f79246283fdc93af76d4f8cdd62c4886e8cd870944e817dd0b97934fdd7719d0810951e03418205868a5c1b40b192451367f28e0088dd75e15de40c05&#xA;&#xA;&#x9;address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()&#xA;&#x9;fmt.Println(address) // 0x96216849c49358B10257cb55b28eA603c874b05E&#xA;&#xA;&#x9;hash := sha3.NewLegacyKeccak256()&#xA;&#x9;hash.Write(publicKeyBytes[1:])&#xA;&#x9;fmt.Println(hexutil.Encode(hash.Sum(nil)[12:])) // 0x96216849c49358b10257cb55b28ea603c874b05e&#xA;}ذخیره کلید و Keystore هابا استفاده از go-ethereum یه پکیج مدیریت حساب ساده ولی کامل در اختیار داریم که تمام ابزارای لازم برای پیاده‌سازی امن عملیات رمزنگاری تو یه برنامه بومی Go رو داره. مدیریت حساب‌ها سمت کلاینت انجام می‌شه و همه داده‌های حساس تو خود برنامه نگهداری می‌شن. این باعث می‌شه کنترل دسترسی‌ها بدون وابستگی به شخص ثالثی دست خود کاربر باشه. این Keystore ها به توسعه دهنده امکان ذخیره سازی امن کلیدها و اطلاعات حساس حساب ها رو میدن.هر فایل Keystore متشکل از کلید خصوصی رمزنگاری شده یک کیف پوله. Keystore ها توی go-ethereum فقط می‌تونن حاوی یک جفت کلید کیف پول در هر فایل باشن. برای تولید Keystore اول باید متد NewKeyStore رو صدا بزنیم و مسیر ذخیره Keystore ها رو بهش بدیم. بعد از اون می‌تونیم با صدا زدن متد NewAccount و پاس دادن یک رمزعبور برای رمزگذاری اطلاعات، یک کیف پول جدید تولید کنیم. هربار که NewAccount صدا زده بشه، یک فایل Keystore جدید روی دیسک ذخیره می‌شه.این یک مثال کامل از تولید یک حساب کیف پول جدیده:ks := keystore.NewKeyStore(&#34;./wallets&#34;, keystore.StandardScryptN, keystore.StandardScryptP)&#xA;password := &#34;secret&#34;&#xA;account, err := ks.NewAccount(password)&#xA;if err != nil {&#xA;  log.Fatal(err)&#xA;}&#xA;&#xA;fmt.Println(account.Address.Hex()) // 0x20F8D42FB0F667F2E53930fed426f225752453b3دو آرگیومنت آخر متد NewKeyStore پارامترهای رمزنگاری هستن که مشخص می‌کنن رمزگذاری keystore چقدر منابع مصرف کنه. گزینه‌هایی که میشه استفاده کرد StandardScryptN و StandardScryptP، همینطور LightScryptN و LightScryptP یا مقادیر سفارشی هستن. به طور کلی نسخه استاندارد توصیه می‌شه.حالا برای ایمپورت کردن Keystore فقط کافیه دوباره مثل قبل NewKeyStore رو صدا بزنیم و بعد متد Import رو استفاده کنیم که محتوای جیسون Keystore رو به شکل بایت دریافت می‌کنه. آرگیومنت دوم هم همون رمزعبوری هست که برای رمزگذاری استفاده شده تا Keystore رو رمزگشایی کنه. آرگیومنت سوم هم برای مشخص کردن یک رمزعبور رمزگذاری جدید هست ولی توی این مثال از همون رمز قبلی استفاده می‌کنیم. با ایمپورت کردن Keystore دسترسی مورد نظر به حساب رو پیدا میکنیم ولی یک فایل Keystore جدید هم تولید می‌شه! نگه داشتن دوتا فایل یکسان بی‌معنیه، پس فایل قدیمی رو حذف می‌کنیم.اینجا هم یک مثال از ایمپورت کردن Keystore و دسترسی به حساب رو داریم:file := &#34;./wallets/UTC--2018-07-04T09-58-30.122808598Z--20f8d42fb0f667f2e53930fed426f225752453b3&#34;&#xA;ks := keystore.NewKeyStore(&#34;./tmp&#34;, keystore.StandardScryptN, keystore.StandardScryptP)&#xA;jsonBytes, err := ioutil.ReadFile(file)&#xA;if err != nil {&#xA;  log.Fatal(err)&#xA;}&#xA;&#xA;password := &#34;secret&#34;&#xA;account, err := ks.Import(jsonBytes, password, password)&#xA;if err != nil {&#xA;  log.Fatal(err)&#xA;}&#xA;&#xA;fmt.Println(account.Address.Hex()) // 0x20F8D42FB0F667F2E53930fed426f225752453b3&#xA;&#xA;if err := os.Remove(file); err != nil {&#xA;  log.Fatal(err)&#xA;}برای اطلاعات بیشتر در مورد Keystore ها و چرخه استفادشون میتونید به این لینک از داکیومنتیشن اصلی مراجعه کنید.کد کاملpackage main&#xA;&#xA;import (&#xA;    &#34;fmt&#34;&#xA;    &#34;io/ioutil&#34;&#xA;    &#34;log&#34;&#xA;    &#34;os&#34;&#xA;&#xA;    &#34;github.com/ethereum/go-ethereum/accounts/keystore&#34;&#xA;)&#xA;&#xA;func createKs() {&#xA;    ks := keystore.NewKeyStore(&#34;./tmp&#34;, keystore.StandardScryptN, keystore.StandardScryptP)&#xA;    password := &#34;secret&#34;&#xA;    account, err := ks.NewAccount(password)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    fmt.Println(account.Address.Hex()) // 0x20F8D42FB0F667F2E53930fed426f225752453b3&#xA;}&#xA;&#xA;func importKs() {&#xA;    file := &#34;./tmp/UTC--2018-07-04T09-58-30.122808598Z--20f8d42fb0f667f2e53930fed426f225752453b3&#34;&#xA;    ks := keystore.NewKeyStore(&#34;./tmp&#34;, keystore.StandardScryptN,&#xA;keystore.StandardScryptP)&#xA;    jsonBytes, err := ioutil.ReadFile(file)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    password := &#34;secret&#34;&#xA;    account, err := ks.Import(jsonBytes, password, password)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    fmt.Println(account.Address.Hex()) // 0x20F8D42FB0F667F2E53930fed426f225752453b3&#xA;&#xA;    if err := os.Remove(file); err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;}&#xA;&#xA;func main() {&#xA;    createKs()&#xA;    //importKs()&#xA;}راه حل دیگه ای که برای ایجاد کیف پول اتریوم داریم استفاده از HD wallet هست که احتمال زیاد باهاش برخورد کردید. برای ایجاد یا استفاده از کیف پول HD wallet، میتونید به پکیج Go زیر مراجعه کنید:https://github.com/miguelmota/go-ethereum-hdwalletتوی بخش‌ بعدی درباره این صحبت می‌کنیم که چطور تراکنش های اتریوم رو کوئری بزنیم و تراکنش جدید ایجاد کنیم. لینکدین من</description><category>Ali Naghiee</category><author>Ali Naghiee</author><pubDate>Fri, 22 Sep 2023 12:53:37 +0330</pubDate></item><item><title>توسعه اپلیکیشن اتریوم با استفاده از Go - اکانت</title><link>https://virgool.ir/@ali-naghiee/توسعه-اپلیکیشن-اتریوم-با-استفاده-از-go-اکانت-qspjfbjcyssq</link><description>فهرستمقدمه و کلاینتاکانت &lt;-کیف پولاکانت ها در اتریوم یا آدرس‌ کیف پول هستن یا آدرس قراردادهای هوشمند.آدرس‌ها شکلی شبیه به این دارن: 0x71c7656ec7ab88b098defb751b7401b5f6d8976fو برای ارسال اتریوم به بقیه کاربران و همینطور ارجاع به یک قرارداد هوشمند روی بلاک‌چین در زمانی که نیاز به تعامل با باهاش داشته باشیم، مورد استفاده قرار می‌گیرن. آدرس‌ها منحصر به فرد هستن و از یک کلید خصوصی ایجاد می‌شن. در بخش‌های بعدی بیشتر در مورد جفت کلیدهای عمومی/خصوصی صحبت میکنیم.برای استفاده از آدرس‌های حساب با go-ethereum، اول باید به نوع common.Address توی go-ethereum تبدیلشون کرد.address := common.HexToAddress(&#34;0x71c7656ec7ab88b098defb751b7401b5f6d8976f&#34;)&#xA;fmt.Println(address.Hex()) // 0x71C7656EC7ab88b098defB751B7401B5f6d8976Fاین نوع common.Address رو هر جایی که نیاز به پاس دادن آدرس اتریوم به متد های go-ethereum هست میبینیم.کد کاملpackage main&#xA;&#xA;import (&#xA;    &#34;fmt&#34;&#xA;&#xA;    &#34;github.com/ethereum/go-ethereum/common&#34;&#xA;)&#xA;&#xA;func main() {&#xA;    address := common.HexToAddress(&#34;0x71c7656ec7ab88b098defb751b7401b5f6d8976f&#34;)&#xA;&#xA;&#x9;fmt.Println(address.Hex())        // 0x71C7656EC7ab88b098defB751B7401B5f6d8976F&#xA;&#x9;fmt.Println(address.Hash().Hex()) // 0x00000000000000000000000071c7656ec7ab88b098defb751b7401b5f6d8976f&#xA;&#x9;fmt.Println(address.Bytes())      // [113 199 101 110 199 171 136 176 152 222 251 117 27 116 1 181 246 216 151 111]&#xA;}بالانس اکانتحالا که مبانی پایه ای اکانت و آدرس‌ها رو دیدیم، توی این بخش بالانس اکانت ها رو میگیریم.خوندن بالانس اکانت سادست و فقط لازمه متد BalanceAt کلاینتمون رو صدا بزنیم و آدرس اکانت مورد نظرمونو بهش بدیم، به صورت انتخابی هم شماره بلاک میگیره که اگه nill قرار بدیم آخرین بالانس اکانت رو برمیگردونه.account := common.HexToAddress(&#34;0x71c7656ec7ab88b098defb751b7401b5f6d8976f&#34;)&#xA;balance, err := client.BalanceAt(context.Background(), account, nil)&#xA;if err != nil {&#xA;  log.Fatal(err)&#xA;}&#xA;fmt.Println(balance) // 25893180161173005034ولی اگه شماره بلاک رو مشخص کنیم بهمون گرفتن بالانس اکانت توی زمان اون بلاک رو میده. شماره بلاک هم باید از جنس big.Int باشه.blockNumber := big.NewInt(5532993)&#xA;balance, err := client.BalanceAt(context.Background(), account, blockNumber)&#xA;if err != nil {&#xA;  log.Fatal(err)&#xA;}&#xA;fmt.Println(balance) // 25729324269165216042اعداد توی اتریوم با کوچکترین واحد ممکن محاسبه میشن و اون واحد wei هست، برای تبدیل مقداری که اینجا گرفتیم به ETH باید محاسبه wei / 10^18 رو انجام بدیم. از اونجایی که با اعداد Big سروکار داریم باید از پکیج های math و math/big استفاده کنیم. روش انجام این محاسبه به شکل زیره.fbalance := new(big.Float)&#xA;fbalance.SetString(balance.String())&#xA;ethValue := new(big.Float).Quo(fbalance, big.NewFloat(math.Pow10(18)))&#xA;fmt.Println(ethValue) // 25.729324269165216041بالانس در انتظاربعضی اوقات میخوایم بدونیم موجودی pending اکانت چقدره، مثلا زمانی که تازه یه تراکنش ثبت کردیم یا منتظر تایید یه تراکنش به اکانتیم. برای همچین مواقعی کلاینت یه متد مشابه BalanceAt به نام PendingBalanceAt داره که آدرس اکانت رو توی ورودیش میگیره.pendingBalance, err := client.PendingBalanceAt(context.Background(), account)&#xA;fmt.Println(pendingBalance) // 25729324269165216042کد کاملpackage main&#xA;&#xA;import (&#xA;    &#34;context&#34;&#xA;    &#34;fmt&#34;&#xA;    &#34;log&#34;&#xA;    &#34;math&#34;&#xA;    &#34;math/big&#34;&#xA;&#xA;    &#34;github.com/ethereum/go-ethereum/common&#34;&#xA;    &#34;github.com/ethereum/go-ethereum/ethclient&#34;&#xA;)&#xA;&#xA;func main() {&#xA;    client, err := ethclient.Dial(&#34;https://cloudflare-eth.com&#34;)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    account := common.HexToAddress(&#34;0x71c7656ec7ab88b098defb751b7401b5f6d8976f&#34;)&#xA;    balance, err := client.BalanceAt(context.Background(), account, nil)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;    fmt.Println(balance) // 25893180161173005034&#xA;&#xA;    blockNumber := big.NewInt(5532993)&#xA;    balanceAt, err := client.BalanceAt(context.Background(), account, blockNumber)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;    fmt.Println(balanceAt) // 25729324269165216042&#xA;&#xA;    fbalance := new(big.Float)&#xA;    fbalance.SetString(balanceAt.String())&#xA;    ethValue := new(big.Float).Quo(fbalance, big.NewFloat(math.Pow10(18)))&#xA;    fmt.Println(ethValue) // 25.729324269165216041&#xA;&#xA;    pendingBalance, err := client.PendingBalanceAt(context.Background(), account)&#xA;    fmt.Println(pendingBalance) // 25729324269165216042&#xA;}چک کردن آدرستوی این قسمت اعتبارسنجی یک آدرس رو توضیح میدیم و اینکه چطور میشه تشخیص داد آدرس متعلق به یک قرارداد هوشمند هست یا نه.اعتبارسنجی آدرسمیتونیم از یه Regex ساده برای اعتبارسنجی آدرس‌های اتریوم استفاده کنیم.re := regexp.MustCompile(&#34;^0x[0-9a-fA-F]{40}$&#34;)&#xA;&#xA;fmt.Printf(&#34;is valid: %v\n&#34;), re.MatchString(&#34;0x323b5d4c32345ced77393b3530b1eed0f346429d&#34;)) // is valid: true&#xA;fmt.Printf(&#34;is valid: %v\n&#34;, re.MatchString(&#34;0xZYXb5d4c32345ced77393b3530b1eed0f346429d&#34;)) // is valid: falseآدرس کیف پول یا قرارداد هوشمنداگه بایت‌کدی برای آدرس ذخیره شده باشه میتونیم تشخیص بدیم که آدرس متعلق به قرارداد هوشمنده.  توی قطعه کد زیر بایت‌کد قرارداد هوشمند یک توکن رو بازیابی میکنیم و طولش رو برای تایید اینکه قرارداد هوشمنده بررسی میکنیم.// 0x Protocol Token (ZRX) smart contract address&#xA;address := common.HexToAddress(&#34;0xe41d2489571d322189246dafa5ebde1f4699f498&#34;)&#xA;bytecode, err := client.CodeAt(context.Background(), address, nil) // nil is latest block&#xA;if err != nil {&#xA;  log.Fatal(err)&#xA;}&#xA;isContract := len(bytecode) &gt; 0&#xA;fmt.Printf(&#34;is contract: %v\n&#34;, isContract) // is contract: trueزمانی که بایت‌کدی وجود نداره میدونیم که آدرس متعلق به قرارداد هوشمندی نیست و برای یه اکانت استاندارد اتریومه.// a random user account address&#xA;address := common.HexToAddress(&#34;0x8e215d06ea7ec1fdb4fc5fd21768f4b34ee92ef4&#34;)&#xA;bytecode, err := client.CodeAt(context.Background(), address, nil) // nil is latest block&#xA;if err != nil {&#xA;  log.Fatal(err)&#xA;}&#xA;isContract = len(bytecode) &gt; 0&#xA;fmt.Printf(&#34;is contract: %v\n&#34;, isContract) // is contract: falseکد کاملpackage main&#xA;&#xA;import (&#xA;    &#34;context&#34;&#xA;    &#34;fmt&#34;&#xA;    &#34;log&#34;&#xA;    &#34;regexp&#34;&#xA;&#xA;    &#34;github.com/ethereum/go-ethereum/common&#34;&#xA;    &#34;github.com/ethereum/go-ethereum/ethclient&#34;&#xA;)&#xA;&#xA;func main() {&#xA;    re := regexp.MustCompile(&#34;^0x[0-9a-fA-F]{40}$&#34;)&#xA;&#xA;    fmt.Printf(&#34;is valid: %v\n&#34;,&#xA;re.MatchString(&#34;0x323b5d4c32345ced77393b3530b1eed0f346429d&#34;)) // is valid: true&#xA;    fmt.Printf(&#34;is valid: %v\n&#34;,&#xA;re.MatchString(&#34;0xZYXb5d4c32345ced77393b3530b1eed0f346429d&#34;)) // is valid: false&#xA;&#xA;    client, err := ethclient.Dial(&#34;https://cloudflare-eth.com&#34;)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    // 0x Protocol Token (ZRX) smart contract address&#xA;    address := common.HexToAddress(&#34;0xe41d2489571d322189246dafa5ebde1f4699f498&#34;)&#xA;    bytecode, err := client.CodeAt(context.Background(), address, nil) // nil is latest block&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    isContract := len(bytecode) &gt; 0&#xA;&#xA;    fmt.Printf(&#34;is contract: %v\n&#34;, isContract) // is contract: true&#xA;&#xA;    // a random user account address&#xA;    address = common.HexToAddress(&#34;0x8e215d06ea7ec1fdb4fc5fd21768f4b34ee92ef4&#34;)&#xA;    bytecode, err = client.CodeAt(context.Background(), address, nil) // nil is latest block&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    isContract = len(bytecode) &gt; 0&#xA;&#xA;    fmt.Printf(&#34;is contract: %v\n&#34;, isContract) // is contract: false&#xA;}توی پست بعدی روش ساخت کیف پول جدید و ذخیره سازی امن کلید خصوصی رو بررسی میکنیم.لینکدین من</description><category>Ali Naghiee</category><author>Ali Naghiee</author><pubDate>Mon, 18 Sep 2023 15:11:07 +0330</pubDate></item><item><title>توسعه اپلیکیشن اتریوم با استفاده از Go - کلاینت</title><link>https://virgool.ir/@ali-naghiee/توسعه-اپلیکیشن-اتریوم-با-استفاده-از-go-کلاینت-n4oyiyisiprr</link><description>این سری پست ها یه راهنمای کلی برای توسعه اپلیکیشن های اتریوم با استفاده از Go هستن، و اگه آشنایی خوبی با اتریوم و Go دارید میتونن نقطه شروع خوبی برای به کارگیریشون با هم باشن. توی این سری آموزش نحوه برقراری ارتباط با بلاکچین و تعامل با قرارداد های هوشمند رو با استفاده از GoLang مورد بررسی قرار میدیم.منبع اصلی مورد استفاده من کتاب goethereumbook  نوشته شده توسط Miguel Mota هست که به صورت آزاد، رایگان و با فرمت های مختلف در دسترسه و خوندنش رو شدیدا توصیه میکنم.هرجا هم که بتونم مطلبی اضافه میکنم :)کلاینت نقطه ورود ما به شبکه اتریومه.کلاینت برای انتشار تراکنش‌ها و خواندن داده‌های بلاکچین مورد نیازه. توی این بخش نحوه راه اندازی این کلاینت رو بررسی میکنیم. برای این کار اول از همه پکیج ethclient از go-ethereum رو وارد میکنیم و با اجرای Dial راه‌اندازی اولیش رو انجام میدیم که یه آدرس ارائه‌دهنده هم میگیره.برای آدرس ارایه دهنده انتخاب های زیادی هست. یکی از اونها استفاده از infura هست که درگاهی امن، قابل اعتماد و مقیاس پذیر برای تعامل با شبکه اتریوم به ما میده. همینطور یه انتخاب خیلی خوب دیگمون alchemy هست. اینجا برای نمونه از درگاه اتریوم cloudflare استفاده کردیم.client, err := ethclient.Dial(&#34;https://cloudflare-eth.com&#34;)همینطور اگه یه نسخه geth درحال اجرای لوکال داشته باشیم میتونیم مسیر فایل اندپوینت IPC رو بهش بدیم.client, err := ethclient.Dial(&#34;/home/user/.ethereum/geth.ipc&#34;)شبکه های تست لوکالبرای تست و توسعه صرفا نیاز نیست از این درگاه های مختلف استفاده کنیم، مخصوصا با در نظر گرفتن سرعت و کیفیت ارتباط، خیلی به صرفه تره که از شبکه های تست لوکال استفاده کنیم. استفاده از Ganacheیکی از این شبکه ها Ganache هست که به عنوان پیاده سازی ای از اتریوم با node.js برای تست و توسعه لوکال مورد استفاده قرار میگیره. اینجا ما مراحل نصب و اتصال بهش رو میبینیم.اول با استفاده از NPM نصبش میکنیم.npm install -g ganache-cliو بعد کلاینت CLI اون رو اجرا میکنیم.ganache-cliحالا میتونیم به شکل قبل از آدرس RPC اون توی کدمون برای اتصال بهش استفاده کنیم.client, err := ethclient.Dial(&#34;http://localhost:8545&#34;)همینطور میتونیم توی زمان اجرای Ganache از mnemonic های قبلی استفاده کنیم که دوباره آدرس های قبلی رو برامون ایجاد کنه.ganache-cli -m &#34;much repair shock carbon improve miss forget sock include bullet interest solution&#34;همینطور توصیه میشه که با خوندن داکیومنتیشن Ganache بیشتر باهاش آشنا بشید، اگه نمیخواید از کلاینت CLI استفاده کنید هم نسخه GUI اش موجوده.استفاده از Hardhatانتخاب دیگه ای که داریم استفاده از Hardhat هست که بیشتر توصیه میکنم، Hardhat یک فریمورک برای تست و توسعه قرارداد های هوشمند اتریومه که به همراهش یک پیاده سازی شبکه اتریوم برای تست لوکال داره. برای استفاده از Hardhat به دایرکتوری مورد نظر میریم.mkdir hardhat-tutorial&#xA;cd hardhat-tutorialو پروژه NPM جدیدی رو راه‌اندازی اولیه میکنیم.npm initحالا میتونیم Hardhat رو نصب کنیم.npm install --save-dev hardhatبعد از نصب توی همون دایرکتوری دستور زیر رو اجرا میکنیم.npx hardhatو از گزینه های موجود Create an empty hardhat.config.js رو انتخاب میکنیم تا یه پروژه خالی بهمون تحویل  بده. این فایل تنظیمات Hardhat رو شامل میشه.حالا میتونیم شبکه تستی لوکال خودمون رو اجرا کنیم.npx hardhat nodeو مثل قبل بهش متصل بشیم.client, err := ethclient.Dial(&#34;http://localhost:8545&#34;)کد کاملpackage main&#xA;&#xA;import (&#xA;    &#34;fmt&#34;&#xA;    &#34;log&#34;&#xA;&#xA;    &#34;github.com/ethereum/go-ethereum/ethclient&#34;&#xA;)&#xA;&#xA;func main() {&#xA;    client, err := ethclient.Dial(&#34;https://cloudflare-eth.com&#34;)&#xA;    if err != nil {&#xA;        log.Fatal(err)&#xA;    }&#xA;&#xA;    fmt.Println(&#34;we have a connection&#34;)&#xA;    _ = client // we&#39;ll use this in the upcoming sections&#xA;}بخش بعدی در مورد اکانت های اتریوم و والت ها، ایجاد، استفاده، ذخیره سازیشون و تعامل باهاشونه.</description><category>Ali Naghiee</category><author>Ali Naghiee</author><pubDate>Fri, 15 Sep 2023 16:17:32 +0330</pubDate></item></channel></rss>