ברוב הפעמים, כשאנשים מתחילים ללמוד איך לכתוב חוזים חכמים, הדבר הראשון שהם שומעים עליו הוא Solidity ו-Ethereum. גם זה היה הדבר הראשון ששמעתי עליו. זה מה שרוב ההדרכות מתמקדות בו, ומסיבה טובה. סולידיות אפשרה לכתוב תוכניות שחיות על בלוקצ'יין, וה-Ethereum הפך למקום שבו אנשים רבים התחילו.
אבל Solidity היא לא שפת החוזים החכמה היחידה בחוץ. ו-Ethereum הוא לא הבלוקצ'יין היחיד שתומך ביישומים מבוזרים.
יש גם TON , קיצור של The Open Network . היא נוצרה על ידי טלגרם, אך כעת היא רשת ציבורית מונעת על ידי קהילה. זה מהיר, קל משקל ומטפל בדברים קצת אחרת ממה שהיית רגיל אליו ב-Ethereum. זה כולל איך נכתבים חוזים חכמים. כשהתחלתי לחקור את התיעוד של TON, נתקלתי בארבע שפות שונות לכתיבת חוזים חכמים: Tact, Tolk, FunC ו-Fift . אני לא אכנס כאן לארבעה.
מדריך זה מתמקד בשפת טקט, ונראה כיצד להשתמש בה כדי לבנות חוזה הצבעה בסיסי המאפשר למשתמשים להצביע ולבדוק תוצאות על השרשרת.
למה החלטתי ללמוד טקט קודם
המערכת האקולוגית של TON תומכת למעשה במספר שפות, שכל אחת מהן משרתת מקרי שימוש שונים, רמות הפשטה וחוויית מפתח שונים. להלן סקירה מהירה של כל אחד מהם:
- FunC היא השפה המסורתית לכתיבת חוזים חכמים של TON. זה ברמה נמוכה ונותן לך שליטה מדויקת על איך החוזה שלך עובד מתחת למכסה המנוע. זה רב עוצמה, אבל זה גם אומר שתצטרך להבין כיצד פועלת ה-TON Virtual Machine (TVM), כולל מושגים כמו מניפולציה של מחסנית, פריסת זיכרון וביצוע דטרמיניסטי. התחביר דומה במקצת ל-C, שיכול להרגיש לא מוכר אם לא עבדת עם סגנון השפה הזה בעבר.
- Fift משמש בדרך כלל לצד FunC. זוהי שפה מבוססת מחסנית המשמשת בעיקר לאינטראקציה ישירה עם ה-TVM ומשמשת לפריסה, ניפוי באגים וביצוע חישובים על השרשרת. בדרך כלל זו לא השפה שאתה מתחיל איתה לכתיבת חוזים חכמים מלאים, אבל היא חשובה בתהליך העבודה הכולל של הפיתוח ב-TON.
- Tolk הוא תוספת חדשה יותר שעדיין מתפתחת. ממה שאספתי, מטרתו היא לשפר כלי עבודה ותאימות עם שפות ברמה גבוהה יותר. זה מבטיח, אבל עדיין לא מאומץ או מתועד באופן נרחב.
- Tact היא שפה ברמה גבוהה שתוכננה במיוחד כדי להפוך את פיתוח חוזים חכמים של TON לנגיש וידידותי יותר למפתחים. Tact מפשט הרבה מהמורכבות ברמה נמוכה יותר ומאפשר לך להתמקד בכתיבת ההיגיון שלך בצורה נקייה וקריאה. התחביר קרוב יותר למה שהיית רואה ב-TypeScript או ב-Solidity, מה שמקל הרבה יותר להתחיל בלי צורך לצלול עמוק לתוך החלקים הפנימיים של TVM.
טקט מספקת נתיב מהיר יותר לבנייה ופריסה של חוזים בבלוקצ'יין TON.
הבנת איך עובד טקט
לפני שנתחיל לכתוב קוד, חשוב להבין כיצד בנויים חוזים חכמים של טאקט. חוזה טקט טיפוסי כולל כמה מרכיבי ליבה:
חסימת
contract
- זה המקום שבו אתה מגדיר את שם החוזה שלך ומצהיר על כל משתני מצב.init
block - הוא מאתחל את משתני המצב של החוזה שלך וקובע את תנאי ההתחלה של החוזה. בלוק זה פועל פעם אחת בזמן הפריסה.receive
בלוקים - אלה הם כמו מאזינים לאירועים. הם מטפלים בהודעות נכנסות ומגדירים כיצד החוזה שלך מגיב אליהם.פונקציות של Getter (
get fun
) – אלו הן פונקציות אופציונליות לקריאה בלבד המאפשרות למשתמשים או חוזים אחרים לבצע שאילתות על מצב החוזה מבלי לשנות אותו.
טאקט משתמשת בתקשורת מבוססת הודעות, וכך עובדות כל האינטראקציות ב-TON. כל חוזה מקבל הודעה ומעבד אותה בבלוק receive
משלו. מבנה מבוסס הודעות זה עוזר לארגן את היגיון החוזה שלך בצורה מודולרית וניתנת לתחזוקה.
בואו ליישם זאת כעת בדוגמה אמיתית על ידי בניית חוזה הצבעה פשוט.
בניית חוזה ההצבעה הראשון שלך בטקט (באמצעות ה-IDE האינטרנטי של TON)
בסעיף זה, נסקור כיצד ליישם מערכת הצבעה בסיסית באמצעות טאקט. חוזה הצבעה זה יאפשר למשתמשים להצביע עבור מועמדים מוגדרים מראש ועוקב אחר המספר הכולל של הקולות שכל מועמד מקבל.
אנחנו נעשה הכל בתוך TON Web IDE, שהוא כלי בדפדפן שבו אתה יכול לכתוב, לבנות ולבדוק את החוזים שלך מבלי להתקין שום דבר באופן מקומי.
שלב 1 - פתח את TON Web IDE
- עבור אל https://ide.ton.org .
- לחץ על צור פרויקט חדש . בחלון הקופץ:
- ודא שהשפה נמצאת ב- Tact .
- בחר חוזה ריק כתבנית שלך.
- תן שם לפרויקט שלך כמו
VotingContract
. - לחץ על + צור .
שלב 2 – כתיבת קוד חוזה ההצבעה
לאחר יצירת הפרויקט, פתח את קובץ main.tact
. תראה הגדרת לוחית:
// Import the Deployable trait so the contract can be deployed easily import "@stdlib/deploy"; contract BlankContract with Deployable { init() { } }
-
import "@stdlib/deploy";
נדרש כדי שהפריסה תעבוד ואין להסיר אותו מהקוד. -
BlankContract
הוא שם מציין המיקום. - בלוק
init()
פועל רק פעם אחת כאשר החוזה נפרס ומשמש לאתחול משתני מצב.
עכשיו, בואו נמפה את הקוד שלנו.
ראשית, נגדיר את מבנה ההודעה להצבעה:
// Import the Deployable trait so the contract can be deployed easily import "@stdlib/deploy"; // Define a message structure for voting message Vote { candidate: Int as uint32; // 1 = Alice, 2 = Bob }
זו הודעת ההצבעה. כאשר מישהו רוצה להצביע, הוא ישלח הודעה לחוזה הכוללת מספר:
- 1 עבור אליס
- 2 לבוב
טאקט משתמש במבנה זה כדי לעבד את ההצבעה הנכנסת ולהחליט מי המועמד מקבל את הנקודה.
לאחר מכן, נגדיר את החוזה שלנו ונוסיף שני משתני מדינה כדי לעקוב אחר ההצבעות של כל מועמד:
... contract VotingContract with Deployable { // State variables to track votes votesAlice: Int as uint32; votesBob: Int as uint32;
בתוך החוזה, הגדרנו שני משתנים:
-
votesAlice
: מאחסן את מספר הקולות שאליס מקבלת. -
votesBob
: מאחסן את מספר ההצבעות שבוב מקבל.
כעת נאתחל את ספירת ההצבעות הללו לאפס בתוך בלוק init
כדי להגדיר את מצב ההתחלה של החוזה כאשר הוא ייפרס לראשונה.
init() { self.votesAlice = 0; self.votesBob = 0; }
בלוק init
פועל פעם אחת בלבד , ממש כאשר החוזה נפרס והוא מגדיר את שתי ספירת ההצבעות לאפס.
עכשיו מגיע ההיגיון. כאשר נשלחת הצבעה, אנו רוצים שהחוזה יבדוק למי מיועדת ההצבעה ויגדיל את ספירת הקולות הנכונה.
// Handle vote messages receive(msg: Vote) { if (msg.candidate == 1) { self.votesAlice += 1; } else if (msg.candidate == 2) { self.votesBob += 1; } }
אז כשמתקבלת הצבעה:
- אם
msg.candidate
הוא 1, אנו מוסיפים 1+ ל-votesAlice
- אם
msg.candidate
הוא 2, אנו מוסיפים 1+ ל-votesBob
לבסוף, ניצור פונקציות משבר כדי לאפשר לכל אחד לשאול את ספירת הקולות עבור כל מועמד מבלי לשנות את מצב החוזה.
// Getter for Alice's votes get fun getVotesForAlice(): Int { return self.votesAlice; } // Getter for Bob's votes get fun getVotesForBob(): Int { return self.votesBob; } }
שתי פונקציות המשבר הללו מאפשרות לנו לבדוק את מספר הקולות שכל מועמד קיבל מבלי לשנות שום דבר בחוזה. זו פעולה לקריאה בלבד.
להלן קוד חוזה ההצבעה המלא:
import "@stdlib/deploy"; // Define a message structure for voting message Vote { candidate: Int as uint32; // 1 = Alice, 2 = Bob } contract VotingContract with Deployable { // State variables to track votes votesAlice: Int as uint32; votesBob: Int as uint32; init() { self.votesAlice = 0; self.votesBob = 0; } // Handle vote messages receive(msg: Vote) { if (msg.candidate == 1) { self.votesAlice += 1; } else if (msg.candidate == 2) { self.votesBob += 1; } } // Getter for Alice's votes get fun getVotesForAlice(): Int { return self.votesAlice; } // Getter for Bob's votes get fun getVotesForBob(): Int { return self.votesBob; } }
שלב 4 - בנה ופריסה של החוזה
- בסרגל הצד השמאלי, לחץ על Build & Deploy
- תחת סביבה , ודא ש- Sandbox נבחרה.
- ודא ש- main.tact נבחר ולחץ על Build . זה ירכיב את החוזה שלך ויבדוק אם יש שגיאות תחביר או בעיות בקוד שלך.
- לאחר מכן, ודא שחוזה הצבעה נבחר בתפריט הנפתח מכיוון שזהו החוזה האמיתי שלך, לא מציין המיקום המוגדר כברירת מחדל. אם אינך רואה אותו, הקש Ctrl + S כדי לשמור את הקובץ שלך כך שה-IDE יוכל לזהות את החוזה המעודכן.
- לאחר מכן לחץ על ReDeploy . אם הכל עובד כשורה, תראה הודעת אישור ביומנים המראה שהחוזה שלך נפרס בהצלחה ב-Sandbox.
שלב 5 - אינטראקציה עם החוזה
לאחר הפריסה, גלול מטה ותראה שני חלקים:
- Getters:
getVotesForAlice
,getVotesForBob
- כונסים:
Vote
להצבעה: בקטע הצבעה , הזן 1
בשדה הקלט candidate
ולחץ על שלח. זה עתה הצבעת לאליס! אתה יכול לחזור על זה כדי להצביע יותר.
כדי לבדוק את ספירת הקולות : לחץ על התקשר תחת getVotesForAlice
ובדוק את לוח היומנים כדי לראות את ספירת הקולות
- עשה את אותו הדבר עבור בוב על ידי שליחת
2
בשדהcandidate
, ולאחר מכן סמןgetVotesForBob
בהרצת המבחן שלי, הצבעתי לאליס 9 פעמים ולבוב 6 פעמים , ופונקציות ה-Gutter הראו בדיוק את זה.
💭 מחשבות אחרונות: המשיכו לבנות, המשיכו לחקור
🙌 מזל טוב אם קראתם עד הסוף!
כעת, לאחר שראית כיצד עובד חוזה הצבעה פשוט ב-Tact, עשית את הצעד הראשון שלך לפיתוח חוזים חכמים ב-TON. חוזה זה עשוי להיות בסיסי, אך המבנה והמושגים חלים גם על לוגיקה מורכבת יותר.
אם אתה רוצה להמשיך להתנסות, נסה להאריך את החוזה הזה או לחקור תבניות אחרות שנבנו מראש מ- https://tact-by-example.org/all . ה-TON Web IDE גם מקל על ניסוי מקרי שימוש שונים והוא מגיע גם עם תבניות כדי לעזור לך לבנות וללמוד מהר יותר.
אז קדימה, לשנות, לבדוק, לבנות משהו טוב יותר.