-- PolyWeather trial and referral program. -- Run in Supabase SQL editor before enabling signup trials/referral checkout. create table if not exists public.trial_claims ( id bigserial primary key, user_id uuid not null references auth.users(id) on delete cascade, email text not null default '', telegram_user_id bigint, primary_wallet_address text, metadata jsonb not null default '{}'::jsonb, claimed_at timestamptz not null default now(), created_at timestamptz not null default now() ); create unique index if not exists uq_trial_claims_user on public.trial_claims(user_id); create unique index if not exists uq_trial_claims_email on public.trial_claims(lower(email)) where email <> ''; create unique index if not exists uq_trial_claims_telegram on public.trial_claims(telegram_user_id) where telegram_user_id is not null; create table if not exists public.trial_claim_wallets ( id bigserial primary key, trial_claim_id bigint not null references public.trial_claims(id) on delete cascade, wallet_address text not null, created_at timestamptz not null default now() ); create unique index if not exists uq_trial_claim_wallets_address on public.trial_claim_wallets(lower(wallet_address)); create table if not exists public.referral_codes ( id bigserial primary key, user_id uuid not null references auth.users(id) on delete cascade, code text not null, status text not null default 'active' check (status in ('active', 'revoked')), created_at timestamptz not null default now(), updated_at timestamptz not null default now() ); create unique index if not exists uq_referral_codes_user on public.referral_codes(user_id); create unique index if not exists uq_referral_codes_code on public.referral_codes(upper(code)); create table if not exists public.referral_attributions ( id bigserial primary key, referrer_user_id uuid not null references auth.users(id) on delete cascade, referred_user_id uuid not null references auth.users(id) on delete cascade, code text not null, status text not null default 'pending' check (status in ('pending', 'converted', 'capped', 'cancelled')), converted_payment_intent_id text, converted_tx_hash text, converted_at timestamptz, created_at timestamptz not null default now(), updated_at timestamptz not null default now(), check (referrer_user_id <> referred_user_id) ); create unique index if not exists uq_referral_attributions_referred on public.referral_attributions(referred_user_id); create index if not exists idx_referral_attributions_pending on public.referral_attributions(referred_user_id, created_at desc) include (id, code, referrer_user_id) where status = 'pending'; create table if not exists public.referral_rewards ( id bigserial primary key, referral_attribution_id bigint not null references public.referral_attributions(id) on delete cascade, referrer_user_id uuid not null references auth.users(id) on delete cascade, referred_user_id uuid not null references auth.users(id) on delete cascade, payment_intent_id text not null, tx_hash text, reward_days integer not null default 0 check (reward_days >= 0 and reward_days <= 30), reward_points integer not null default 0 check (reward_points >= 0 and reward_points <= 100000), created_at timestamptz not null default now() ); create unique index if not exists uq_referral_rewards_attribution on public.referral_rewards(referral_attribution_id); create index if not exists idx_referral_rewards_referrer_month on public.referral_rewards(referrer_user_id, created_at desc) include (id, reward_days, reward_points); analyze public.trial_claims; analyze public.trial_claim_wallets; analyze public.referral_codes; analyze public.referral_attributions; analyze public.referral_rewards;