Urgent.News

What's breaking now, across thousands of outlets.

Tech

How we made battles deterministic and server-verified in a Telegram mini-game

We are building Seraph Legion, an angel-collector RPG that runs inside Telegram as a Mini App. This is a writeup of the most interesting engineering decision in the project: how battles work , and what a farming exploit taught us about trusting clients. The constraint A Telegram Mini App is just a webview. Anything your client computes, a motivated player can fake - the JS is right there, the API…

Seraph Legion is an angel-collecting RPG built as a Mini App inside Telegram. One key engineering decision was ensuring battles were deterministic and server-verified. Since the client has full access to the code, the design required making the server the arbiter of outcomes. The battle simulator resides in a pure TypeScript module shared between client and server.

It uses a seeded random number generator to ensure identical results given the same inputs. The client reports its perceived outcome to the server, which then re-runs the simulation with the exact same seed and inputs. If the server's replay matches the client's, the rewards are calculated server-side from predefined data tables and entered into the ledger.

If the results don't match, the client's request is rejected. This process prevents cheating by ensuring the server controls all final outcomes. The team learned a valuable lesson from an exploit where a farm of accounts abused a migration endpoint to mint millions. As a result, most write operations are now server-verified, accepting only signed inputs and flagging anomalies for review.

While the client does render the battle animations, it cannot alter the final result. The game can be played at seraphlegion.com for more details on the simulation and the Telegram Open Network (TON) jetton implementation.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

Show DEV: I built a cozy Christmas village game in Godot, solo

Hi DEV, I'm the solo developer of Christmas Town, a free iPhone game where you decorate your own house, yard and Christmas tree in a snowy village.

  • Creator built solo Christmas Town game in Godot
  • iPhone game allows personalizing homes, yards, trees
  • Game features cozy decorating, shared town square

Co-op Bank customers hit by Sunday banking outage as App, USSD fail

Co-operative Bank of Kenya customers on Sunday, November 15, 2026, reported difficulties accessing their accounts and conducting transactions after the lender confirmed a technical disruption…

  • Co-operative Bank of Kenya experienced a Sunday outage on November 15, 2026
  • Customers could not access MCo-opCash app or USSD platform 667#
  • Bank acknowledged issue, support team working to restore services

Turning noisy bathroom-scale data into a projected date: SMA vs. EMA vs. linear regression

Body weight is a terrible time series. On a single morning it can swing by a kilogram or more because of water, salt, glycogen and whatever is still in your gut.

  • Simple moving average (SMA) calculates 7-day average weight, lagging about 3 days
  • Exponentially smoothed moving average (EMA) uses 10% smoothing factor, slower to respond
  • Linear regression estimates daily weight change, provides date estimate but assumes constant rate

How to Sync Billing Data to Prisma Postgres (Stripe, QuickBooks, Xero & Paddle)

Sync Stripe, QuickBooks, Xero or Paddle into Prisma Postgres. Which connection string to use, how a batched sync counts operations, and what it costs.

  • Prisma Postgres bills per operation, not query duration, making it cost-effective for batch syncs
  • Recommended pooled connection string for background workers like scheduled syncs
  • Sync of 375 Stripe paymentintents costs only 15 operations, demonstrating efficiency

Docker Compose build must be a string, in CI

Docker Compose build must be a string is the schema validator naming one branch of a rule with two, and following it literally will send you to rewrite a mapping that was never the problem.

  • "Docker Compose build must be a string" error occurs
  • Invalid key type or mapping branch causes the error
  • Validate Compose files in CI to prevent the error

More from Sunday 15 November →