Як нетехнічному фаундеру не з’їхати з глузду: Сповідь про HROSHI, баги Monobank та React-амнезію
Привіт, DOU!
Одразу дисклеймер: так, я розумію, що для більшості з вас, шановні сіньори та архітектори, цей текст може здатися описом «дитячих» проблем. Для когось ці шматки коду — це банальність, яку ви пишете лівою рукою під час матча-брейку. Але для мене, як для нетехнічного фаундера, кожне таке рішення — це невеликий політ у космос.
HROSHI — це мій «велосипед». І ось як ми його збирали останні 10 днів, борючись із лімітами Mono, власною пам’яттю React та «багами мільйонера».
Проблема № 1: Ліміти API або «Чому Monobank мене ігнорує?»
Коли ми підключили Monobank API, я думав: «Круто, зараз все полетить!». Але реальність вдарила
У першій версії ми просто запустили оновлення всіх карток одночасно. Користувач відкриває застосунок, ми робимо Promise.all (щоб це не значило) для всіх карток... і миттєво відлітаємо в бан.
Як ми це «перемогли»: Ми впровадили розумну чергу з глобальним таймером. Апка оновлює баланси, а потім чемно чекає хвилину перед кожним наступним запитом історії тразакцій.
Для вас це простий рекурсивний запуск(так сказав мені dev), а для мене — архітектурний прорив
const processQueue = async (queue) => {
if (queue.length === 0) return setSyncStatus('success');
const lastReqTime = parseInt(localStorage.getItem('last_api_req') || '0');const timeDiff = Date.now() - lastReqTime;
</code></div>
<div><code>
if (timeDiff < 60000) {
const wait = Math.ceil((60000 - timeDiff) / 1000);setSyncStatus('limit');
setSyncMessage(`Ліміт банку: чекаємо ${wait}с...`);setTimeout(() => processQueue(queue), 1000); return;
}
</code></div>
<div><code> // ... логіка запиту
};
Проблема № 2: Валютні «фокуси» або як я став мільйонером (на екрані)
Ми додали мультивалютність: USD, EUR, PLN та інші. І тут я зловив свій улюблений баг. Я переказую 100 грн на свою доларову карта. Застосунок списує 100 грн і... зараховує 100 доларів. Профіт 4000% за секунду! Топ!
Вихід: Тепер вікно переказу — це міні-біржа. Ми додали крос-курси через гривню, щоб математика нарешті почала сходитися.
// Тепер ми рахуємо все чесно
if (mode === 'from') {
amountTo = rawAmount * (rateFrom / rateTo); } else {
amountFrom = rawAmount * (rateTo / rateFrom);
}
Проблема № 3: React-амнезія (Stale Closures)
Це був найпідступніший баг. Виглядало це так: юзер оновлює дві картки. Перша оновилася, все окей. Чекаємо хвилину (ліміт API, пам’ятаєте?), оновлюється друга... і транзакції першої картки просто зникають!
Я ледь не посивів. Виявилося, це «замикання» в асинхронному коді. Функція «пам’ятала» стан масиву на момент свого запуску і просто затирала нові дані старими.
Рішення: Переписали хук useLocalStorage на функціональний апдейт. Тепер ми завжди беремо актуальні дані безпосередньо перед записом. Для мене це звучить як заклинання, але воно працює!
Що ми маємо в результаті (версія 3.4.33):
Ми навчили HROSHI бути «своїм» в Україні. Ми знаємо, що таке Сільпо, АТБ, Нова Пошта та Bolt. Ми виділили донати на United24 та «Повернись Живим» в окрему категорію, бо це не просто «інші витрати».
Ми також додали Swipe-to-refresh (це було боляче без важких бібліотек) та авто-планування кредитів. Якщо ви в мінусі — ми покажемо вам графік погашення хоч на 5 років вперед, щоб ви бачили світло в кінці тунелю .
Що далі?
Ми щойно завершили закритий альфа-тест з першими 11 сміливцями. Наступного тижня ми відкриваємо двері для Бета-тесту (наступні 50 людей із вейтліста).
Якщо вам теж набридло, що банківські апки просто показують історію, а не допомагають планувати майбутнє — залітайте до нас.
👉 Залишайте свій email на hroshi.app, щоб отримати інвайт у Бету наступного тижня.
Чекаю на ваш фідбек у коментарях. Йдемо в прод чи мені краще повернутися до малювання презентацій? 🚀
P.S. і щойно побачив, що вікно переказу між рахунками не працює. Клас! Пака! Я пішов 😂

2 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів