The tech behind our game
If you haven't played our Funstash Meme prediction game, you can access it on Telegram or Farcaster. On the surface it's a very simple game, you pick some meme coins, select the up / down trend and watch it play our for 60 seconds.
But getting sub second price data for all the meme tokens we support is anything but trivial - specially since we didn't use a 3rd party API for this.
Architecture
Funstash is built using the Elixir language and the Phoenix framework. If you're not familiar with Elixir, it's a functional language that targets the same VM that Erlang, the language that powers projects like Whatsapp, RabbitMQ or Discord. If you're coming from JS / Typescript world, you're already used to asynchronous code (async/await). Elixir supports that, but there are a few more native building blocks that takes Elixir to another level:
- Supervision trees
- Seamless process communication across different machines
Supervision trees
Elixir is using the actor concurrency model, which is not unique to the language. It has a concept of a process, which can send and receive messages. Each process has a mailbox, so that it can buffer messages as well. A supervisor is a special process that, as the name implies, it supervises other processes. The built in supervision mechanisms allow you to build very resilient systems that are composed of a multitude of processes all communicating back and forth. If something goes wrong you can deal with the problem by restarting just one child, or restarting all the child's siblings. Or perhaps, restarting or shutting down other components that might rely on that particular child. If used correctly, this can ensure you application stays running even in the face of expected failures. Or completely shuts down to prevent corrupted state in the case where a core component fails.
Let's see how we used this to build our live price feed. There are not that many APIs out there that provide live streaming of price data for cryptocurrencies. And if there are, the pricing is very prohibitive. What is available for free though, is a live feed or order book data for most exchanges. We picked two high volume exchanges to start with: Kraken and Binance.

Our supervisor starts and monitors the websocket connection for each of the clients. If one of them crashes or doesn't respond to a heartbeat, it gets restarted and reconnected.
For each event (sometimes 1000s a second), the clients take the average of the bids and asks and broadcasts a normalized price event in a PubSub topic price:<symbol>

Now that we have the price event river just flowing continuously. Each time we start a game we can tap into just the events we're interested in. Depending on how many players are in and what tokens they select, we might tap into all the tokens or just a few.
Synchronize Prices
If you've played the game, you will notice that the price data updates at the same time for the three tokens you selected. This is the same for every single player in the game. We are computing the points based on the current price for all the tokens. Our price feed is per token, so we need a way to process those events and update all the tokens in the game at the same time. Enter the Trade Buffer Supervisor.
Each game starts a Trade Buffer process that is managed by the Trade Buffer Supervisor. When we start the Trade Buffer we specify the list of tokens in the current game. This is so that the process know the complete list of tokens it needs to buffer before broadcasting a game price event further downstream.

Game Server
By now you probably see a trend, each game is also a process supervised by a Game Supervisor. When a game starts, it triggers the Trade Buffer process in the Trade Buffer Supervisor and it subscribes to its PubSub topic (based on the game id).

But it goes deeper than that. Not only that each game has its own process that subscribes to the price feed list, but also the player's browser is connected to a special process known as LiveView via websockets. This makes it seamless and real-time all the way from the raw prices to the user's browser. Once you experience building applications this way, you'll never want to go back.
Once the game is over, the Trade Buffer Supervisor turns off the Trade Buffer process that was buffering the specific list of tokens. The same goes for each game's process. Processes come and go all orchestrated by the trusty supervisors. Even if something were to happen to a live game, the way we've built the supervision tree will ensure that everything gets restarted and picked up where it left off.