check-deposits hits the isolate's CPU ceiling on almost every run — 17 limit
events across 20 invocations in the last 20 minutes — and when it does, the
supervisor cancels the worker and the scan stops partway. Deposits after the
cut-off simply are not seen until some later run happens to reach them.
The cause is in deriveTronAddress: it calls mnemonicToSeedSync per user, which
is PBKDF2 with 2048 iterations. The seed depends only on the mnemonic, so with
51 accounts that cost was paid 51 times a minute to produce the identical seed.
Only the derivation path varies per user.
Derive the master key once and reuse it. Measured over the 51 accounts we
actually scan: 418ms -> 58ms, a 7.2x drop in the part that was blowing the
budget.
Verified the addresses are unchanged: old and new paths produce identical
private keys for every index tested, including repeated indexes in one run,
which is what would expose derive() mutating the parent key. It does not.
The main slot was described as a retired testnet bot. It is not retired — a
fresh bot was created for it on 2026-07-30 under separate ownership, username
@BizinikiwiBot, display name Pezkuwichain_Bot. It is not a recovery of the
compromised @pezkuwichain_bot; that account is gone and its token stays invalid.
Its webhook carries no ?bot parameter, so getBotId falls back to main and this
slot is now a live path rather than a fallback. The cloud secret
TELEGRAM_BOT_TOKEN holds the new token.
Also puts the PEX.network link on the main welcome, so all three bots offer it.
MINI_APP_URLS.main still pointed at telegram.pezkuwichain.io, the testnet domain
whose DNS record was removed on 2026-07-12. Live webhooks arrive as ?bot=krd and
?bot=dks so that default is never reached today, but a webhook call without the
parameter would have answered /start with a link that cannot resolve.
Also puts the PEX.network link on the krd menu — @pezkuwichainBot, the bot that
actually opens the mini app. It only existed on the dks welcome, so no user
reaching the mini app through the main bot has ever been shown it.
Leaves the three-slot routing alone: both slots are live and healthy on the
cloud project, and collapsing them would have removed the AI assistant.
The button is live but has never existed in this repo — `git log -S "Buy/Sell
Crypto"` returns nothing, so it was added by hand on the server and missed when
9bb9d2c synced git with the deployed source. Deploying telegram-bot from CI
would therefore have silently dropped it.
Restoring it here keeps what is actually running. Removing it should be a
deliberate decision, not a side effect of the first automated deploy.
`ask` has never been deployed, and the CI step in this branch will publish it.
Its limiter counts rows in ai_chat_log to cap requests at 8/min and 120/day per
IP, but no migration ever created that table, and the limiter fails open when
the count cannot be read.
Shipping `ask` without this would put an unauthenticated endpoint with
Access-Control-Allow-Origin: * in front of paid model APIs with no limit at all.
Applied to the live database as well.
#1 brought the live P2P identity resolution into main, which this branch's CI
deploy step needs to be present before it can safely publish these functions.
Version stamp was the only conflict; took main's.
The Supabase edge-function volume on the host is shared with pwap-web, which
deploys into it by rsyncing its whole tree. Both projects defined a function
called telegram-auth, so on 2026-06-28 pwap-web's login-widget handler replaced
this project's initData handler. Sign-in and every wallet screen behind it have
returned 401 ever since; nothing failed loudly because the name still resolved.
Rename this project's two colliding functions to a tgm- namespace so the two
deploys can no longer reach the same directory, and point the client at the new
name. process-withdraw is renamed too: it is currently unreferenced here, but it
moves platform funds, so leaving it shadowed by another project's version is not
something to keep.
Also deploy functions from CI. They were last pushed by hand in April, so seven
of them had drifted behind the repo and one had never shipped at all. The new
step writes through the host's ownership gate, which refuses any name this
project does not own — the drift and the collision both stop here.
Ownership is recorded in /opt/supabase-self-hosted/functions-registry.json.
User decision after the Groq reliability fix (previous PR): prioritize
Groq's smallest/fastest model, llama-3.1-8b-instant, over gpt-oss-120b —
it's long out of preview and has historically the best free-tier
availability, at the cost of gpt-oss-120b's better Turkish/Kurdish
fluency (which is why it was chosen originally). Model order is now
llama-3.1-8b-instant -> gpt-oss-120b -> llama-3.3-70b-versatile before
the (currently uncredited) Anthropic fallback.
Also fixed a real UX complaint: asking about the Mining Simulation made
the model repeat "this isn't real mining / it's just an estimate" in
nearly every paragraph. Added an explicit instruction to state that once,
briefly, near the start of the answer, and not repeat it — verified live,
the disclaimer now appears once per response instead of several times.
User decision after the Groq reliability fix (previous PR): prioritize
Groq's smallest/fastest model, llama-3.1-8b-instant, over gpt-oss-120b —
it's long out of preview and has historically the best free-tier
availability, at the cost of gpt-oss-120b's better Turkish/Kurdish
fluency (which is why it was chosen originally). Model order is now
llama-3.1-8b-instant -> gpt-oss-120b -> llama-3.3-70b-versatile before
the (currently uncredited) Anthropic fallback.
Also fixed a real UX complaint: asking about the Mining Simulation made
the model repeat "this isn't real mining / it's just an estimate" in
nearly every paragraph. Added an explicit instruction to state that once,
briefly, near the start of the answer, and not repeat it — verified live,
the disclaimer now appears once per response instead of several times.
The AI assistant (both @DKSKurdistanBot on Telegram and the news.pex.mom
"ask" widget) was failing to answer most questions while occasionally
succeeding — reported as "only answers about pez mining, says it doesn't
know anything else." Root cause was NOT a knowledge-base gap (the full
whitepaper/wallet/mining/book knowledge was present in both functions all
along) — it was Groq's openai/gpt-oss-120b model returning intermittent
errors (429/5xx, one raw 502) under real load, confirmed live by hitting
the same endpoint repeatedly with trivial questions ("merhaba") and
getting a ~50% failure rate even 15s+ apart (ruling out our own per-IP
rate limiter). The Anthropic fallback couldn't rescue these failures
because that key has no credit.
Fix: retry each Groq call up to 2x with backoff, and fall back to
llama-3.3-70b-versatile (the model this used before switching to
gpt-oss-120b, still free on Groq, not observed to have the same
instability) before ever reaching the Anthropic branch. Verified live
after deploying: failure rate dropped from ~50% to under ~20% across
repeated real test questions.
Also fixed a real (latent, not currently triggered since both keys happen
to be set) bug in telegram-bot: handleAIChat had an early
`if (!ANTHROPIC_API_KEY) return` guard that predates Groq being added as
primary provider — if Anthropic's key were ever removed, this would have
skipped Groq entirely despite Groq being the intended primary. Changed to
only bail if BOTH keys are missing.
Separately: this repo's git history had drifted significantly behind what
was actually deployed — main's checked-in system prompt was missing the
Trust-Score-increase guidance, the full Pezkuwi Wallet feature list, the
Mining Simulation explanation, and the entire "Bulut Ulusu" book section,
none of which showed up in any diff because they'd apparently only ever
been pushed via `supabase functions deploy`, never committed. Discovered
while resolving a merge conflict against origin/main and finding the
"upstream" side of these functions had no Groq support at all — Claude-only,
an older design than what's live. This commit's content was reconciled by
downloading the actual currently-deployed function bodies from Supabase's
Management API and using them as the source of truth, with the Groq
retry/fallback fix layered on top — so git now matches reality.
Root cause chain found while investigating why TRC20/TON/Polkadot deposits
were never being credited after the self-hosted Supabase migration:
- DEPOSIT_TRON_HD_MNEMONIC, TRONGRID_API_KEY, DEPOSIT_TON_ADDRESS,
DEPOSIT_POLKADOT_ADDRESS and the pg_cron job itself were never carried
over during the 2026-04-09 migration, so check-deposits never ran.
- Once reconnected, the TRC20 loop was fully sequential (one address at a
time) and hit the edge function's CPU/time budget with 50+ users -
parallelized with a bounded concurrency of 8.
- The dedup check (select-by-tx_hash + .single()) breaks permanently once
2+ rows ever share a tx_hash - .single() then errors on every future
lookup, so the guard silently stops working and every cron tick
reinserts. This is what produced 50k+ and 30k+ duplicate rows for two
historical deposits back in April. Replaced with upsert +
onConflict/ignoreDuplicates against a new unique constraint on tx_hash,
so duplicates are impossible at the DB level regardless of app-level
races.
- deposit_index 0 is the platform admin account and also used as the
treasury sweep destination - excluded from the TRC20 scan so internal
sweep transfers landing on it are never mistaken for a customer deposit.
- Correct Instagram/TikTok/Telegram/X/Facebook URLs to official accounts
- Apply same Telegram channel fix to bot welcome messages
- Add ask edge function powering the AI assistant on news.pex.mom
The Telegram assistant now answers via Groq (free) first and falls back to
Claude when ANTHROPIC has credit. Keys come from env (GROQ_API_KEY /
ANTHROPIC_API_KEY) — no secrets in source. Wallet/p2p logic untouched.
Add p2p_user_id column to tg_users to bridge citizen/visa UUID (v5)
used by pwap/web with the Supabase Auth UUID (v4) used by the mini app.
- Migration: tg_users.p2p_user_id UUID (nullable, indexed)
- 6 P2P edge functions: replace listUsers+find with direct tg_users
lookup — resolves userId as p2p_user_id ?? id (backwards compatible)
- Eliminates O(N) auth.admin.listUsers scan in every P2P call
When p2p_user_id is populated (via TelegramConnect wallet link),
mini app users share the same P2P balance and offers as pwap/web.
- Add DKS bot support to telegram-bot and telegram-auth functions
- Claude-powered Q&A using PezkuwiChain whitepaper knowledge base
- Update Telegram social link to dijitalkurdistan channel
request-withdraw-telegram now sends tokens from hot wallet to user wallet
using @pezkuwi/api, instead of leaving requests in pending state.
Falls back to pending if PLATFORM_PRIVATE_KEY is not configured.
- Rewrite DepositWithdrawModal to send TX automatically via assetHubApi
instead of manual copy-paste-hash flow
- Fix listUsers pagination bug (default 50) in 4 edge functions by
adding perPage: 1000 - fixes P2P offers not showing for users
- Add new i18n keys for automated deposit states in all 6 languages
- Fix process-withdraw and verify-deposit-telegram to use RPC_ENDPOINT
env var defaulting to Asset Hub (wss://asset-hub-rpc.pezkuwichain.io)
- Add P2P E2E test script (scripts/p2p-e2e-test.py) covering full flow:
offer creation, trade accept, payment, escrow release, cancel, visa
user trade, and withdrawal request
- Update p2p_balance_transactions transaction_type check constraint
to include withdraw_lock, withdraw_complete, dispute_refund
- Remove wallet setup/create/import/connect steps from CitizenPage
- Add privacy notice banner with Shield icon to form
- Add seed phrase textarea with mnemonic validation
- CitizenProcessing creates keypair directly from seed phrase
- CitizenSuccess shows 3-step next process info
- Add /citizens path support alongside ?page=citizen
- Update bot URL to /citizens
- Add 10 new i18n keys in all 6 languages
- Add telegram.pezkiwi.app to CORS allowed origins in all edge functions
- Support multiple bot tokens (TELEGRAM_BOT_TOKEN, TELEGRAM_BOT_TOKEN_KRD) in auth
- Dynamic origin matching for proper CORS headers
- Add announcement-reaction Edge Function for secure like/dislike
- Update telegram-auth to sync users to tg_users table
- Update useAnnouncementReaction hook to use Edge Function
- Add bridge announcement script and migration
- AuthContext now stores and exposes sessionToken from telegram-auth
- App.tsx sends session_token instead of tg_id to P2P
- Enables secure cross-app authentication without from_miniapp method
- Remove insecure from_miniapp auth method (telegram_id spoofing vulnerability)
- Implement HMAC-SHA256 signed session tokens (replace weak Base64 encoding)
- Reduce token expiry from 7 days to 24 hours
- Restrict CORS to production domains only (telegram.pezkuwichain.io, t.me)
- Add detailed debug logging for troubleshooting