למה פיתוח dApp ב-React נשבר בעסקאות
כשל קלאסי בפיתוח dApp ב-React — הממשק והארנק מציגים מצב שונה. המשתמש חתם על עסקה, המסך עבר ל"הצלחה", אבל ברשת היא נדחתה בגלל nonce או נדחקה על ידי שליחה מתחרה.
האפליקציה סומכת על תגובת הצומת שלה ולא משווה לסטטוס בפועל, לכן חוסר הסנכרון במצב הממשק לא מתגלה מיד — בדרך כלל רק דרך פנייה לתמיכה.
הקבוצה השנייה — שגיאות עסקאות ב-dApp שמשחזרות באופן לא עקבי. חתימה חוזרת של הארנק בלחיצה כפולה יוצרת פעולה שנייה עם אותה משמעות אבל האש שונה: בדיקת כפילות לפי האש לא עובדת, כי ברגע השליחה ההאש עדיין לא קיים.
עסקאות תקועות ומסכי המתנה נשארים במקום שבו ממתינים לאישור לפי אירוע מנוי, והוא הולך לאיבוד בעת החלפת רשת או רענון עמוד.
מקום הכשל השלישי — מטמון בקשות. לאחר אישור הנתונים לא מתבטלים, הממשק מציג יתרה ישנה והרשאה ישנה לחיוב, המשתמש שולח פעולה חוזרת. החלפת עסקה עם אותו nonce וחזרת רשת בכמה בלוקים לא מטופלות כלל.
סטאק כמו wagmi ו-viem מסיר חלק מהשגרה, אבל לא מבטל את לוגיקת הסנכרון — כותבים אותה מעל ומאמתים בנפרד.
ההשלכה של טעות כזו — עלייה בבדיקות ידניות ואובדן אמון במוצר בלי סיבה, למרות שהלוגיקה העסקית עובדת. נפרט איך זה נסגר.
מה נותן פרונטאנד צפוי: מצבים, רשת, אישור
כל עוד הפעולה חיה במצב של קומפוננטה אחת, כל הרכבה מחדש של רשימה, החלפת חשבון או רשת בארנק הופכת את הממשק לאוסף של ניחושים. המשתמש רואה "נשלח", למרות שהחתימה לא יצאה, או להפך — הפעולה כבר קיימת ברשת, והמסך מציע ללחוץ על הכפתור שוב. כל מקרה כזה — פנייה לתמיכה ובדיקה ידנית של לוגים.
אנחנו מוציאים את סטטוס הפעולה למקור אחיד: מכונת מצבים עם מצבים מטיוטה וחתימה ועד אישור במספר בלוקים מוגדר ופיינליזציה. קומפוננטות נרשמות אליו, במקום לשאול את הצומת כל אחת בעצמה — מספר בקשות הרשת יורד, וחלקי הממשק מפסיקים להציג נתונים סותרים.
החלפת רשת מטופלת ללא רענון: בקשת ההחלפה נשלחת לארנק, ואם היא נדחית הממשק נשאר במצב הקודם ומסביר מה חסר. הסשן משוחזר מעל WalletConnect — טיוטה והיסטוריית פעולות נשמרות מקומית, לאחר התחברות מחדש הסטטוס מושווה ליומן אירועי הרשת, לכן שום חתימה לא אובדת.
האפקט מדיד: שיעור הפעולות שדורשות התערבות ידנית יורד למקרים בודדים, ופניות לתמיכה בנוסח "העסקה נתקעה" נעלמות יחד עם מחלקת השגיאות שיצרה אותן. חקירת תקלה אורכת דקות — מהיומן רואים את המצב שבו הפעולה הופסקה.
דרכים לחיבור ארנק: מה לבחור למשימה
בפרונטאנד של אפליקציית React חיבור ארנק הוא הפעולה הראשונה של המשתמש ונקודת הכשל הנפוצה ביותר: ספק לא נכון, החלפת רשת, ניתוק באמצע החתימה. אנחנו משווים אפשרויות עבודה לפי מתי כל אחת מתאימה ומה ההשלכות שלה.
הבחירה מצטמצמת לשלוש שאלות: כמה ארנקים צריך לתמוך, האם יש תרחיש מובייל, והיכן נבדקת החתימה — בדפדפן או בצד השירות.
אפשרויות והגבולות שלהן
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| קומפוננטות חיבור מוכנות | צריך כיסוי מהיר של ארנקי דסקטופ ומובייל | הספרייה מכתיבה את מבנה המצב; כניסה לא סטנדרטית צריך לעקוף |
| מימוש עצמי בקריאות ישירות לספק | ארנק אחד-שניים, זרימה לא סטנדרטית, דרישות קשיחות למשקל הממשק | החלפת רשת, ניתוק וקונפליקט בין כמה ספקים מטופלים אצלנו |
| חתימה בצד השירות | כניסה בלי עסקה, קישור ארנק לחשבון | צריך הודעות חד-פעמיות, בקרת תוקף החתימה והגנה מפני חזרה |
| ארנק מובנה באפליקציה | קהל בלי ארנקים, צריך כניסה חלקה | המפתחות נשארים אצלנו — דרישות גבוהות יותר לאבטחה ולשחזור גישה |
בפועל אנחנו לוקחים שילוב: קומפוננטות מוכנות מכסות את מגוון הארנקים, קריאות ישירות לספק — תרחישים לא סטנדרטיים, חתימה בשרת — זיהוי המשתמש. את הבחירה מתעדים במפרט, כדי שהיא לא תעלה שוב בעת הוספת ארנק חדש.
סדר העבודה: מביקורת הקוד הנוכחי ועד מסירה
ביקורת הפרונטאנד של dApp מתחילה לא בממשק, אלא בניתוח המצב הקיים: אילו רשתות מחוברות, איך נשמר מצב הארנק, היכן מטופלים כשלים בשליחה. אנחנו מתעדים נקודות תורפה ומעריכים את היקף העבודה. משם הכל מתקדם בשלבים, וכל שלב מסתיים בתוצאה ניתנת לבדיקה, לא בדוח התקדמות.
- ביקורת פרונטאנד dApp. מנתחים קומפוננטות, שכבת העבודה עם הרשת, טיפול בחתימה ובאישור, כיסוי בבדיקות. בפלט — מפת בעיות עם עדיפויות: מה שובר את מסלול המשתמש, מה מעכב פיתוח.
- תרשים זרימת העסקה. מתארים מחזור חיים של פעולה: אתחול, חתימה בארנק, שליחה, המתנה לאישור, ביטול או החלפה, ארגון מחדש של השרשרת. התרשים הופך לחוזה בין הממשק ללוגיקה.
- עיצוב מצבים. מפרידים בין "המתנה", "מאושר", "נדחה"; לכל אחד טקסט משלו והצעד הבא למשתמש. סירוב לחתימה וכשל רשת מטופלים באופן שונה.
- מימוש. עובדים בשינויים קטנים, כל אחד נבדק ברשת בדיקה בתרחישים אמיתיים: חוסר במשאבים, שליחה חוזרת, ניתוק חיבור.
- בדיקת תרחישים. מריצים מסלול מלא מחיבור הארנק ועד אישור, כולל החלפת רשת וכניסה מחדש.
- קבלת תרחישים. מתבצעת לפי רשימה שסוכמה מראש: אתם רואים כל שלב ומאשרים את ההתנהגות לפני שחרור.
- מסירה. מאגר קוד, תיאור זרימת העסקה, הוראות פריסה וסקירת קוד עם הצוות שלכם.
מה נשאר במאגר הקוד לאחר מסירה
מסירת פרויקט היא לא ארכיון קוד מקור, אלא סט פתרונות ניתן לשחזור, שלפיו צוות חדש מרים סביבה ומוציא תיקון בלי ארכאולוגיה בתכתובות. אנחנו מקבעים את הרכב הארטיפקטים כקריטריון מוכנות: עד שכל סעיף למטה לא נמצא במאגר ולא נבדק על ידי מהנדס שני, העבודה לא נחשבת למסורה.
- קונפיגורציית רשתות: מזהי שרשראות, כתובות חוזים, צמתי קריאה ראשי וגיבוי, מעבר בין רשת ייצור לרשת בדיקה דרך משתני סביבה בלי שינויים בקוד.
- תיאור מצבי האפליקציה: רשימת מצבי מסך — ארנק לא מחובר, מחובר לרשת לא נכונה, עסקה נשלחה וממתינה לאישור, אושרה, נדחתה על ידי המשתמש — ומה בדיוק האדם רואה בכל מקרה.
- טיפול בשגיאות עסקאות: כשלים מחולקים למחלקות (דחייה בארנק, חוסר במשאבים לעמלה, החזר משאבים על ידי החוזה, המתנה שפגה לקבלה), לכל מחלקה טקסט משלה בממשק וצעד הבא ברור.
- מדיניות רענון נתונים: מתי נקראים מחדש יתרות וסטטוסים לאחר אישור, כדי שהמספרים על המסך לא יסתרו ממצב השרשרת.
- תיעוד לצוות: הרצה מקומית, ייעוד משתני סביבה, היכן לשנות כתובות בעת חיבור מעגל חדש, בדיקות חובה לפני שחרור.
- נוהל שחרור וחזרה אחורה: סדר בנייה, הרצה ברשת בדיקה, תנאים לחזרה לגרסה קודמת.
- יומן החלטות: למה מבנה הפרויקט כזה ואילו אפשרויות נדחו — כדי שהצוות הבא לא יתכנן את זה מחדש.
מקרה בוחן: איך צמצמנו את שיעור הפעולות התקועות
לקוח הגיע עם אפליקציית React שבה חלק מהעסקאות אבדו בין החתימה בארנק לבין האישור ברשת. הסטטוס נבדק בסקר לפי טיימר: בעת ניתוק החיבור הבקשה просто לא חזרה על עצמה, והמשתמש ראה "נשלח", למרות שהפעולה לא יצאה.
צרה נפרדת — לחיצה כפולה על הכפתור: החתימה השנייה יצרה כפילות, והיה צריך לבדוק ידנית בלוגים של הצומת.
הרכבנו שכבת מצב אחידה לעסקה על wagmi: מנוי לאירועי אישור במקום סקר, מפתח אידמפוטנטי לכל פעולה ותור ניסיונות חוזרים עם הגבלה במספר הצעדים.
לאחר רענון העמוד האפליקציה משווה האשים שלא הושלמו עם הרשת ומשחזרת את הסטטוס העדכני — הפעולה ה"תקועה" או שמגיעה, או שמסומנת ביושר כשגיאה.
מדדים לפני ואחרי: שיעור הפעולות בלי אישור ירד מ-9% ל-0.4%. מספר החתימות החוזרות בלחיצה כפולה — מ-30 לאפס, הכפתור נחסם עד לסטטוס הסופי. זמן ההתאוששות לאחר כשל חיבור הצטמצם מבדיקה ידנית של 10–15 דקות לכמה שניות.
העיקר — נעלמה מחלקת כשלים שלמה של "המשתמש חתם, אבל הפעולה לא יצאה". האישור הפך לאידמפוטנטי, המצב משוחזר מהרשת ולא מהזיכרון של הלשונית, לכן כניסה חוזרת לאפליקציה כבר לא יוצרת כפילויות.
במה שונה שליחת עסקה מהאישור שלה ב-React?
החזרה מ-writeContract אומרת בדיוק דבר אחד: הארנק חתם על הקריאה ושלח אותה לרשת, והחזיר האש. הפעולה עוד לא בבלוק — היא בתור של אלה שלא אושרו, אפשר לזרוק אותה או להחליף בעסקה עם אותו nonce. ממשק שמסיר חסימה לפי האירוע הזה מציג "הצלחה" במקום שבו מצב החוזה לא השתנה.
אישור — מצב נפרד, אותו נותן useWaitForTransactionReceipt: ממתין לקבלה עם שדה status ורק אז מחשיב את הפעולה כמבוצעת. בין הנקודות האלה — כל מחזור החיים: סימולציית קריאה, חתימה, פרסום, הכללה בבלוק, צבירת אישורים. כל מעבר ראוי לסטטוס משלו, לא לדגל בוליאני אחד של טעינה.
סימולציית קריאה לפני חתימה חוסמת החזרות בגלל ארגומנטים שגויים או מצב חוזה שהשתנה: המשתמש לא חותם על פעולה שנכשלת מראש ולא רואה שגיאה רק אחרי אישור בארנק.
זמן ההמתנה להכללה בלתי צפוי — הוא תלוי בעומס הרשת ובעמלה המוצעת, לכן אין טעם לחכות לו בטיימר קבוע. את המצב מחזיקים על אירועים, את הכפתור משחררים לפי קבלה, לא לפי האש, ובנפרד עוקבים אחרי החלפה: לפעולה שנדחקה לא תופיע לעולם קבלה לפי האש הישן.
ענף נפרד — סירוב המשתמש בארנק: זה לא כשל רשת, ואסור לערבב אותו עם שגיאת שליחה, אחרת הממשק של אפליקציית React מפחיד בטקסט אדום במקום שבו האדם פשוט שינה את דעתו.
ספקות טכניים שכדאי להסיר לפני ההתחלה
ניתוח ההתנגדויות מתחיל במקרה נפוץ: פרונטאנד ב-React כבר קיים, נכתב על ידי צוות קודם או בכוחות עצמכם. לפני שמשנים משהו, אנחנו בודקים שלוש נקודות — איך נשמר המצב, היכן מבודדת שכבת חתימת העסקאות ואיך מטופלים כשלי רשת. לפיהן רואים מה לשפר ומה לבנות מחדש.
למטה — מה שבדרך כלל מפרטים לפני חתימה על התוכנית.
הקוד כבר קיים אצלנו — אתם מתכוונים לכתוב אותו מחדש?
לא כברירת מחדל. אם שכבת חתימת העסקאות מבודדת מהממשק, אנחנו משאירים אותה ומשנים רק את מה שמפריע. כותבים מחדש כשהלוגיקה של הארנק מפוזרת בין קומפוננטות: אז כל רשת חדשה שוברת את הפריסה, והתמיכה דורשת יותר מאשר בנייה מסודרת מחדש.
היכן נגמרת האחריות שלכם ומתחילה שלנו?
אנחנו אחראים לחלק הלקוח: חיבור ארנק, שליחה ואישור עסקאות, מצבי הממשק וניתוח שגיאות. חוזים, מפתחות והרשאות גישה נשארים בצד שלכם — אנחנו פונים אליהם כממשק חיצוני ולא שומרים סודות אצלנו.
איך תוסיפו ארנק או רשת חדשים?
שכבת החיבור נשמרת בנפרד מהמסכים, לכן ספק חדש הוא קונפיגורציה, לא כתיבה מחדש של הממשק. בודקים עליו חיבור, חתימה והחלפת רשת, ורק אחרי זה מציגים את הכפתור למשתמשים.
איך אתם בודקים כשלים?
בנפרד משחזרים סירוב משתמש וכשל רשת: חתימה שנדחתה, אובדן חיבור, תגובה ארוכה, שליחה חוזרת. לכל מקרה — מצב ברור בממשק; בלעדיו המשתמש לוחץ על הכפתור שוב ומקבל עסקה תלויה.
נדון במשימה ונחזור עם הערכה ותוכנית
כדי שההערכה תהיה הנדסית ולא "לפי תחושות", צריך נתוני פתיחה על הפרויקט — ככל שהנתונים קונקרטיים יותר, כך יש פחות הנחות בתוכנית העבודה והלוחות זמנים מדויקים יותר. מספיק מה שכבר קיים בעבודה: מאגר קוד, תיעוד, גישה לסביבת בדיקה.
- כתובות ורשתות של חוזים שהממשק יעבוד איתם, ותיאורים של המתודות הציבוריות שלהם;
- רשימת תרחישי משתמש: חיבור ארנק, חתימה, שליחת עסקה, המתנה לאישור, סירוב;
- אילו ארנקים ודרכי חיבור צריך לתמוך — תוסף, מובייל, חומרה;
- עיצובי מסכים או קישור לממשק הנוכחי, אפילו טיוטות;
- גישות לסביבות: רשת בדיקה, צומת או ספק, מפתח לקריאה בלבד;
- דרישות לטיפול בכשלים: מה מציגים כשחתימה נדחית, כשהחוזה דוחה וכשמחליפים עסקה;
- סטאק הממשק הנוכחי — גרסת React, ספריות לעבודה עם חוזים, מגבלות בנייה.
הלאה הצעד שלנו. בתוך שני ימי עבודה מנתחים את נתוני הפתיחה, משווים את התרחישים לחוזים וחוזרים עם תוכנית עבודה: שלבים, היקף, תלויות, נקודות שבהן נדרשות ההחלטות שלכם, וקריטריוני קבלה לכל תרחיש.
תארו את המשימה בצורה נוחה — נחזור עם הערכה ותוכנית.







