LuckyMe is a Solana mobile-first luck pool game for fixed-entry rounds. Users
connect a Solana wallet, choose a pool, review the ticket transaction, and sign
with their wallet. The project includes the Solana Mobile / Seeker app and the
browser web app at https://www.lucky-me.app/play/.
Pool math is transparent: fixed ticket price, total tickets, winner chance, prize, jackpot contribution, and treasury fee. Results and payouts are executed by the Solana program.
Production status (verified read-only on 2026-07-14): the minimum-ticket and automatic-refund program, backend, web release, settlement keeper, push alerts, operations monitor, and protected admin control are live. Mini 7, Normal 6, High 6, and Premium 7 are open and waiting for their first ticket; all have
startTs=0andendTs=0. The Seeker1.1.7/ code10APK was submitted through the Solana dApp Store Publisher Portal. The signed Seeker1.1.9/ code12APK is the verified update candidate prepared on 2026-07-15.
The one-hour timer starts only when the first ticket is confirmed. A draw is valid only when the round reaches its target before the timer expires:
| Pool | Ticket target | Distinct-wallet target |
|---|---|---|
| Mini | 25 | 1 |
| Normal | 13 | 1 |
| High | 3 | 1 |
| Premium | 3 | 3 |
Mini, Normal, and High count total tickets, not distinct players: one wallet may buy the complete target. Premium keeps one ticket per wallet and requires three distinct wallets. If a round expires below either applicable target, no ORAO request or winner draw is created. The authorized settlement keeper automatically returns every ticket's full purchase principal and closes each Entry account so its rent returns to that player. Solana network fees already paid to the network cannot be refunded. There is no player claim step.
- Release mode:
MAINNET_RELEASE - Network target: Solana
mainnet-beta - Wallet chain:
solana:mainnet - Program ID:
4bndxrGfuUcSLJnbCu8vs9WZ4qHdKGwcoeCybNThkrA3 - Mobile app: Expo React Native with Mobile Wallet Adapter
- Web app: static landing and browser dapp shell for
lucky-me.app - Backend: transaction builder and public state API
- Randomness: ORAO VRF only for expired rounds that reached their draw minimum; below-target rounds enter refund mode without an ORAO request.
- Player custody: the backend never signs player transactions and never custodies user funds.
- Device smoke test: Victor reported the signed Seeker build tested on a Seeker phone on 2026-07-07.
The app builds an unsigned transaction, the connected wallet signs it, and the
backend submit relay is disabled by default. Users see the amount, pool,
connected wallet, Solana mainnet network, and expected ticket behavior before
signing. The legal/community surface is Links only: Terms, Privacy, Support,
and future X/Discord placeholders.
programs/luckyme/ Anchor program
idl/ Generated IDL
sdk/ TypeScript IDL type helper
scripts/ Operator and keeper transaction builders
backend/ Public state API and transaction builders
app-seeker/ Solana Mobile / Seeker Expo app
docs/ Publishing, APK signing, operations, and handoff docs
tests/ Node and Anchor integration tests
sim/ Economic simulator and unit tests
Set these backend variables for MAINNET_RELEASE:
export LUCKYME_RELEASE_MODE=MAINNET_RELEASE
export LUCKYME_SOLANA_CLUSTER=mainnet-beta
export ANCHOR_PROVIDER_URL=https://api.mainnet-beta.solana.com
export LUCKYME_RANDOMNESS_MODE=orao_vrf
export LUCKYME_PRODUCTION_RANDOMNESS=true
export CORS_ORIGIN=https://lucky-me.app,https://www.lucky-me.app
export ENABLE_TRANSACTION_SUBMIT=false
export LUCKYME_PUSH_TOKEN_STORE=/var/lib/luckyme/push-tokens.jsonSet these app variables for the Solana Mobile dApp Store APK build:
export EXPO_PUBLIC_LUCKYME_RELEASE_MODE=MAINNET_RELEASE
export EXPO_PUBLIC_LUCKYME_STORE_BUILD=true
export EXPO_PUBLIC_LUCKYME_API_URL=https://api.lucky-me.app
export EXPO_PUBLIC_LUCKYME_WALLET_CHAIN=solana:mainnet
export EXPO_PUBLIC_LUCKYME_WALLET_RPC_URL=https://api.mainnet-beta.solana.com
export EXPO_PUBLIC_LUCKYME_SOLANA_CLUSTER=mainnet-beta
export EXPO_PUBLIC_LUCKYME_PROGRAM_ID=4bndxrGfuUcSLJnbCu8vs9WZ4qHdKGwcoeCybNThkrA3
export EXPO_PUBLIC_LUCKYME_TERMS_URL=https://lucky-me.app/terms
export EXPO_PUBLIC_LUCKYME_PRIVACY_URL=https://lucky-me.app/privacy
export EXPO_PUBLIC_LUCKYME_SUPPORT_URL=https://lucky-me.app/supportRelease validation rejects:
- missing production environment variables;
- loopback or LAN backend URLs;
- non-HTTPS mainnet RPC URLs;
- non-mainnet wallet chain values;
- placeholder terms, privacy, or support URLs;
- production commit-reveal randomness.
npm install
npm run app:validate:production
node backend/src/server.mjsImportant backend behavior:
GET /configexposes release mode, cluster, Program ID, randomness mode, economics, and public release checks.GET /poolsreads the Solana program state. InMAINNET_RELEASE, unavailable on-chain state returns an unavailable/error state rather than fake pool data.- Public pool state is cached once per short state window; wallet-specific Entry data is enriched separately with bounded caching and batched RPC reads. Concurrent requests for the same wallet share one in-flight read.
POST /transactions/buy-ticketsbuilds and simulates an unsigned ticket transaction for the connected wallet.POST /transactions/refund-entryis retired and returns410; below-target refunds are executed only by the authorized, journaled settlement keeper.POST /transactions/request-randomness,POST /transactions/request-orao-randomness, andPOST /transactions/settle-provider-roundsupport the ORAO keeper flow.POST /transactions/submitis disabled unless explicitly enabled; keep it disabled for production.POST /notifications/registerstores opted-in Expo push tokens for the APK notification flow; responses return only a token hash.
Round notification sender:
CONFIRM_MAINNET_PUSH_ALERTS=true \
LUCKYME_PUSH_SEND=true \
npm run push:round-alertsThe sender reads confirmed on-chain rounds and sends max two notifications per
active round per registered APK token: countdown started and last 10 minutes.
Without LUCKYME_PUSH_SEND=true, it runs as a dry-run.
Incident forensics:
ANCHOR_PROVIDER_URL=https://api.mainnet-beta.solana.com \
npm run incident:forensics -- --pool mini --round 2The report is read-only and prints pool vault balances, entries, active rounds, and ORAO randomness state for the deployed mainnet program.
The public site lives under site/lucky-me.app and deploys as static files to
/var/www/luckyme/public.
- Landing:
https://www.lucky-me.app/ - Browser dapp:
https://www.lucky-me.app/play/ - Player rules:
https://www.lucky-me.app/how-to-play/ - Legal/support pages:
/terms/,/privacy/,/support/
The web wallet UI exposes one public Connect wallet action. After click it
shows detected Solana browser wallets. On mobile Chrome, where Solana providers
are not injected, it also offers neutral app-browser actions for Phantom,
Solflare, and Backpack. WalletConnect/Reown is configured through
window.LUCKYME_WALLETCONNECT_PROJECT_ID in /config.js; the public Reown
project must keep https://lucky-me.app and https://www.lucky-me.app
allowlisted.
The referral flow is available only in the Android Seeker app and verifies both
wallet ownership and an authentic Seeker Genesis Token. An invite code is
optional and immutable after it is accepted. Shared invites open the LuckyMe
listing in the Solana dApp Store; the recipient enters the separate LM-XXXXXX
code in the app before verification.
Production qualification is calculated automatically from the append-only settlement archive and distinct app-activity days. A referred owner qualifies after three completed rounds with a winner on three different days plus seven active LuckyMe days. Cancelled or refunded rounds do not count.
The protected, read-only /admin/ page has separate Server Status, Treasury
Estimate, Winners and Referrals tabs. The referral tab shows inviter/invitee
identity, immutable binding status and qualification progress without adding
any game or settlement write path.
cd app-seeker
npm install
npm run validate:production
npm run typecheck
npm run doctorThe app defaults wallet authorization to solana:mainnet and uses
https://api.mainnet-beta.solana.com as the fallback wallet RPC. The
dapp-store profile still requires explicit production env through:
app-seeker/scripts/validate-production-env.mjsapp-seeker/app.config.js
For EAS cloud builds, set EXPO_PUBLIC_LUCKYME_API_URL,
EXPO_PUBLIC_LUCKYME_WALLET_RPC_URL, EXPO_PUBLIC_LUCKYME_TERMS_URL,
EXPO_PUBLIC_LUCKYME_PRIVACY_URL, and EXPO_PUBLIC_LUCKYME_SUPPORT_URL in the
EAS project environment or as EAS secrets before the dapp-store build. The
build must use HTTPS production URLs, not loopback or LAN addresses.
The current signed update candidate is app version 1.1.9, Android
versionCode 12, and keeps package com.luckyme.seeker. It includes the
tested ticket picker, smooth countdown, notification icon and permission flow,
production FCM configuration, current refund/rent explanations, a focused Home
screen, the Seeker Referral League rules and prize table, the optional one-time
review request, and the Social navigation screen with a permanent Discord
#welcome invite. It also keeps the explicit block on unused overlay and
legacy external-storage permissions.
Build the Solana dApp Store APK with EAS:
cd app-seeker
eas build --platform android --profile dapp-storeFor a local build with Android SDK/NDK installed:
cd app-seeker
eas build --platform android --profile dapp-store --localThe Solana dApp Store accepts signed APK files. app-seeker/eas.json contains a
dapp-store profile with android.buildType set to apk.
Create a dedicated dApp Store signing key if you manage signing locally:
keytool -genkey -v -keystore luckyme-dapp-store.keystore \
-alias luckyme-dapp-store \
-keyalg RSA \
-keysize 2048 \
-validity 10000Verify the signed APK:
apksigner verify --print-certs app-release.apkDo not commit:
- keystores;
- key passwords;
- Expo credentials;
- Solana keypairs;
- Publisher Portal API keys.
Based on the official Solana Mobile dApp Store docs, prepare:
- Prepare a release-ready APK signed with the release key.
- Prepare app metadata: name, description, screenshots, and icon.
- Use a Solana browser-extension wallet with enough SOL for submission fees and storage costs.
- Review the Publisher Policy and Developer Agreement.
- Create a Publisher Account in the Publisher Portal and complete KYC/KYB.
- Connect the publisher wallet and keep access to it for future submissions.
- Set the storage provider for APK and asset uploads.
- Add LuckyMe app details and submit the first release version.
- After submission, monitor the publisher email for review results.
Optional CLI publish path:
npm install -g @solana-mobile/dapp-store-cli
export DAPP_STORE_API_KEY=<publisher-portal-api-key>
dapp-store \
--apk-file ./app-release.apk \
--keypair ./publisher-keypair.json \
--whats-new "$(cat docs/store-listing/whats-new-v1.1.0.txt)"The CLI path requires an app already created in the Publisher Portal, an App NFT minted, a signed APK, a Solana signer keypair, and a Publisher Portal API key.
Store listing material is in docs/store-listing/:
short-description.txtfull-description.mdwhats-new-v1.0.0.txtwhats-new-v1.1.0.txtwhats-new-v1.1.7.txtwhats-new-v1.1.8.txtwhats-new-v1.1.9.txtscreenshot-checklist.mdicon-adaptive-icon-checklist.mdprivacy-policy.mdsupport-contact.mdrequired-links.mdcategory.txt
required-links.md tracks the final terms, privacy, and support URLs that must
be configured before submitting the APK.
Store readiness is tracked in docs/store-readiness.md; it uses the same
MAINNET_RELEASE, solana:mainnet, mainnet-beta, and signed APK release
positioning as this README. docs/release-v1.0.0-mainnet.md is retained as
historical v1.0 evidence. The minimum-ticket 1.1.0 release-candidate evidence
and still-gated mainnet plan are recorded in the dated July 11 documents under
docs/.
The official Solana Mobile docs specify signed APK submission, app metadata, Publisher Portal account/KYC, publisher wallet SOL for submission/storage, storage provider selection, Publisher Policy review, Developer Agreement review, and optional publishing CLI requirements. LuckyMe keeps those as the store-submission requirements in this repo.
Run the repository checks:
npm install
npm test
npm run app:validate:production
npm run app:typecheck
npm run backend:validate:production
npm --prefix app-seeker run doctor
npm run audit:mainnet-release
cargo check
cargo testFor production backend smoke testing:
LUCKYME_RELEASE_MODE=MAINNET_RELEASE \
LUCKYME_SOLANA_CLUSTER=mainnet-beta \
ANCHOR_PROVIDER_URL=https://api.mainnet-beta.solana.com \
LUCKYME_RANDOMNESS_MODE=orao_vrf \
LUCKYME_PRODUCTION_RANDOMNESS=true \
CORS_ORIGIN=https://lucky-me.app \
ENABLE_TRANSACTION_SUBMIT=false \
npm run backend:validate:productionBuild and verify the Solana Mobile APK after final EAS env values are set:
npm run app:build:dapp-store
APK_PATH=/path/to/app-release.apk npm run app:apk:verify



