- wallet
- transaction ledger
- reconciliation
- idempotency
Проєктування iGaming-гаманця: як пояснити кожен баланс

Спроєктуйте гаманець, який пояснює депозити, резерви, ставки, виплати й коригування за збереженими записами. Розберіть збалансовані проведення, атомарні рішення про витрачання, захист від повторів і звірку з конкретними критеріями перевірки.
Гаманець надійний, коли команда може точно відповісти: чому ця сума доступна зараз і які зафіксовані операції її пояснюють? Колонка балансу не дасть відповіді після втраченого повідомлення, ставок, що перетинаються, або пізнього коригування. Журнал допоможе, лише якщо входить до того самого контрольованого процесу запису, який вирішує, чи допустимий рух грошей.
Посібник призначений для архітекторів, керівників розробки та фахівців фінансової чи операційної перевірки. Він пропонує модель операційного журналу, розбирає записи й визначає підтвердження, необхідні для довіри до нього. Модель рахунків і суми умовні. Фінансові фахівці оператора та фахівці з дотримання вимог мають затвердити реальні рахунки, облік акцій, правила захисту коштів і політику коригувань; інженерний проєкт не вирішує цих питань за них.
Визначте повноваження гаманця та факти, які він має зберігати
Гаманець відповідає за грошові проведення та резерви. Платежі надають прийняті підтвердження провайдера; ігри — відомості про прийняті раунди й розрахунки; бонуси — правила фінансування та посилання на акцію. Ці модулі запитують операції через межу гаманця. Вони не ведуть кожен свій незалежно змінюваний баланс гравця. Ширший контекст розкривають послуги з архітектури iGaming та інтеграції платежів і перевірки особи.
Розрізняйте операцію та її записи в журналі. Операція зберігає намір, ідентифікатор і результат; група проведень містить дебетові й кредитові записи завершеної грошової зміни. Резерв обмежує доступну для витрачання суму, не обов’язково завершуючи цю зміну. Відхилений запит може мати запис операції без фінансових проведень. Збереження запиту не доводить його проведення.
- Збалансоване проведення: у кожної зафіксованої групи дебет дорівнює кредиту в межах її валюти та обліку.
- Контрольована доступність: витрачання й нові резерви не перевищують коштів, допустимих за затвердженими правилами.
- Стабільний ідентифікатор: повтор тієї самої прийнятої операції не створює нового фінансового результату; зміна її змісту виявляється.
- Збережена історія: коригування додають пов’язані записи. Користувачі застосунку не можуть переписувати або видаляти зафіксовані проведення.
- Простежуване відновлення: кожне зовнішнє посилання, завершення резерву й коригування пов’язані з початковою операцією.
Це запропоновані умови приймання, а не властивості, що виникають від назви сервісу «журнал». Адміністративні права, імпорт і коригування підтримки мають дотримуватися тих самих умов, що звичайні ігрові та платіжні запити.
Виберіть типи рахунків і точне представлення сум до проєктування балансу
З погляду оператора грошові кошти гравця — сума зобов’язання перед ним. В умовній моделі вона збільшується за кредитом і зменшується за дебетом. Тому дебет не означає автоматично «гроші йдуть із бізнесу»: зміст залежить від типу рахунку.
Посібник TigerBeetle з обліку пояснює збільшення активів за дебетом, зобов’язань за кредитом і наявність дебетових та кредитових записів у транзакції. Це обґрунтовує термінологію, але не визначає плану рахунків оператора чи визнання виручки.
Для прикладів використовуйте рахунок зобов’язань за грошовими коштами гравця, активний рахунок розрахунків із платіжним провайдером (PSP) для коштів у нього або сум до отримання та контрольний рахунок ігрових розрахунків. Останній — операційний кореспондуючий рахунок, а не автоматично ігрова виручка. Послідовність проведень нижче починається з нульових залишків, використовує EUR і не враховує комісій та податків. В інших сценаріях початкові залишки вказано окремо. Реальна відповідність рахунків потребує схвалення фінансових фахівців і окремого обліку строків розрахунків, комісій та інших зобов’язань.
Зберігайте валюту й визначену одиницю разом із кожною сумою. Ціле число підтримуваних мінімальних одиниць або десятковий тип із явною точністю та правилами округлення дозволяють зберігати точні значення; двійкова рухома кома не підходить для грошових підсумків, що є підставою для операцій. Не вважайте, що кожна підтримувана валюта або актив мають два знаки після коми. Перевіряйте кількість дробових розрядів вхідної суми, межі та перетворення на одиницю зберігання до приймання операції.
Документація PostgreSQL щодо числових типів розрізняє точні десяткові значення й неточну рухому кому, зазначаючи можливість округлення за заданої кількості дробових розрядів. Точне зберігання не замінює явних правил для надлишкової вхідної точності. Це приклад бази даних, а не вимога використовувати PostgreSQL.
Розділяйте грошові кошти й обмежений бонус за рахунками та посиланнями на джерело фінансування. Загальна показана сума не обов’язково доступна для ставки чи виведення. У простій грошовій моделі облікований залишок дорівнює кредитам мінус дебети; доступний залишок — облікованим коштам мінус активні грошові резерви. Формула передбачає відсутність дозволеного овердрафту й додаткових грошових обмежень. Реальні правила дії можуть зменшувати суму, придатну для конкретної гри чи виведення. Не об’єднуйте різні валюти або непов’язані права на акції в цій формулі.
Простежте депозити, резерви й розрахунки через відповідні записи
Використовуйте цей запропонований список операцій, щоб пов’язати кожну дію з її записами. Він передбачає повне завершення резерву; частковий розрахунок потребує окремо визначених правил розподілу.
- Депозит EUR 100. Коли узгоджене підтвердження дозволяє зарахування, дебетуйте рахунок розрахунків із PSP на EUR 100 і кредитуйте грошовий рахунок гравця на EUR 100 в одній групі проведень. Грошовий залишок — EUR 100. Укажіть прийнятий платіж і зовнішню транзакцію; повернення браузера не дозволяє цього проведення.
- Резерв під ставку EUR 30. Створіть резерв грошових коштів гравця та збережіть його призначення. У цій моделі резерв не створює проведеного дебету або кредиту: залишок зберігається EUR 100, у резерві EUR 30, доступно EUR 70. Пояснюваними мають бути і журнал, і історія резервування.
- Звільнення резерву, якщо ставку остаточно не прийнято. Додайте запис звільнення з посиланням на резерв. Залишок зберігається EUR 100, доступна сума повертається до EUR 100. Звільнення — не новий депозит EUR 30.
- Альтернативна гілка: проведення прийнятої ставки. Дебетуйте грошовий рахунок гравця на EUR 30 і кредитуйте контрольний рахунок ігрових розрахунків на EUR 30, водночас завершуючи резерв у тій самій атомарній операції гаманця. Облікована й доступна суми стають EUR 70; EUR 30 не мають додатково залишатися активним резервом.
- Розрахунок із загальною виплатою EUR 45. Дебетуйте контрольний рахунок ігрових розрахунків на EUR 45 і кредитуйте грошовий рахунок гравця на EUR 45 з посиланням на початковий прийнятий раунд. Залишок стає EUR 115. Виплата в прикладі включає ставку; додаткове повернення ставки дало б надлишкове зарахування.
- Запит виведення EUR 40. Зарезервуйте EUR 40 за затвердженими правилами виведення. Облікований залишок зберігається EUR 115, у резерві EUR 40, доступно EUR 75. Підтверджена завершена виплата дебетує грошовий рахунок гравця на EUR 40 і кредитує рахунок розрахунків із PSP на EUR 40, водночас списуючи резерв. Залишок тепер EUR 75, активного резерву немає.
- Сторнування виплати EUR 45, якщо цього вимагає перевірене коригування. Додайте нову групу: дебет грошового рахунку гравця EUR 45, кредит контрольного рахунку ігрових розрахунків EUR 45. Якщо після завершеного виведення інших витрат не було, залишок стає EUR 30. Збережіть початкову виплату й пов’яжіть із нею коригування; замінний розрахунок оформлюйте окремою явною операцією.
Звільнення та проведення ставки — альтернативні гілки. За відхиленого або скасованого виведення резерв звільняється лише тоді, коли правила взаємодії встановлюють, що виплата не відбулася й не відбудеться. Невідомий результат провайдера не можна вважати відмовою лише через сплив локального таймера.
Документація TigerBeetle щодо двоетапних переказів описує конкретну модель: резервування, потім проведення або скасування новим незмінним записом переказу, з підтримкою налаштованого спливу строку. Локальний механізм не встановлює завершення зовнішньої виплати. Правила спливу строку мають враховувати реальні умови зовнішнього приймання та відновлення.
Фіксуйте рішення про витрачання, операцію та проведення разом
Припустімо, доступно EUR 60 і водночас надходять два різні запити на EUR 40. Обидва можуть пройти попереднє читання балансу. Не дати їм витрачати ту саму суму може лише остаточне атомарне рішення про приймання: після успішного створення одного резерву доступно EUR 20, а другий запит має бути відхилений або очікувати реальної зміни балансу.
Для реляційної реалізації використовуйте транзакцію, яка разом перевіряє область операції та параметри, захищає зачеплені баланс і резерви, перевіряє доступність, записує всі проведення або зміни резервів і зберігає результат. Виберіть явне блокування рядків з однаковим порядком захоплення, умовні оновлення з перевіркою версії та інваріанта або відповідний варіант серіалізованого виконання. Блокування непов’язаного рядка запиту не захищає спільних коштів гравця. Черга на рахунок має також враховувати конкуруючих відправників і відновлення обробників; автоматично спільним блокуванням вона не стає.
Документація PostgreSQL щодо ізоляції пояснює: зафіксовані конкурентні транзакції за серіалізованого виконання еквівалентні послідовному порядку, а застосунок має обробляти помилки серіалізації. Захист обмежений транзакцією цієї бази; він не серіалізує віддалений виклик провайдера разом із гаманцем.
Зовнішні виклики мають виконуватися поза короткою транзакцією захисту коштів. Зберігайте намір зовнішньої роботи й відновлюйте її зі стабільним ідентифікатором операції після локальної фіксації. Якщо транзакцію бази потрібно перезапустити після взаємного блокування або конфлікту серіалізації, повторюйте все її локальне рішення з тим самим ідентифікатором операції; не повторюйте платіж провайдеру як випадковий побічний ефект перезапуску.
Обмежте захист від повторів довіреним учасником, що викликає сервіс, або інтеграцією, типом операції та стабільним ідентифікатором запиту. Пов’яжіть його з гравцем, рахунком, валютою, сумою, розподілом фінансування та відповідним початковим посиланням. Повтор ідентифікатора події й повтор бізнес-операції — різні випадки: два повідомлення можуть стосуватися одного розрахунку. Фінансовий ідентифікатор визначається на межі, що відповідає за запис.
Amazon Builders’ Library описує ідентифікатори від сторони, що викликає сервіс, атомарне збереження зі змінами й відхилення змінених параметрів під тим самим ідентифікатором. Якщо токен гаманця зберігається до проведень або проведення до токена, виникає розрив у разі збою — крім випадку їх спільної фіксації.
Одночасні повтори мають сходитися до збереженої операції завдяки обов’язковій унікальності та транзакції проведень. Після втрати відповіді дозволений пошук або безпечний повтор мають визначати початковий результат, а не просто повідомляти «вже існує». Зберігайте достатні фінансові посилання довше короткого кешу відповідей API; пізній повтор не має ставати новим проведенням. Навмисно нове коригування отримує власний ідентифікатор і посилання на початкову операцію.
Виправляйте історію, не приховуючи нестачі
Журнал, що дозволяє лише додавання, зберігає зафіксовані записи; він не робить усіх змінюваних операційних полів незмінними. Статус процесу або похідний баланс можуть змінюватися за контрольованими переходами. Початкову групу проведень, суму, рахунки й посилання не можна редагувати, щоб історія виглядала як найновіший результат. Обмеження запису застосунку, контроль привілейованого доступу та підтвердження відновлення мають забезпечувати це правило.
Коригування — фінансове рішення з повноваженнями, причиною та посиланням. Перевірте джерело провайдера або дозволену дію працівника, визначте результат для сторнування й обмежте повторні чи надлишкові сторнування. За часткового сторнування раніше скасована сума плюс нова не мають перевищувати допустимої початкової суми. Перевіряйте умову атомарно щодо інших коригувань; позначка адміністратора не звільняє операції від перевірки.
Розгляньмо варіант прикладу: після досягнення EUR 75 гравець витрачає ще EUR 50, залишаючи EUR 25, а потім сторнується виплата EUR 45. Просте віднімання дає від’ємний залишок EUR 20, порушуючи заборону овердрафту в цій моделі. Ні відкидання коригування, ні непомітне обнулення не пояснюють відсутньої суми.
Якщо затверджені правила дозволяють фінансове врегулювання з використанням решти EUR 25, умовна група може дебетувати грошовий рахунок гравця на EUR 25, дебетувати схвалений фінансовими фахівцями рахунок збитку або дебіторської заборгованості на EUR 20 та кредитувати контрольний рахунок ігрових розрахунків на EUR 45, указавши справу розбору. Залишок стає нульовим, а нестача залишається облікованою. Дебіторська заборгованість має означати обґрунтовану затверджену вимогу, а не інженерну вигадку. Якщо правила не дозволяють такого врегулювання, збережіть коригування як нерозв’язану роботу й передайте його відповідальним; не оголошуйте його проведеним. Обмеження акаунта, повідомлення й подальше врегулювання визначайте з відповідальними фахівцями оператора.
Грошові, бонусні та змішані операції додають ще одну умову: коригування дотримується початкового розподілу фінансування й правил акції. Сторнування ставки з обмеженого бонусу не має непомітно перетворюватися на гроші, доступні для виведення. Інструменти працівників мають пропонувати підтримувані операції коригування з причинами й необхідним розглядом, а не прямий редактор балансу.
Звіряйте записи на однакових межах обліку
Звірка перевіряє, чи узгоджуються незалежно збережені факти на одній межі обліку. Почніть із внутрішніх перевірок: збалансовані групи, відсутність проведень без відповідної групи, завершення резервів із посиланнями на реальні резерви, відповідність результатів операцій проведенням і збережених представлень балансу журналу та активним резервам. Порівнюйте узгоджений знімок або явно однакові позиції; порівняння поточного журналу зі старим представленням створює хибні розбіжності.
Потім порівнюйте прийняті платіжні записи, операції гаманця та звіти провайдера або розрахунків. Зіставляйте спочатку стабільні посилання, потім валюту, суму, статус і період. Звіт про платежі провайдера та звіт про його банківські розрахунки можуть описувати різні межі; комісії, зворотні списання та строки розрахунків потребують явних категорій. Один підсумок не виявить відсутнього зарахування EUR 100, компенсованого непов’язаним зайвим зарахуванням EUR 100.
- Провайдер прийняв, проведення гаманця немає: установіть достовірний результат платежу, знайдіть початкову операцію гаманця й завершуйте її лише за правилами зарахування.
- Проведення є, відповіді немає: відновіть видимий результат операції; не додавайте проведення заради виправлення статусу.
- Результат виведення невідомий, резерв активний: з’ясовуйте початкове надсилання провайдеру й зберігайте резерв, доки правила відновлення не дозволять завершення.
- Внутрішні записи збалансовані, зовнішні підсумки розходяться: перевірте відсутні, повторні чи неправильно класифіковані операції, комісії та момент відсікання даних. Збалансований облік може відображати неправильні бізнес-факти.
Для кожної розбіжності потрібні відповідальний, сума під ризиком, час очікування, підтвердні посилання й дозволене рішення. Виконуйте коригування лише після встановлення причини та повноважень. Вважайте непояснене відхилення інцидентом за узгодженими порогами; анонімне «коригування звірки» вирівнює число, знищуючи пояснення.
Перевірте відновлення й перехід без появи другого гаманця
Перевіряйте гаманець на типових операціях і точках збою. Попросіть команду відтворити за записами один депозит, одну зарезервовану ставку, одну завершену виплату й одне коригування, включно з дебетом і кредитом там, де рух проведено. Вимагайте підтвердження відновлення кешованого відображення без перетворення його на друге джерело запису.
Для відновлення встановіть, до якої зафіксованої точки повертається база чи журнал, потім зіставте її із зовнішніми операціями, які могли завершитися після цієї точки. Відновлена локальна база не скасовує виплати провайдера. Збережіть і звірте підтвердження проміжку до дозволу нових витрат; повторна обробка має розрізняти відсутні локальні результати й уже завершені. Визначайте допустиму втрату даних і час відновлення за реальними зобов’язаннями та перевіряйте їх, а не обіцяйте нуль за замовчуванням.
Міграція потребує тієї самої дисципліни. Відтворіть початкові залишки й активні резерви, збережіть їхнє походження та зовнішні посилання, класифікуйте нерозв’язані операції. Звірте імпортовану початкову позицію зі старою системою й незалежними підтвердженнями на документований момент відсікання. Під час передавання для кожного рахунку має бути один компонент із правом запису; просте дублювання запитів у два журнали може повторити реальні дії або дати розбіжності в разі збою. До дозволу повернення до старого джерела перевірте відновлення нових записів.
Перевірка продуктивності має вимірювати фінансовий шлях: одночасні дії на часто використовуваних рахунках, очікування блокувань або конфлікти, швидкість фіксації проведень, час очікування незавершених операцій та відновлення за накопиченої черги. За потреби винесіть звітність із великою кількістю читань у контрольовані представлення, але не дозволяйте витрачання за застарілою реплікою для читання. Журнал, збалансований в окремій демонстрації успішного шляху, ще не пройшов наведених нижче перевірок конкурентності й відновлення.
Доповніть перевірку матеріалами про проєктування результатів платежів і звірки, фінансування ставок і розрахунки букмекерської платформи та межі безпеки й привілейовані права.
Обмеження акаунта, акції та координація модулів впливають на запити до журналу. Зберігайте їхні правила взаємодії видимими через архітектуру акаунтів гравців, проєктування бонусного рушія та повний шлях гравця й грошей. Гаманець залишається відповідальним за дотримання фінансових інваріантів, коли ці модулі запитують зміну.
- Втрачена відповідь і змінені параметри. Зафіксуйте депозит, втратьте відповідь і надішліть одночасні повтори з початковим ідентифікатором. Доведіть наявність однієї збалансованої групи проведень і дозволене отримання її результату. Повторіть з іншою сумою, валютою або гравцем: прийнята операція не має змінитися чи створитися заново.
- Конкуруючі витрати й завершення резерву. За доступних EUR 60 надішліть два різні запити на EUR 40. Доведіть, що обидва не можуть витрачати ті самі кошти. Потім одночасно звільніть і спишіть успішно створений резерв: допускається рівно одне дійсне завершення без залишеного дубльованого резерву або подвійного повернення.
- Пізнє й надлишкове коригування. Сторнуйте виплату EUR 45, коли залишилося лише EUR 25, за заборони овердрафту з прикладу. Покажіть затверджене врегулювання нестачі або явно нерозв’язану справу. Також одночасно запитайте часткові сторнування, що разом перевищують початкову суму: інваріант має зберегтися.
- Відновлення за вже завершеної зовнішньої роботи. Поверніться до локальної точки до збереження результату виплати, коли провайдер уже заплатив. Звірте початкове посилання до відновлення витрат. Перебудуйте представлення балансу й порівняйте їх на однакових позиціях; відновлення чи повторна обробка не мають надіслати ще одну виплату.
Чи достатньо подвійного запису для гарантії правильного гаманця?
Ні. Рівність дебету й кредиту перевіряє структуру обліку, а не справжність платежу, правильність суми або право гравця її витратити. Помилкові й повторні бізнес-операції також можуть балансуватися. Доповнюйте збалансовані групи довіреними підтвердженнями приймання, стабільними ідентифікаторами операцій, атомарними перевірками доступності та звіркою.
Чи потрібно щоразу перераховувати баланс за всією історією проведень?
Ні. Контрольоване представлення або накопичений баланс дозволяють ефективно читати й перевіряти витрати, якщо їхнє оновлення, що визначає рішення, атомарне з відображеними проведеннями та резервами. Зберігайте достатньо історії й відомостей про походження для перевірки або відновлення. Окремо оновлюваний кеш чи застаріла репліка не можуть ухвалювати остаточного рішення про приймання операції.
Чи має кожен резерв автоматично спливати?
Лише якщо це безпечно за правилами операції. Локальний резерв, що очікує завершення, не показує, чи прийняті зовнішня ставка або виплата. До повернення коштів у доступні сплив строку має унеможливити подальше приймання або встановити неприймання. Інакше зберігайте явний невідомий результат і з’ясовуйте його пошуком, звіркою або контрольованим розглядом.
Чи усуває зберігання лише з додаванням потребу контролю привілеїв?
Ні. Зафіксовані записи потрібно захищати в реальному процесі запису, імпорті, інструментах працівників і адмініструванні бази. Відділяйте дозволені коригування від видалення чи переписування та зберігайте, хто й чому їх схвалив. Строки зберігання, персональні дані й облікові обов’язки потребують явної політики; режим додавання не дає підстав копіювати чутливі документи в кожне проведення.
Підготуйте правила операції, типові проведення та один нерозв’язаний платіж або коригування. Ми можемо визначити обсяг перевірки відповідності рахунків, атомарного приймання, завершення резервів і звірки, з конкретними демонстраціями та рішеннями, закріпленими за відповідальними командами.



