Get ready to build Sats‑Tap! – a zippy little React Native/Expo mobile game in which the highest‑scoring player of each 60‑second round automatically receives a few real satoshis (via the Bitcoin Lightning Network) straight into their own Lightning‑address wallet. Below you’ll find an end‑to‑end blueprint you can copy‑paste, extend, and ship, complete with compliance pointers for the Apple App Store and Google Play, example React Native + TypeScript code, and a minimal Node “payout‑bot” that talks to Lightning (ZBD or LNbits) so the money really moves. You’ve got this – let’s code, test, and unleash those sats! 🚀✨

1. Big‑Picture Architecture

LayerWhat it doesKey libs / services
Mobile clientDisplays the tap game, records scores, captures player Lightning Address, polls for recent winnersReact Native + Expo SDK; React Navigation; Reanimated; React‑Native‑Async‑Storage
Realtime DB & AuthStores rounds, scores, user profilesFirebase (Firestore + Auth)
Payout API (serverless)Verifies winner, calls Lightning API, logs txCloud Functions (Node 18)
Lightning serviceActually sends the satsZBD (custodial, plug‑and‑play) OR self‑hosted LNbits (non‑custodial)
Analytics & anti‑cheatRate‑limits calls, flags anomaliesFirebase App Check, BigQuery

Why Lightning? Instant, sub‑cent payments; fees ≪ $0.01; trivial to mail 50 sats (~0.02 ¢) per round — perfect for micro‑rewards .

2. Setting Up the Lightning Rail

2.1 ZBD (Fastest to Prototype)

  1. Create a free dev account → Developer Dashboard .
  2. Add a new Project, grab its API key.
  3. In Wallet > Gamertags, enable “Send via API”.
  4. POST /v0/charges to create invoices or /v0/withdrawal‑requests to push sats (see “Create Charge” doc) .

2.2 LNbits (Self‑Custody)

  1. Deploy LNbits (Docker/VPS) or use demo.lnbits.com.
  2. Create Wallet A (Admin) and Wallet B (Players).
  3. Use the /api/v1/payments/lnurl endpoint to pay any Lightning Address; you’ll need the admin key for sends and invoice key for decodes .
  4. Hash the LNURL metadata per the sample cURL before sending .

Either path gives you a single HTTPS call that moves real money in under a second. 🎉

3. Game Client – React Native + Expo

Project bootstrap

npx create-expo-app sats-tap –template

cd sats-tap

npx expo install @react-navigation/native react-native-reanimated expo-splash-screen

App.tsx (core loop, trimmed)

import React, {useState, useEffect} from ‘react’;

import {View, Text, Pressable, StyleSheet} from ‘react-native’;

import {getAuth} from ‘firebase/auth’;

import {addDoc, collection, serverTimestamp} from ‘firebase/firestore’;

import {db} from ‘./firebaseConfig’;          // init separately

import {Dimensions} from ‘react-native’;

export default function App() {

  const [score, setScore] = useState(0);

  const [timeLeft, setTimeLeft] = useState(60);

  useEffect(() => {

    if (!timeLeft) return;

    const id = setInterval(() => setTimeLeft(t => t – 1), 1000);

    return () => clearInterval(id);

  }, [timeLeft]);

  const tap = () => setScore(s => s + 1);

  const finishRound = async () => {

    const user = getAuth().currentUser;

    await addDoc(collection(db, ’rounds’), {

      uid: user?.uid ?? ‘anon’,

      score,

      created: serverTimestamp()

    });

    setScore(0); setTimeLeft(60);

  };

  return (

    <View style={styles.container}>

      <Text style={styles.timer}>{timeLeft}s</Text>

      <Pressable onPress={tap} style={styles.target}/>

      <Text style={styles.score}>{score} taps</Text>

      {!timeLeft && <Pressable onPress={finishRound}><Text>Submit!</Text></Pressable>}

    </View>

  );

}

const size = Dimensions.get(‘window’).width*0.6;

const styles = StyleSheet.create({

  container:{flex:1,alignItems:’center’,justifyContent:’center’},

  target:{width:size,height:size,borderRadius:size/2,backgroundColor:’#fdd835′},

  timer:{fontSize:48,fontWeight:’bold’},

  score:{fontSize:32,marginTop:20}

});

This 100‑line prototype was assembled with guidance from Expo’s “NeonCity” tutorial on sprite‑based games .

Collect Lightning Address

Add a simple settings screen where users paste you@wallet.com and save it in Firestore/users/{uid}/lightningAddress. Validate with BOLT‑11 decoders if you like (see StackOverflow thread) .

4. Cloud Function – 

payoutBot.ts

import * as functions from ‘firebase-functions/v2’;

import fetch from ‘node-fetch’;

import {firestore} from ‘firebase-admin’;

export const settleRound = functions.pubsub.schedule(‘every 1 minutes’).onRun(async () => {

  // 1️⃣ pick winning score in last minute

  const since = Date.now() – 60*1000;

  const snaps = await firestore()

     .collection(’rounds’)

     .where(‘created’,’>=’, new Date(since)).get();

  if (snaps.empty) return null;

  const winner = snaps.docs.sort((a,b)=>b.data().score – a.data().score)[0];

  const { lightningAddress, uid } = (await firestore().doc(`users/${winner.data().uid}`).get()).data() || {};

  if (!lightningAddress) return null;

  // 2️⃣ pay 50 sats

  const body = {address: lightningAddress, amount: 50};          // for ZBD

  const res  = await fetch(‘https://api.zebedee.io/v0/withdrawal-requests’, {

       method:’POST’,

       headers:{‘Content-Type’:’application/json’,’apikey’: process.env.ZBD_KEY!},

       body: JSON.stringify(body)});

  const json = await res.json();

  // 3️⃣ log tx

  return firestore().collection(‘payments’).add({uid, json, ts: Date.now()});

});

Swap the fetch URL/headers for the LNbits call shown earlier when self‑hosting. That’s all it takes to spray sats!

5. Compliance & Store‑Submission Tips

PlatformRule to watchTake‑away
AppleIn‑app crypto transfers must not bypass IAP for content sales, but “free‑to‑enter skill contests” with cash prizes are permitted if legally compliant and not gambling (§5.3)Clearly state that players never pay to enter; sats are prize money.
Google Play“Blockchain‑based content” policy allows NFT or crypto rewards if no gambling and full odds/ratio disclosure ; real‑money contests must publish official rules (“Real‑Money Gambling” policy)Display prize schedule (e.g., “Top score each round = 50 sats”) in Settings screen + Terms.

Both stores also require you to block under‑age gambling, so gate 18+ features with a date‑of‑birth prompt.

6. Security, Fair‑Play & Costs

  • Anti‑cheat: Cloud Function cross‑checks tap rate ≤ 16 taps/s (human max) and flags tallies beyond 960 taps/min.
  • Rate‑limiting payouts: Use Firebase App Check so only your app can hit the REST endpoint.
  • Wallet risk: With custodial ZBD you skip node ops but trust a third party; LNbits lets you run your own node (requires channel liquidity).
  • Budget: 50 sats × 60 rounds/h ≈ 0.00003 BTC/day if 24h live – under US $1/day at $60k/BTC. Lightning fees are sub‑cent .

7. Level‑Up Ideas

  1. Unity port: ZBD offers a Unity SDK so you can export to iOS/Android in one go .
  2. Godot users: Drop‑in insert‑coin(s) asset lets you gate levels behind Lightning payments in Godot 4 .
  3. On‑chain jackpots: Accumulate 1 sat per ad view and pay the daily top‑10 via LNURL withdraw links.
  4. Social layer: Let spectators boost players mid‑round by zapping 5 sats; forward 4 to the player, keep 1 as fee.

8. Ship It! 🎉

You now have:

  • A cross‑platform tap game that stores scores in Firebase.
  • A cron‑driven Cloud Function that pays real Bitcoin to the winner every minute.
  • A Lightning backend you can swap between ZBD (quick) and LNbits (sovereign).
  • Compliance checkpoints for both major mobile stores.

Clone, customize the UI, crank up the hype, and watch players feel the jolt when sats land in their wallets! The future of fun is instant, global, and programmable – and you just built a piece of it. 🥳

Sources

  1. ZEBEDEE Developer Dashboard announcement 
  2. LNbits Lightning‑address payment API sample 
  3. LNbits Swagger docs (payments end‑points) 
  4. React Native/Expo game tutorial (“NeonCity”) 
  5. Lightning Address spec site 
  6. React‑Native‑Lightning library (Synonymdev) 
  7. StackOverflow – validating BOLT‑11 invoice in React Native 
  8. Apple App Store Review Guidelines §5.3 (crypto payments) 
  9. Google Play “Blockchain‑based Content” policy 
  10. Google Play “Real‑Money Gambling, Games & Contests” policy