Sync telesrv 4c0e2d9 (feat: complete official star gift lifecycle and admin tooling). Public adjustments: skipped private docs/deploy-nginx/README source changes, kept iamxvbaba/td public dependency, replaced local/private sample IP and orange seed label.
425 lines
21 KiB
PL/PgSQL
425 lines
21 KiB
PL/PgSQL
-- Complete collectible Star Gift lifecycle: ownership state, transfer/resale, purchase
|
|
-- offers, crafting, auctions, notification preferences and the explicit TON boundary.
|
|
|
|
ALTER TABLE public.peer_star_gifts
|
|
DROP CONSTRAINT IF EXISTS peer_star_gifts_terminal_state_check,
|
|
ADD COLUMN lifecycle_status text DEFAULT 'active' NOT NULL,
|
|
ADD COLUMN transfer_stars bigint DEFAULT 0 NOT NULL,
|
|
ADD COLUMN prepaid_upgrade_hash text DEFAULT '' NOT NULL,
|
|
ADD COLUMN gift_num integer DEFAULT 0 NOT NULL,
|
|
ADD COLUMN can_export_at integer DEFAULT 0 NOT NULL,
|
|
ADD COLUMN can_transfer_at integer DEFAULT 0 NOT NULL,
|
|
ADD COLUMN can_resell_at integer DEFAULT 0 NOT NULL,
|
|
ADD COLUMN drop_original_details_stars bigint DEFAULT 0 NOT NULL,
|
|
ADD COLUMN can_craft_at integer DEFAULT 0 NOT NULL;
|
|
|
|
UPDATE public.peer_star_gifts SET lifecycle_status='converted' WHERE converted;
|
|
|
|
ALTER TABLE public.peer_star_gifts
|
|
ADD CONSTRAINT peer_star_gifts_lifecycle_check CHECK (
|
|
lifecycle_status IN ('active', 'converted', 'burned', 'exported') AND
|
|
transfer_stars >= 0 AND gift_num >= 0 AND can_export_at >= 0 AND can_transfer_at >= 0 AND
|
|
can_resell_at >= 0 AND drop_original_details_stars >= 0 AND can_craft_at >= 0 AND
|
|
((lifecycle_status='converted' AND converted AND unique_gift_id IS NULL) OR
|
|
(lifecycle_status='active' AND NOT converted) OR
|
|
(lifecycle_status IN ('burned','exported') AND NOT converted AND unique_gift_id IS NOT NULL))
|
|
);
|
|
|
|
CREATE UNIQUE INDEX peer_star_gifts_prepaid_upgrade_hash_uniq
|
|
ON public.peer_star_gifts(prepaid_upgrade_hash) WHERE prepaid_upgrade_hash<>'';
|
|
|
|
ALTER TABLE public.unique_star_gifts
|
|
ALTER COLUMN owner_peer_type DROP NOT NULL,
|
|
ALTER COLUMN owner_peer_id DROP NOT NULL,
|
|
DROP CONSTRAINT IF EXISTS unique_star_gift_owner_check,
|
|
ADD COLUMN require_premium boolean DEFAULT false NOT NULL,
|
|
ADD COLUMN resale_ton_only boolean DEFAULT false NOT NULL,
|
|
ADD COLUMN theme_available boolean DEFAULT false NOT NULL,
|
|
ADD COLUMN burned boolean DEFAULT false NOT NULL,
|
|
ADD COLUMN crafted boolean DEFAULT false NOT NULL,
|
|
ADD COLUMN original_owner_peer_type text,
|
|
ADD COLUMN original_owner_peer_id bigint,
|
|
ADD COLUMN owner_name text DEFAULT '' NOT NULL,
|
|
ADD COLUMN owner_address text DEFAULT '' NOT NULL,
|
|
ADD COLUMN gift_address text DEFAULT '' NOT NULL,
|
|
ADD COLUMN released_by_peer_type text,
|
|
ADD COLUMN released_by_peer_id bigint,
|
|
ADD COLUMN value_amount bigint DEFAULT 0 NOT NULL,
|
|
ADD COLUMN value_currency text DEFAULT '' NOT NULL,
|
|
ADD COLUMN value_usd_amount bigint DEFAULT 0 NOT NULL,
|
|
ADD COLUMN theme_peer_type text,
|
|
ADD COLUMN theme_peer_id bigint,
|
|
ADD COLUMN host_peer_type text,
|
|
ADD COLUMN host_peer_id bigint,
|
|
ADD COLUMN offer_min_stars integer DEFAULT 0 NOT NULL,
|
|
ADD COLUMN craft_chance_permille integer DEFAULT 0 NOT NULL,
|
|
ADD COLUMN last_sale_date integer DEFAULT 0 NOT NULL,
|
|
ADD COLUMN last_sale_currency text DEFAULT '' NOT NULL,
|
|
ADD COLUMN last_sale_amount bigint DEFAULT 0 NOT NULL,
|
|
ADD CONSTRAINT unique_star_gift_owner_check CHECK (
|
|
(owner_peer_type IN ('user','channel') AND owner_peer_id > 0 AND owner_address='') OR
|
|
(owner_peer_type IS NULL AND owner_peer_id IS NULL AND owner_address<>'')
|
|
),
|
|
ADD CONSTRAINT unique_star_gift_released_by_check CHECK (
|
|
(released_by_peer_type IS NULL AND released_by_peer_id IS NULL) OR
|
|
(released_by_peer_type IN ('user','channel') AND released_by_peer_id > 0)
|
|
),
|
|
ADD CONSTRAINT unique_star_gift_theme_peer_check CHECK (
|
|
(theme_peer_type IS NULL AND theme_peer_id IS NULL) OR
|
|
(theme_peer_type IN ('user','channel') AND theme_peer_id > 0)
|
|
),
|
|
ADD CONSTRAINT unique_star_gift_host_peer_check CHECK (
|
|
(host_peer_type IS NULL AND host_peer_id IS NULL) OR
|
|
(host_peer_type IN ('user','channel') AND host_peer_id > 0)
|
|
),
|
|
ADD CONSTRAINT unique_star_gift_value_check CHECK (
|
|
value_amount >= 0 AND value_usd_amount >= 0 AND offer_min_stars >= 0 AND
|
|
craft_chance_permille BETWEEN 0 AND 1000 AND last_sale_date >= 0 AND last_sale_amount >= 0 AND
|
|
((value_currency='' AND value_amount=0) OR value_currency<>'') AND
|
|
((last_sale_currency='' AND last_sale_amount=0 AND last_sale_date=0) OR
|
|
(last_sale_currency IN ('XTR','TON') AND last_sale_amount>0 AND last_sale_date>0)) AND
|
|
(NOT burned OR owner_address='') AND
|
|
((owner_address='' AND gift_address='') OR (owner_address<>'' AND gift_address<>''))
|
|
);
|
|
|
|
UPDATE public.unique_star_gifts u
|
|
SET original_owner_peer_type=p.owner_peer_type, original_owner_peer_id=p.owner_peer_id
|
|
FROM public.peer_star_gifts p WHERE p.id=u.source_saved_gift_id;
|
|
|
|
ALTER TABLE public.unique_star_gifts
|
|
ALTER COLUMN original_owner_peer_type SET NOT NULL,
|
|
ALTER COLUMN original_owner_peer_id SET NOT NULL,
|
|
ADD CONSTRAINT unique_star_gift_original_owner_check CHECK (
|
|
original_owner_peer_type IN ('user','channel') AND original_owner_peer_id>0
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_listings (
|
|
unique_gift_id bigint PRIMARY KEY REFERENCES public.unique_star_gifts(id) ON DELETE RESTRICT,
|
|
seller_peer_type text NOT NULL,
|
|
seller_peer_id bigint NOT NULL,
|
|
currency text NOT NULL,
|
|
amount bigint NOT NULL,
|
|
listed_at integer NOT NULL,
|
|
updated_at integer NOT NULL,
|
|
version bigint DEFAULT 1 NOT NULL,
|
|
CONSTRAINT star_gift_listing_seller_check CHECK (seller_peer_type IN ('user','channel') AND seller_peer_id>0),
|
|
CONSTRAINT star_gift_listing_amount_check CHECK (currency IN ('XTR','TON') AND amount>0 AND listed_at>0 AND updated_at>=listed_at)
|
|
);
|
|
CREATE INDEX star_gift_listings_gift_price_idx ON public.star_gift_listings(currency, amount, unique_gift_id);
|
|
CREATE INDEX star_gift_listings_updated_idx ON public.star_gift_listings(updated_at DESC, unique_gift_id DESC);
|
|
|
|
CREATE TABLE public.star_gift_sales (
|
|
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
unique_gift_id bigint NOT NULL REFERENCES public.unique_star_gifts(id) ON DELETE RESTRICT,
|
|
seller_peer_type text NOT NULL,
|
|
seller_peer_id bigint NOT NULL,
|
|
buyer_peer_type text NOT NULL,
|
|
buyer_peer_id bigint NOT NULL,
|
|
currency text NOT NULL,
|
|
amount bigint NOT NULL,
|
|
commission_amount bigint DEFAULT 0 NOT NULL,
|
|
sold_at integer NOT NULL,
|
|
command_key text NOT NULL,
|
|
CONSTRAINT star_gift_sales_command_uniq UNIQUE(command_key),
|
|
CONSTRAINT star_gift_sales_peer_check CHECK (
|
|
seller_peer_type IN ('user','channel') AND seller_peer_id>0 AND
|
|
buyer_peer_type IN ('user','channel') AND buyer_peer_id>0),
|
|
CONSTRAINT star_gift_sales_amount_check CHECK (
|
|
currency IN ('XTR','TON') AND amount>0 AND commission_amount>=0 AND commission_amount<=amount AND sold_at>0)
|
|
);
|
|
CREATE INDEX star_gift_sales_unique_date_idx ON public.star_gift_sales(unique_gift_id, sold_at DESC);
|
|
|
|
CREATE TABLE public.star_gift_offers (
|
|
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
buyer_user_id bigint NOT NULL,
|
|
owner_peer_type text NOT NULL,
|
|
owner_peer_id bigint NOT NULL,
|
|
unique_gift_id bigint NOT NULL REFERENCES public.unique_star_gifts(id) ON DELETE RESTRICT,
|
|
currency text NOT NULL,
|
|
amount bigint NOT NULL,
|
|
random_id bigint NOT NULL,
|
|
offer_msg_id integer DEFAULT 0 NOT NULL,
|
|
buyer_msg_id integer DEFAULT 0 NOT NULL,
|
|
status text DEFAULT 'pending' NOT NULL,
|
|
created_at integer NOT NULL,
|
|
expires_at integer NOT NULL,
|
|
resolved_at integer DEFAULT 0 NOT NULL,
|
|
balance_after bigint DEFAULT 0 NOT NULL,
|
|
expiry_notified boolean DEFAULT false NOT NULL,
|
|
CONSTRAINT star_gift_offer_random_uniq UNIQUE(buyer_user_id, random_id),
|
|
CONSTRAINT star_gift_offer_owner_msg_uniq UNIQUE(owner_peer_type, owner_peer_id, offer_msg_id),
|
|
CONSTRAINT star_gift_offer_peer_check CHECK (buyer_user_id>0 AND owner_peer_type IN ('user','channel') AND owner_peer_id>0),
|
|
CONSTRAINT star_gift_offer_amount_check CHECK (currency IN ('XTR','TON') AND amount>0),
|
|
CONSTRAINT star_gift_offer_status_check CHECK (status IN ('pending','accepted','declined','expired','cancelled')),
|
|
CONSTRAINT star_gift_offer_time_check CHECK (created_at>0 AND expires_at>created_at AND resolved_at>=0 AND
|
|
((status='pending' AND resolved_at=0) OR (status<>'pending' AND resolved_at>=created_at)))
|
|
);
|
|
CREATE INDEX star_gift_offers_pending_expiry_idx ON public.star_gift_offers(expires_at, id) WHERE status='pending';
|
|
CREATE INDEX star_gift_offers_unique_pending_idx ON public.star_gift_offers(unique_gift_id, id) WHERE status='pending';
|
|
|
|
CREATE TABLE public.star_gift_transfer_commands (
|
|
actor_user_id bigint NOT NULL,
|
|
command_key text NOT NULL,
|
|
unique_gift_id bigint NOT NULL REFERENCES public.unique_star_gifts(id) ON DELETE RESTRICT,
|
|
from_peer_type text NOT NULL,
|
|
from_peer_id bigint NOT NULL,
|
|
to_peer_type text NOT NULL,
|
|
to_peer_id bigint NOT NULL,
|
|
charge_stars bigint DEFAULT 0 NOT NULL,
|
|
balance_after bigint DEFAULT 0 NOT NULL,
|
|
created_at integer NOT NULL,
|
|
CONSTRAINT star_gift_transfer_commands_pkey PRIMARY KEY(actor_user_id, command_key),
|
|
CONSTRAINT star_gift_transfer_command_peer_check CHECK (
|
|
actor_user_id>0 AND from_peer_type IN ('user','channel') AND from_peer_id>0 AND
|
|
to_peer_type IN ('user','channel') AND to_peer_id>0 AND charge_stars>=0 AND created_at>0)
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_purchase_commands (
|
|
buyer_user_id bigint NOT NULL,
|
|
command_key text NOT NULL,
|
|
gift_id bigint NOT NULL REFERENCES public.star_gift_catalog(gift_id) ON DELETE RESTRICT,
|
|
recipient_peer_type text NOT NULL,
|
|
recipient_peer_id bigint NOT NULL,
|
|
saved_gift_id bigint NOT NULL REFERENCES public.peer_star_gifts(id) ON DELETE RESTRICT,
|
|
form_id bigint NOT NULL,
|
|
charge_stars bigint NOT NULL,
|
|
balance_after bigint NOT NULL,
|
|
created_at integer NOT NULL,
|
|
CONSTRAINT star_gift_purchase_commands_pkey PRIMARY KEY(buyer_user_id,command_key),
|
|
CONSTRAINT star_gift_purchase_commands_form_uniq UNIQUE(buyer_user_id,form_id),
|
|
CONSTRAINT star_gift_purchase_command_shape_check CHECK (
|
|
buyer_user_id>0 AND recipient_peer_type IN ('user','channel') AND recipient_peer_id>0 AND
|
|
form_id>0 AND charge_stars>0 AND balance_after>=0 AND created_at>0)
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_prepaid_upgrade_commands (
|
|
payer_user_id bigint NOT NULL,
|
|
command_key text NOT NULL,
|
|
saved_gift_id bigint NOT NULL REFERENCES public.peer_star_gifts(id) ON DELETE RESTRICT,
|
|
form_id bigint NOT NULL,
|
|
charge_stars bigint NOT NULL,
|
|
balance_after bigint NOT NULL,
|
|
created_at integer NOT NULL,
|
|
CONSTRAINT star_gift_prepaid_upgrade_commands_pkey PRIMARY KEY(payer_user_id, command_key),
|
|
CONSTRAINT star_gift_prepaid_upgrade_commands_form_uniq UNIQUE(payer_user_id, form_id),
|
|
CONSTRAINT star_gift_prepaid_upgrade_command_shape_check CHECK (
|
|
payer_user_id>0 AND form_id>0 AND charge_stars>0 AND balance_after>=0 AND created_at>0)
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_drop_details_commands (
|
|
user_id bigint NOT NULL,
|
|
command_key text NOT NULL,
|
|
saved_gift_id bigint NOT NULL REFERENCES public.peer_star_gifts(id) ON DELETE RESTRICT,
|
|
unique_gift_id bigint NOT NULL REFERENCES public.unique_star_gifts(id) ON DELETE RESTRICT,
|
|
form_id bigint NOT NULL,
|
|
charge_stars bigint NOT NULL,
|
|
balance_after bigint NOT NULL,
|
|
created_at integer NOT NULL,
|
|
CONSTRAINT star_gift_drop_details_commands_pkey PRIMARY KEY(user_id, command_key),
|
|
CONSTRAINT star_gift_drop_details_commands_form_uniq UNIQUE(user_id, form_id),
|
|
CONSTRAINT star_gift_drop_details_command_shape_check CHECK (
|
|
user_id>0 AND form_id>0 AND charge_stars>0 AND balance_after>=0 AND created_at>0)
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_craft_commands (
|
|
user_id bigint NOT NULL,
|
|
command_key text NOT NULL,
|
|
input_unique_gift_ids bigint[] NOT NULL,
|
|
gift_id bigint NOT NULL REFERENCES public.star_gift_catalog(gift_id) ON DELETE RESTRICT,
|
|
success boolean NOT NULL,
|
|
result_unique_gift_id bigint REFERENCES public.unique_star_gifts(id) ON DELETE RESTRICT,
|
|
chance_permille integer NOT NULL,
|
|
created_at integer NOT NULL,
|
|
CONSTRAINT star_gift_craft_commands_pkey PRIMARY KEY(user_id, command_key),
|
|
CONSTRAINT star_gift_craft_shape_check CHECK (
|
|
user_id>0 AND cardinality(input_unique_gift_ids) BETWEEN 1 AND 4 AND
|
|
chance_permille BETWEEN 0 AND 1000 AND created_at>0 AND
|
|
((success AND result_unique_gift_id IS NOT NULL) OR (NOT success AND result_unique_gift_id IS NULL)))
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_notification_settings (
|
|
user_id bigint NOT NULL,
|
|
channel_id bigint NOT NULL,
|
|
enabled boolean DEFAULT true NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT star_gift_notification_settings_pkey PRIMARY KEY(user_id, channel_id),
|
|
CONSTRAINT star_gift_notification_settings_peer_check CHECK (user_id>0 AND channel_id>0)
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_withdrawal_requests (
|
|
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
unique_gift_id bigint NOT NULL REFERENCES public.unique_star_gifts(id) ON DELETE RESTRICT,
|
|
owner_user_id bigint NOT NULL,
|
|
provider text NOT NULL,
|
|
provider_request_id text NOT NULL,
|
|
url text NOT NULL,
|
|
status text DEFAULT 'pending' NOT NULL,
|
|
created_at integer NOT NULL,
|
|
expires_at integer NOT NULL,
|
|
completed_at integer DEFAULT 0 NOT NULL,
|
|
CONSTRAINT star_gift_withdrawal_request_unique UNIQUE(unique_gift_id),
|
|
CONSTRAINT star_gift_withdrawal_provider_request_uniq UNIQUE(provider, provider_request_id),
|
|
CONSTRAINT star_gift_withdrawal_shape_check CHECK (
|
|
owner_user_id>0 AND provider<>'' AND provider_request_id<>'' AND url<>'' AND
|
|
status IN ('pending','completed','failed') AND created_at>0 AND expires_at>created_at AND completed_at>=0)
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_auctions (
|
|
gift_id bigint PRIMARY KEY REFERENCES public.star_gift_catalog(gift_id) ON DELETE RESTRICT,
|
|
slug text NOT NULL UNIQUE,
|
|
version integer DEFAULT 1 NOT NULL,
|
|
start_date integer NOT NULL,
|
|
end_date integer NOT NULL,
|
|
round_duration integer NOT NULL,
|
|
gifts_per_round integer NOT NULL,
|
|
total_rounds integer NOT NULL,
|
|
current_round integer DEFAULT 0 NOT NULL,
|
|
next_round_at integer NOT NULL,
|
|
last_gift_num integer DEFAULT 0 NOT NULL,
|
|
gifts_left integer NOT NULL,
|
|
min_bid_amount bigint NOT NULL,
|
|
status text DEFAULT 'pending' NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT star_gift_auction_shape_check CHECK (
|
|
version>0 AND start_date>0 AND end_date>start_date AND round_duration>0 AND
|
|
gifts_per_round>0 AND total_rounds>0 AND current_round BETWEEN 0 AND total_rounds AND
|
|
next_round_at>=start_date AND last_gift_num>=0 AND gifts_left>=0 AND min_bid_amount>0 AND
|
|
status IN ('pending','active','completed','cancelled'))
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_auction_bids (
|
|
gift_id bigint NOT NULL REFERENCES public.star_gift_auctions(gift_id) ON DELETE RESTRICT,
|
|
bidder_user_id bigint NOT NULL,
|
|
recipient_peer_type text NOT NULL,
|
|
recipient_peer_id bigint NOT NULL,
|
|
amount bigint NOT NULL,
|
|
bid_date integer NOT NULL,
|
|
hide_name boolean DEFAULT false NOT NULL,
|
|
message text DEFAULT '' NOT NULL,
|
|
returned boolean DEFAULT false NOT NULL,
|
|
acquired_count integer DEFAULT 0 NOT NULL,
|
|
active boolean DEFAULT true NOT NULL,
|
|
version bigint DEFAULT 1 NOT NULL,
|
|
CONSTRAINT star_gift_auction_bids_pkey PRIMARY KEY(gift_id, bidder_user_id),
|
|
CONSTRAINT star_gift_auction_bid_peer_check CHECK (
|
|
bidder_user_id>0 AND recipient_peer_type IN ('user','channel') AND recipient_peer_id>0),
|
|
CONSTRAINT star_gift_auction_bid_amount_check CHECK (amount>0 AND bid_date>0 AND acquired_count>=0 AND version>0)
|
|
);
|
|
CREATE INDEX star_gift_auction_bids_rank_idx ON public.star_gift_auction_bids(gift_id, amount DESC, bid_date, bidder_user_id) WHERE active;
|
|
|
|
CREATE TABLE public.star_gift_auction_bid_payments (
|
|
user_id bigint NOT NULL,
|
|
form_id bigint NOT NULL,
|
|
gift_id bigint NOT NULL REFERENCES public.star_gift_auctions(gift_id) ON DELETE RESTRICT,
|
|
bid_amount bigint NOT NULL,
|
|
balance_after bigint NOT NULL,
|
|
created_at integer NOT NULL,
|
|
CONSTRAINT star_gift_auction_bid_payments_pkey PRIMARY KEY(user_id, form_id),
|
|
CONSTRAINT star_gift_auction_bid_payment_shape_check CHECK (
|
|
user_id>0 AND form_id>0 AND bid_amount>0 AND balance_after>=0 AND created_at>0)
|
|
);
|
|
|
|
CREATE TABLE public.star_gift_auction_acquired (
|
|
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
gift_id bigint NOT NULL REFERENCES public.star_gift_auctions(gift_id) ON DELETE RESTRICT,
|
|
bidder_user_id bigint NOT NULL,
|
|
recipient_peer_type text NOT NULL,
|
|
recipient_peer_id bigint NOT NULL,
|
|
saved_gift_id bigint REFERENCES public.peer_star_gifts(id) ON DELETE RESTRICT,
|
|
bid_amount bigint NOT NULL,
|
|
round integer NOT NULL,
|
|
pos integer NOT NULL,
|
|
gift_num integer,
|
|
acquired_at integer NOT NULL,
|
|
hide_name boolean DEFAULT false NOT NULL,
|
|
message text DEFAULT '' NOT NULL,
|
|
CONSTRAINT star_gift_auction_acquired_round_pos_uniq UNIQUE(gift_id, round, pos),
|
|
CONSTRAINT star_gift_auction_acquired_shape_check CHECK (
|
|
bidder_user_id>0 AND recipient_peer_type IN ('user','channel') AND recipient_peer_id>0 AND
|
|
bid_amount>0 AND round>0 AND pos>0 AND acquired_at>0 AND (gift_num IS NULL OR gift_num>0))
|
|
);
|
|
CREATE INDEX star_gift_auction_acquired_user_idx ON public.star_gift_auction_acquired(bidder_user_id, gift_id, id);
|
|
|
|
CREATE TABLE public.ton_balances (
|
|
user_id bigint PRIMARY KEY,
|
|
balance_nanoton bigint DEFAULT 0 NOT NULL,
|
|
granted boolean DEFAULT false NOT NULL,
|
|
updated_at timestamp with time zone DEFAULT now() NOT NULL,
|
|
CONSTRAINT ton_balances_check CHECK (user_id>0 AND balance_nanoton>=0)
|
|
);
|
|
|
|
CREATE TABLE public.ton_transactions (
|
|
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
|
user_id bigint NOT NULL,
|
|
amount_nanoton bigint NOT NULL,
|
|
reason text NOT NULL,
|
|
peer_type text,
|
|
peer_id bigint,
|
|
gift_id bigint,
|
|
date integer NOT NULL,
|
|
CONSTRAINT ton_transaction_amount_check CHECK (user_id>0 AND amount_nanoton<>0 AND date>0),
|
|
CONSTRAINT ton_transaction_peer_check CHECK (
|
|
(peer_type IS NULL AND peer_id IS NULL) OR (peer_type IN ('user','channel') AND peer_id>0))
|
|
);
|
|
CREATE INDEX ton_transactions_user_idx ON public.ton_transactions(user_id, id DESC);
|
|
|
|
CREATE FUNCTION public.telesrv_guard_star_gift_listing() RETURNS trigger LANGUAGE plpgsql AS $$
|
|
DECLARE
|
|
gift_owner_type text;
|
|
gift_owner_id bigint;
|
|
gift_burned boolean;
|
|
BEGIN
|
|
SELECT owner_peer_type, owner_peer_id, burned
|
|
INTO gift_owner_type, gift_owner_id, gift_burned
|
|
FROM public.unique_star_gifts WHERE id=NEW.unique_gift_id FOR SHARE;
|
|
IF gift_burned OR gift_owner_type IS DISTINCT FROM NEW.seller_peer_type OR gift_owner_id IS DISTINCT FROM NEW.seller_peer_id THEN
|
|
RAISE EXCEPTION 'star gift listing owner/state mismatch';
|
|
END IF;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
CREATE TRIGGER star_gift_listing_guard BEFORE INSERT OR UPDATE ON public.star_gift_listings
|
|
FOR EACH ROW EXECUTE FUNCTION public.telesrv_guard_star_gift_listing();
|
|
|
|
CREATE FUNCTION public.telesrv_check_unique_star_gift_owner() RETURNS trigger LANGUAGE plpgsql AS $$
|
|
DECLARE
|
|
unique_id bigint;
|
|
gift_owner_type text;
|
|
gift_owner_id bigint;
|
|
gift_owner_address text;
|
|
gift_burned boolean;
|
|
saved_status text;
|
|
saved_owner_type text;
|
|
saved_owner_id bigint;
|
|
BEGIN
|
|
IF TG_TABLE_NAME = 'unique_star_gifts' THEN
|
|
unique_id := COALESCE(NEW.id, OLD.id);
|
|
ELSE
|
|
unique_id := COALESCE(NEW.unique_gift_id, OLD.unique_gift_id);
|
|
END IF;
|
|
IF unique_id IS NULL THEN RETURN NULL; END IF;
|
|
SELECT owner_peer_type, owner_peer_id, owner_address, burned
|
|
INTO gift_owner_type, gift_owner_id, gift_owner_address, gift_burned
|
|
FROM public.unique_star_gifts WHERE id=unique_id;
|
|
IF NOT FOUND THEN RETURN NULL; END IF;
|
|
SELECT lifecycle_status, owner_peer_type, owner_peer_id
|
|
INTO saved_status, saved_owner_type, saved_owner_id
|
|
FROM public.peer_star_gifts WHERE unique_gift_id=unique_id;
|
|
IF NOT FOUND THEN RAISE EXCEPTION 'unique star gift missing saved aggregate'; END IF;
|
|
IF gift_burned THEN
|
|
IF saved_status <> 'burned' THEN RAISE EXCEPTION 'burned unique star gift has live saved aggregate'; END IF;
|
|
ELSIF gift_owner_address <> '' THEN
|
|
IF saved_status <> 'exported' THEN RAISE EXCEPTION 'exported unique star gift has non-exported saved aggregate'; END IF;
|
|
ELSIF saved_status <> 'active' OR gift_owner_type IS DISTINCT FROM saved_owner_type OR gift_owner_id IS DISTINCT FROM saved_owner_id THEN
|
|
RAISE EXCEPTION 'unique star gift owner mismatch';
|
|
END IF;
|
|
RETURN NULL;
|
|
END;
|
|
$$;
|
|
CREATE CONSTRAINT TRIGGER unique_star_gift_owner_guard
|
|
AFTER INSERT OR UPDATE ON public.unique_star_gifts DEFERRABLE INITIALLY DEFERRED
|
|
FOR EACH ROW EXECUTE FUNCTION public.telesrv_check_unique_star_gift_owner();
|
|
CREATE CONSTRAINT TRIGGER peer_unique_star_gift_owner_guard
|
|
AFTER INSERT OR UPDATE ON public.peer_star_gifts DEFERRABLE INITIALLY DEFERRED
|
|
FOR EACH ROW WHEN (NEW.unique_gift_id IS NOT NULL)
|
|
EXECUTE FUNCTION public.telesrv_check_unique_star_gift_owner();
|