Commit Graph

66 Commits

Author SHA1 Message Date
martbost 7d6818a8d4 Buy flow: survive mobile app-switch fetch drops
Mobile drops in-flight fetches when the page returns from the wallet app, which
aborted the purchase before the tx ("Failed to fetch"). Retry /api/me and
/api/sponsor, and make waitTx keep polling through transient fetch failures.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 10:08:34 -05:00
martbost bd4040ff4f Rebuild wallet connect on Reown AppKit (universal, all wallets, working icons)
Replaces the low-level ethereum-provider + deprecated modal (broken icons, jank)
with Reown AppKit loaded from the CDN — the standard connector every wallet
supports, with QR + mobile deep-links and a polished picker. Keeps the exact
SIWE sign-in and contract buy/activate logic, driving AppKit's EIP-1193 provider.
CSP widened for the AppKit SDK/RPC + a worker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 09:48:38 -05:00
martbost b0f807f6a5 WalletConnect buy: stop overriding gas (let wallet set fees)
Setting fees made MetaMask show an unclearable "site-suggested fee" alert. Hand
fee control back to the wallet; its own estimate meets Amoy's minimum.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 09:38:15 -05:00
martbost 952f2367d6 WalletConnect: always show the wallet picker (no auto-deeplink to last wallet)
Clear WALLETCONNECT_DEEPLINK_CHOICE before each connect so users aren't trapped
auto-launching a wallet that can't finish (e.g. Trust on Amoy); the All Wallets
picker shows every time so they can choose MetaMask.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 09:32:38 -05:00
martbost 89d636df82 Disconnect wallet: clear all WC state + reload so the picker truly reappears
Clearing localStorage alone wasn't enough — WalletConnect keeps the last wallet
and session in memory, so it auto-reconnected the same wallet. Broadened the
storage purge and reload the page after disconnect, guaranteeing a clean pick.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 09:26:34 -05:00
martbost 379a5352ea Add "Disconnect wallet" button (clears stuck WC session / switch wallets)
A stuck WalletConnect request or wrong-wallet choice could trap testers. New
IAPWallet.disconnect() drops the WC session, forgets the chosen provider, and
clears WC localStorage so the next connect re-offers the picker. Surfaced as a
"Disconnect wallet" button on the Wallet pane.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 09:21:42 -05:00
martbost d23eb10c58 WalletConnect buy: lower maxFeePerGas ceiling to 50 gwei
250 gwei ceiling tripped MetaMask's "network fee higher than necessary" alert on
Amoy (base fee ~0). 50 gwei keeps priority above Polygon's ~25 gwei floor while
reading as a normal fee, so buyers get a clean Confirm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 09:12:19 -05:00
martbost 7469a4907c WalletConnect buy: set EIP-1559 fees above Polygon's min priority fee
Amoy/Polygon reject txs whose priority fee is under ~25 gwei ("gas tip below
minimum"); wallets lowball it. Set explicit maxPriorityFeePerGas 30 gwei,
maxFeePerGas 250 gwei ceiling, and a 600k gas limit so buys/activations aren't
rejected or mis-estimated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 09:07:00 -05:00
martbost 90e33a42b5 WalletConnect: add redirect metadata (return to dApp after wallet approvals)
Sets metadata.redirect so mobile wallets bounce the user back to /my after each
approval instead of stranding them in the wallet app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 08:56:10 -05:00
martbost dcfc5ca86e WalletConnect: make the chain optional (fixes Trust hang on Amoy)
Requiring Amoy (80002) in the session namespaces made Trust Wallet hang on
"redirecting" — testnet wallets that don't natively list Amoy can't satisfy a
required-chain proposal. Switched to optionalChains so the session establishes;
the chain is switched/added after connect.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 08:44:21 -05:00
martbost 9cff0dc667 WalletConnect: gate to public chains (137/Amoy), not the private rehearsal
External wallets reject a WalletConnect session for the private rehearsal chain
(31337) with "user rejected", since they don't recognize custom chains. Only
offer WalletConnect on chains wallets know (Polygon mainnet / Amoy); it lights up
automatically when the site points at a public chain. Rehearsal keeps the
injected/dApp-browser path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 08:05:58 -05:00
martbost f0e42e47bb Add WalletConnect: connect from any mobile browser (no dApp browser)
Mobile users in a normal browser hit "no wallet found" because EIP-6963 only
sees injected/extension wallets. WalletConnect fixes it: the connect picker now
offers WalletConnect (auto-selected when no injected wallet is present), which
shows a QR on desktop and opens the wallet app directly on mobile — no in-app
dApp browser, no second login. Lazy-loads the @walletconnect/ethereum-provider
UMD from jsdelivr; the result is a plain EIP-1193 provider so sign/switch/buy are
unchanged. CSP widened for the SDK + WC relay. Project id lives in site config
(public value); gated so nothing changes until it's set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-08 07:36:07 -05:00
martbost 0c803c07cb Legal pages (Terms, Privacy, Disclaimer) + always-present footer
- New /terms, /privacy, /disclaimer pages in the site style with real content
  tailored to an on-chain ad+referral platform (no income guarantee, crypto
  risk, rehearsal note, privacy of email/wallet/profile, acceptable use).
- renderNav now appends a persistent footer with legal + site links on every
  public page; member-area sidebar gets a Legal link group.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-07 09:38:08 -05:00
martbost 4e50e02e9d Ship logo (header + favicon) + bolder downline level labels
- Logo lockup (mint lightning/arrow icon + InstantAdPay wordmark) replaces the
  text wordmark in the back-office sidebar and public nav; icon added as the
  favicon on every page. Assets: /logo.png, /logo-icon.png.
- Downline level captions (LEVEL 1 / LEVEL 2 …) are now a bold mint pill instead
  of faint grey — far more readable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-07 09:26:03 -05:00
martbost ae580b966c 125x125 sidebar banner (sized ad serving) + shorts report link
- New 125x125 "square button" banner size; ad serve now filters by width/height,
  and the sidebar slot serves a 125x125 banner (empty until such inventory exists).
- Shorts reel gets a "report this short" link (posts to /api/report-ad).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-07 08:47:17 -05:00
martbost 0dbd99f69e Wall page: mint QR, achievement badge, admin-ad backfill, join gated on views
- QR is mint-green (still high-contrast for reliable scanning).
- The wall shows the owner's achievement badge next to their avatar.
- Positions 2 & 3 fill with upline line-banners, then ADMIN ADS when there's no
  upline (configurable via data/admin-wall-ads.json; sensible default) so the
  wall is never sparse.
- "Join free through this wall" is disabled until the visitor has viewed every
  ad on the wall, with a "X/Y viewed" prompt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-07 08:35:44 -05:00
martbost 9fd85e0d6c Multi-wallet support: EIP-6963 discovery + picker
Detects all injected wallets via EIP-6963 (Trust, MetaMask, SafePal, Phantom,
OKX, TokenPocket, and any 6963 wallet), with named fallbacks for ones that don't
announce and window.ethereum(.providers). One wallet connects directly; multiple
show a picker. connect()/sendTx() resolve a provider before use.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-07 08:24:28 -05:00
martbost bc95965814 Featured to top, centered, capped; banner ads capped 728px centered; slot CTA
- Featured card moved to the top of Overview, centered, max 760px; the rotating
  link is capped to 728px and centered (banner-sized, not a huge block).
- Served banner creatives cap at min(100%,728px), centered — kills the oversized
  sample banner; ad slots center their creative + label.
- Featured self-sell: shows "N of C slots open today" + "Feature your link →"
  that jumps to Campaigns with Featured preselected.
- Campaign target/image/video URL fields get autocomplete=off and clear when the
  Campaigns pane opens, so no residual (e.g. massifly) URL carries over.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-07 08:08:47 -05:00
martbost 4991fe96e8 Ad reporting + featured rotates one link + clear campaign form on submit
- Ad reporting (auto-approved ads need a safety valve): new reports.js store
  (dual-mode) + ad_reports table + POST /api/report-ad; a "⚠ report" control on
  served ad slots opens a reason prompt and notifies the admin by email
  (siteConfig.adminEmail / ADMIN_EMAIL).
- Featured links now show ONE link at a time and cycle (true rotation), instead
  of listing all links at once.
- Campaign form now clears EVERY field on submit (target/creative/title/etc.).
  A leftover target URL was carrying into the next campaign — the same reason a
  video short was saved with the wrong (massifly) CTA target.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-07 07:57:12 -05:00
martbost 85a6ac5bb0 Wallet: fix Trust Wallet chain-add + personal_sign ("invalid method parameters")
- wallet_addEthereumChain omits blockExplorerUrls when the config explorer is
  empty (rehearsal has none) — an empty-string URL made Trust Wallet reject the
  add with "invalid method parameters", blocking new users from adding the chain.
- personal_sign now hex-encodes the SIWE message (Trust Wallet requires hex;
  MetaMask took raw). Signed bytes are identical so server recovery is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-07 06:58:12 -05:00
martbost 23136f4ba0 Ornate achievement badges (Spark/Surge/Circuit/Nexus) — kie.ai mint-teal trophies + name overlay
- Named the milestone ladder: Spark (payouts) / Surge (first buyer) / Circuit (L2) / Nexus (L3)
- Overview badges strip now shows the ornate badge art (locked = dimmed); milestone stepper renamed
- Share button composites the badge template with the member's @username on the ribbon (JPEG, same-origin canvas)
- Badge art in public/badges/ (optimized JPG ~300KB each)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 14:11:44 -05:00
martbost 3c0e94f20f Badge emblems, profile social links, and SEO/OG social previews
- Achievement badge share-image now draws a milestone emblem (⚡🎯⭐🏆) in the medal
- Profile: Facebook/X/YouTube/Instagram/TikTok/Telegram/LinkedIn/Website links, shown on the public bio page
- OG + Twitter Card tags on homepage/ledger/contract (hero banner as share image)
- Per-member OG tags server-injected into /wall/<username> so shared bio links preview with name/bio/avatar
- robots.txt + sitemap.xml; .txt/.xml MIME types

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 12:21:53 -05:00
martbost b001df61b1 Homepage: all 7 ad formats live (add Video ads, flip Featured + Verified visits to live), refresh member benefits with earn-back, badges, bio page, messaging, banner kit
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 12:06:27 -05:00
martbost 5c99753f45 Banner kit: add crisp vector 320x50 mobile leaderboard (SVG) — full 7-size IAB set
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 10:21:27 -05:00
martbost 1912d2b251 Banner kit: add 468x60, 160x600, 120x600 (kie.ai) — 6 IAB sizes now in Promo tools
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 10:20:34 -05:00
martbost 6423d57f60 InstantAdPay banner kit (kie.ai): hero + leaderboard + rectangle in Promo tools
- 3 brand banners generated via kie.ai (mint-on-dark Web3 aesthetic), served from /banners/
- Promo tools Banners card now shows the kit with copy-image-URL

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 09:35:06 -05:00
martbost cb2542fca5 Verified visits (7th ad format): guaranteed unique human-visit packs
- Buy N verified visits flat up-front; each is a distinct member, dwell + captcha verified
- Verified visits earn sub-tab: open site (new tab), dwell, human-check, earn
- Per-viewer dedup (visit_seen unique), daily cap, completes at N; single-use tokens

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 09:21:59 -05:00
martbost f30a462ca8 Featured rotation -> day-slot booking: 10 slots/day, pick your start day, live occupancy
- Per-day occupancy shown in composer (Today 1/10, Tomorrow 2/10, …), full days unpickable
- Book a specific start day + duration; every covered day must have an open slot
- Slot cap turns dilution disclosure into a hard ceiling; featured skips frame-check (new-tab)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 09:16:24 -05:00
martbost b7e9fdf656 Wall view interaction: click banner, countdown, then a viewed checkmark (per-position, persisted)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 09:00:14 -05:00
martbost 37a2b97bfd Featured rotation format: duration-priced link rotation with disclosed dilution
- New 'featured' type: headline + link + 1/2/7 day run, flat up-front price (40cr/day)
- Composer discloses dilution (N links share the rotation, yours makes N+1) before buying
- Overview featured strip shows the live rotation; expires automatically

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 08:58:22 -05:00
martbost b25b4c67fe Buy more views: top up any campaign's budget, reactivates spent/paused ones (+NAS extend)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 08:53:35 -05:00
martbost 1aab52ca90 Profile build-out (avatar + bio) + shareable bio page with QR
- Profile pane: avatar upload + bio, with a link to your public page
- Wall becomes a bio page: avatar, bio, scannable join QR, line ladder, join CTA
- qrcode npm dep; /api/qr renders SVG QR server-side (CSP-clean img)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 08:49:20 -05:00
martbost 9e05711f4e Achievement badges + milestone credit bonuses
- Idempotent one-time credit bonus per milestone (payouts/firstBuyer/level2/level3): 10/25/50/100 cr
- Overview badges strip (unlockable medals) with canvas share-to-image (username overlaid)
- Newly-unlocked milestones toast the bonus on next dashboard load

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 08:43:50 -05:00
martbost 7701a29169 Sponsor to downline messaging: lineage view, daily broadcast (email+inbox), login modal
- Downline resolver (3 levels); email visible for directs only, username+ID deeper
- Broadcast composer (rich editor) to directs or full downline, 1/day cap, sends email + on-site inbox
- Upline messages inbox in My line; unmissable sign-in modal for unread, ack marks read
- messages.js dual-mode store; sponsor_messages table; sanitizeRich reused

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 08:39:06 -05:00
martbost 57bba0111a NAS syndication adapter (feature-flagged off): push banner/text to Network Ad Space, reconcile delivery into unified credit pool
- nas.js: direct-MySQL writer mirroring CTB's proven payments+sponsorads path (approved:1, pid 1/2, catid 5, remaining counts DOWN)
- Create-time push for banner/text; pause/resume mirrors to NAS deactivate/topUp
- reconcileNas() 5-min loop: reads served, charges delta credits to the shared budget, stops NAS ad when budget dry
- Campaign row shows IAP + '+N net' network views (differentiated stats)
- Inert unless NAS_DB_* env is set; zero prod impact until enabled
- Also: rename Inbox sub-tab to 'Inbox Ads'

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 08:11:32 -05:00
martbost 860aedabf6 Video ads (watch-to-earn): duration-tiered pricing, escape-proof player, per-view charge
- New 'video' campaign type; MP4/WebM upload or direct https link + required-watch tier (10/30/60s → 3/7/12 cr per view; viewer earns 1/2/4)
- Composer: video fields, tier dropdown, live price hint
- Earn credits > Watch videos sub-tab: no-seek player, server-clock watch floor, daily cap, self-exclusion, single-use tokens
- media-src CSP for direct-link/hosted video; video skips frame-check

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 08:03:01 -05:00
martbost 49508c2a13 Banner ads: required IAB size picker (width/height stored, shown in row, maps to NAS)
Also lands dormant server-side scaffolding for video ads (type, tiers, validation) — not yet exposed in UI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 07:51:28 -05:00
martbost b3be71135d Merge solo Inbox into Earn credits as a sub-tab; unread badge on Earn menu item
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 07:41:41 -05:00
martbost 1ee0b5626e Viral welcome tour + line banner + wall, milestone stepper, rich solo editor, CTA-gated reads
- Welcome tour (3 levels x 10s) unlocks welcome credits; line banner in Profile; public /wall/<username>
- 'Your next move' redesigned as a milestone stepper
- Solo composer: BV-style rich editor (H2/H3, inline image+video, undo/redo, raw text)
- Solo read reward now requires clicking through to the advertiser, not just dwelling
- Sanitizer: inline media whitelist + script/style stripped whole

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 07:30:49 -05:00
martbost 718d7f2d0e Built-in transaction viewer: every ledger row verifiable at /tx/<hash>, explorer link when configured
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-06 05:37:29 -05:00
martbost 1c31679b6c Login ads as post-signin interstitials: Open Ad in new tab, timer here, Go to Dashboard
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 16:28:57 -05:00
martbost f6a3befe09 Onsite solo ads: inbox delivery with read rewards, composer, homepage format live
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 15:25:00 -05:00
martbost fee86d296a Overview v3: plated stat cards, trend chips, payout bars, credit donut, view ring, delivery chart
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 06:41:01 -05:00
martbost e22021c266 Member identity, promo tools, back-office color, seeded inventory
Real people, not numbers: usernames (unique, profile pane to set them),
shown across the ledger, activity, rosters, and the sidebar chip; vanity
invite links (/join/<username>) with late chain binding intact. Promo tools
pane ships Branded Voice share posts and an email swipe personalized with
each member's link. The earn viewer excludes a member's own campaigns, so
nobody earns from their own spend. Back office gains the cyan/violet/amber
accent family over the green base. Three house campaigns seeded so every
surface shows live inventory. Assets v=20260905i.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 06:28:17 -05:00
martbost 28ed925443 View-fraud protection + real ad placement surfaces
Earning views now run on single-use server-issued tokens: the view only
counts when the full dwell elapses on the server clock; instant, forged,
replayed, and stale posts are all rejected, and the client countdown
pauses whenever the tab loses visibility or focus. New placements: login
ads on the sign-in screen (the per-day format's real home), a banner slot
in the back-office Overview, a text slot in the member sidebar, and a
member-ads banner on the homepage. Assets v=20260905g.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 06:15:27 -05:00
martbost 7331eac244 Back-office polish: Overview command center, quick actions, pane motion
Overview gains a recent-activity mini-feed (chain events + line joins) and
a quick-actions card jumping straight to buy/earn/campaigns plus one-tap
invite copy. Panes fade in (reduced-motion safe). First slice of the
back-office polish pass. Assets v=20260905f.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 06:09:37 -05:00
martbost a4c7028c0e Buy packages pane inside the member back office
Members buy directly from the dashboard: live-priced tiles in a dedicated
menu section, wallet flow with buy-time sponsor resolution, dashboard
refresh on settle. No more round-trip to the homepage. Assets v=20260905e.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 06:07:33 -05:00
martbost cdeb59ed7f Earn-and-spend credit economy + private rehearsal chain cutover
Members earn credits by attention (spec 8b): daily 5-ad set with dwell
timing and a too-fast guard, then a claimable daily batch. Earned credits
now FUND campaigns: banner/text budgets draw earned-first (free members can
advertise on welcome credits alone), purchased credits and the on-chain
burn queue only cover the remainder; earned-only campaigns pause when the
pool runs dry. New Earn credits section in the member menu with the viewer.
Explorer links degrade gracefully for the private chain (contract page
points at the audited Amoy verification). Site flipped to the anvil
rehearsal chain at rpc.instantadpay.com: unlimited test POL, no more
faucets. E2E: welcome->views->claim->earned-funded campaign->charged
serving, all green. Assets v=20260905d.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 05:59:42 -05:00
martbost d5bb74db7a Welcome credits (spec 8b earned pool v1) + official rehearsal rate card
Every account gets welcomeCredits (25, rate-card configurable) via an
idempotent lazy grant on dashboard load, so existing members receive theirs
retroactively. earned_credits table with JSON fallback; Overview stat shows
the purchased/welcome split. Chatbot facts and canned answers synced;
homepage free-membership list mentions the welcome batch. Rate card
promoted from placeholder to decided and persisted in the volume.
Spending integration for the earned pool is the next engine build.
Assets v=20260905b.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 05:48:42 -05:00
martbost 013a88b7d0 Fix: relay tx receipts through the server (CSP blocked direct RPC polls)
After a wallet sent a transaction, waitTx polled the public RPC straight
from the browser, which connect-src 'self' blocks (Firefox NetworkError,
reported by Marty on Activate; the activation itself landed on-chain).
New /api/tx/<hash> relays eth_getTransactionReceipt via the server's RPC
pool, so the browser only ever talks to us and the mainnet flip needs no
CSP changes. Assets v=20260905a.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-05 05:40:56 -05:00