Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions supabase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Supabase Schema & Data Loading

This directory captures the Postgres schema that powers the Telcoin Wiki FAQ and status surfaces. Contributors can run the SQL migrations and seeds directly via `psql`, the Supabase SQL editor, or the Supabase CLI.

## Structure

- `migrations/20240611120000_create_faq_and_status_schema.sql` – creates the FAQ, tag, source, and status metric tables along with supporting indexes and search configuration.
- `seeds/20240611121000_seed_faq_and_status.sql` – idempotently loads FAQ content, tag mappings, source links, and the initial status metric from the existing JSON assets.

## Applying the schema

```bash
# Using the Supabase CLI
supabase db reset # Drops and recreates the local database, then runs migrations + seeds
# or, to apply to an existing database
supabase db push # Applies the SQL in migrations/ to your linked project
psql "$SUPABASE_DB_URL" -f supabase/seeds/20240611121000_seed_faq_and_status.sql
```

The seed script is safe to rerun; it performs UPSERT operations so repeated executions keep the database in sync with the JSON source files.

## Status metrics lifecycle

The `status_metrics` table mirrors keys from `status.json` (for example, `remittanceCorridors`). Each row records:

- `value` – stored as a numeric type so both integers and decimals are supported.
- `unit` – optional human-readable unit (e.g., `countries`).
- `update_strategy` – constrained to `manual` or `automated`. For now, metrics are maintained manually by updating rows through Supabase or a SQL client. When an automated feed becomes available, switch the column to `automated` and point a cron job or background worker at the table.
- `notes` – provenance for the seeded values.

Consumers can query `status_metrics` directly or create lightweight views/materialized views if additional formatting is required for the React application.

## Full-text search

FAQ rows maintain a generated `search_vector` that indexes both the question and HTML answer. The migration adds a GIN index over this vector so Supabase can satisfy typeahead or keyword search workloads without additional configuration.

## Referential integrity

Tags are normalized in `faq_tag_labels` (unique slug + label) and joined to FAQ entries via the `faq_tags` bridge table. Source links live in `faq_sources` with a `UNIQUE (faq_id, url)` constraint to prevent accidental duplication.

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
begin;

create table if not exists public.faq (
id text primary key,
question text not null,
answer_html text not null,
display_order integer not null,
created_at timestamptz not null default now(),
updated_at timestamptz not null default now(),
search_vector tsvector generated always as (
to_tsvector('english', coalesce(question, '') || ' ' || coalesce(answer_html, ''))
) stored
);

create index if not exists idx_faq_display_order on public.faq(display_order);
create index if not exists idx_faq_search_vector on public.faq using gin(search_vector);

create table if not exists public.faq_tag_labels (
id bigserial primary key,
slug text not null unique,
label text not null unique,
created_at timestamptz not null default now()
);

create table if not exists public.faq_tags (
faq_id text not null references public.faq(id) on delete cascade,
tag_id bigint not null references public.faq_tag_labels(id) on delete cascade,
primary key (faq_id, tag_id)
);

create index if not exists idx_faq_tags_tag_id on public.faq_tags(tag_id);
create index if not exists idx_faq_tags_faq_id on public.faq_tags(faq_id);

create table if not exists public.faq_sources (
id bigserial primary key,
faq_id text not null references public.faq(id) on delete cascade,
label text not null,
url text not null,
created_at timestamptz not null default now(),
unique (faq_id, url)
);

create index if not exists idx_faq_sources_faq_id on public.faq_sources(faq_id);
create index if not exists idx_faq_sources_url on public.faq_sources(url);

create table if not exists public.status_metrics (
key text primary key,
label text not null,
value numeric not null,
unit text,
notes text,
update_strategy text not null default 'manual' check (update_strategy in ('manual', 'automated')),
updated_at timestamptz not null default now()
);

create index if not exists idx_status_metrics_update_strategy on public.status_metrics(update_strategy);

commit;
91 changes: 91 additions & 0 deletions supabase/seeds/20240611121000_seed_faq_and_status.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
begin;

insert into public.faq (id, question, answer_html, display_order)
values
('what-is-telcoin', 'What is Telcoin in one paragraph?', '<p>Telcoin pairs a global mobile-first financial app with the Telcoin Network, a carrier-secured EVM chain governed by the Telcoin Association. The ecosystem is designed to let users send money, hold digital cash, and interact with compliant DeFi services using their own smartphones.</p>', 1),
('what-is-the-telcoin-wallet', 'What is the Telcoin Wallet and what can it do?', '<p>The Telcoin Wallet is the official mobile app that lets verified users buy, sell, and store TEL alongside multi-currency digital cash. It provides direct access to Telcoin remittances, in-app swaps, and a secure account recovery path tied to your device and credentials.</p>', 2),
('where-can-i-send-remittances', 'Where can I send remittances today?', '<p>Telcoin currently supports remittance corridors across <span data-status-key="remittanceCorridors" data-status-format="plus">20+</span> countries, focusing on fast and low-cost mobile money payouts. Live corridor availability and fees are listed inside the Telcoin Wallet and on the official remittance corridors page.</p>', 3),
('what-is-digital-cash', 'What is Digital Cash?', '<p>Digital Cash is Telcoin’s multi-currency stablecoin suite, offering fiat-backed assets such as eUSD, eCAD, and ePHP that settle instantly on the Telcoin Network. These currencies are spendable in the Telcoin Wallet and integrate with remittances, merchant payouts, and TELx liquidity.</p>', 4),
('what-is-the-telcoin-network', 'What is the Telcoin Network?', '<p>The Telcoin Network is an EVM-compatible, proof-of-stake blockchain secured by mobile network operators who meet GSMA standards. It underpins Telcoin services and hosts smart contracts for digital cash, TEL staking, and TELx liquidity while remaining governed by the Telcoin Association.</p>', 5),
('what-is-tel', 'What is TEL (the token) used for?', '<p>TEL is the native asset of the Telcoin Network. It functions as network gas, powers staking and governance incentives, and serves as the unit of account for TELx liquidity programs that reward users who deepen ecosystem liquidity.</p>', 6),
('what-is-telx', 'What is TELx?', '<p>TELx is Telcoin’s liquidity layer that connects the Telcoin Wallet, Network, and partner DeFi protocols. It lets users supply TEL and digital cash to earn rewards, driving the regulated liquidity that powers in-app swaps and remittance throughput.</p>', 7),
('who-is-the-telcoin-association', 'Who is the Telcoin Association and what do they do?', '<p>The Telcoin Association is a Swiss Verein responsible for Telcoin Network governance, validator onboarding, and the issuance policies for TEL and Digital Cash. The Association stewards proposals, security reviews, and compliance frameworks in collaboration with community councils.</p>', 8),
('is-telcoin-compliant', 'Is Telcoin compliant?', '<p>Telcoin Holdings reports SOC 2 Type II attestation progress and operates a regulated digital asset bank in Nebraska, while the Association maintains governance that aligns with telecom and financial regulations. Legal resources and security updates are published on the official site.</p>', 9),
('where-to-find-updates', 'Where can I find official updates?', '<p>Official announcements ship through the Telcoin Newsroom, the Telcoin Status page, and verified social channels such as X (Twitter). You can also follow product updates directly inside the Telcoin Wallet for release notes and maintenance alerts.</p>', 10)
on conflict (id) do update set
question = excluded.question,
answer_html = excluded.answer_html,
display_order = excluded.display_order,
updated_at = now();

insert into public.faq_tag_labels (slug, label)
values
('getting-started', 'Getting Started'),
('network', 'Network'),
('wallet', 'Wallet'),
('remittances', 'Remittances'),
('digital-cash', 'Digital Cash'),
('governance', 'Governance'),
('tel-token', 'TEL Token'),
('defi-telx', 'DeFi/TELx'),
('compliance-security', 'Compliance & Security')
on conflict (slug) do update set
label = excluded.label;

insert into public.faq_tags (faq_id, tag_id)
values
('what-is-telcoin', (select id from public.faq_tag_labels where slug = 'getting-started')),
('what-is-telcoin', (select id from public.faq_tag_labels where slug = 'network')),
('what-is-the-telcoin-wallet', (select id from public.faq_tag_labels where slug = 'wallet')),
('what-is-the-telcoin-wallet', (select id from public.faq_tag_labels where slug = 'getting-started')),
('where-can-i-send-remittances', (select id from public.faq_tag_labels where slug = 'remittances')),
('where-can-i-send-remittances', (select id from public.faq_tag_labels where slug = 'wallet')),
('what-is-digital-cash', (select id from public.faq_tag_labels where slug = 'digital-cash')),
('what-is-digital-cash', (select id from public.faq_tag_labels where slug = 'wallet')),
('what-is-the-telcoin-network', (select id from public.faq_tag_labels where slug = 'network')),
('what-is-the-telcoin-network', (select id from public.faq_tag_labels where slug = 'governance')),
('what-is-tel', (select id from public.faq_tag_labels where slug = 'tel-token')),
('what-is-tel', (select id from public.faq_tag_labels where slug = 'network')),
('what-is-telx', (select id from public.faq_tag_labels where slug = 'defi-telx')),
('what-is-telx', (select id from public.faq_tag_labels where slug = 'tel-token')),
('who-is-the-telcoin-association', (select id from public.faq_tag_labels where slug = 'governance')),
('who-is-the-telcoin-association', (select id from public.faq_tag_labels where slug = 'compliance-security')),
('is-telcoin-compliant', (select id from public.faq_tag_labels where slug = 'compliance-security')),
('is-telcoin-compliant', (select id from public.faq_tag_labels where slug = 'getting-started')),
('where-to-find-updates', (select id from public.faq_tag_labels where slug = 'getting-started')),
('where-to-find-updates', (select id from public.faq_tag_labels where slug = 'governance'))
on conflict do nothing;

insert into public.faq_sources (faq_id, label, url)
values
('what-is-telcoin', 'Telcoin overview', 'https://telco.in/'),
('what-is-telcoin', 'Telcoin Association overview', 'https://www.telcoinassociation.org'),
('what-is-the-telcoin-wallet', 'Telcoin Wallet', 'https://telco.in/wallet'),
('where-can-i-send-remittances', 'Remittance corridors', 'https://telco.in/remittances'),
('what-is-digital-cash', 'Digital Cash overview', 'https://telco.in/digital-cash'),
('what-is-the-telcoin-network', 'Telcoin Network', 'https://www.telcoinassociation.org/network'),
('what-is-the-telcoin-network', 'Telcoin Network overview', 'https://www.telcoinnetwork.org'),
('what-is-tel', 'TEL token overview', 'https://www.telcoinassociation.org/tel'),
('what-is-telx', 'TELx overview', 'https://www.telcoinassociation.org/telx'),
('what-is-telx', 'TELx pools', 'https://www.telx.network/pools'),
('who-is-the-telcoin-association', 'Telcoin Association', 'https://www.telcoinassociation.org'),
('is-telcoin-compliant', 'Security & compliance updates', 'https://telco.in/newsroom/security'),
('is-telcoin-compliant', 'Legal resources', 'https://telco.in/legal'),
('where-to-find-updates', 'Telcoin Newsroom', 'https://telco.in/newsroom'),
('where-to-find-updates', 'Status page', 'https://status.telco.in'),
('where-to-find-updates', 'Telcoin on X', 'https://x.com/telcoin')
on conflict (faq_id, url) do update set
label = excluded.label;

insert into public.status_metrics (key, label, value, unit, update_strategy, notes)
values
('remittanceCorridors', 'Remittance corridors', 20, 'countries', 'manual', 'Seeded from status.json on static site')
on conflict (key) do update set
label = excluded.label,
value = excluded.value,
unit = excluded.unit,
update_strategy = excluded.update_strategy,
notes = excluded.notes,
updated_at = now();

commit;