feat(indexer): index pair_creation fees on /api/v1/protocol/fees (no instantiate-gas double-count) #1209

Closed
opened 2026-09-06 12:05:06 +00:00 by ops-worker · 6 comments
Member

Summary

Index factory pair-creation treasury uluna on GET /api/v1/protocol/fees as FeeSource::PairCreation / pair_creation. The on-chain fee already exists. The indexer has seven sources and no create_pair parser.

Do not count CosmWasm instantiate gas (validator fee, not treasury revenue). Do not mix SKU/settings invoices (#1210) or cohort split (#1211). Design/home: #1213.

Closed marketing tracker: cl8y-marketing#1. Do not reopen it. Do not implement fee truth in marketing.

Given / When / Then

Given a successful factory CreatePair on the pinned FACTORY_ADDRESS with creation_fee_uluna > 0
When the indexer ingests that tx
Then it inserts one protocol_fee_events row (source=pair_creation, amount = the wasm attr)
And instantiate gas, overpay refunds, and reply_instantiate_pair are not fee rows
And GET /api/v1/protocol/fees exposes pair_creation with the same idle/unpriced/window semantics as wrap/window

Not a duplicate / already implemented

Issue Why it is not this ticket
#1213 (closed) Design/home map only. Adds no FeeSource.
#1210 Community SKU/settings UST1 invoices. Different pin, asset, attrs. Stack after this pattern; do not mix sources.
#1211 Actor + retail/MM/unjoined split. Include pair_creation once this source exists.
#586 / #614 Existing seven-source census / UST1 window. Pattern to copy, not this parser.
#276 On-chain pair_creation_fee_uluna (already shipped).
#1204 OpenAPI/curl pack. No ingest.
#1202 Client analytics. Not fee truth.

Not implemented: FeeSource::ALL is length 7. indexer/src/indexer/ has no create_pair / creation_fee_uluna parser. Pair discovery is not treasury census.


Current codebase

On-chain (already correct)

Factory execute_create_pair:

  • Reads config.pair_creation_fee_uluna (default 100_000_000 uluna).
  • Requires attached uluna ≥ fee; rejects stray denoms; refunds overpay to sender.
  • BankMsg::Send fee → config.treasury.
  • Same tx instantiates the pair (SubMsg::reply_on_success). Instantiate failure reverts the fee.
  • Wasm attrs: action=create_pair, pair=…, creation_fee_uluna=<fee>.
  • Reply attrs: action=reply_instantiate_pair (registration only — not a fee).

Gas for instantiate is a separate Cosmos tx fee.

Indexer ingest (seven sources)

FeeSource is swap_amm, book_take, limit_place, wrap, unwrap, ust1_mint, ust1_redeem. Wrap/UST1 require pinned addresses and explicit positive fee attrs (fail closed). ingest_protocol_fee drops amount_raw <= 0. Rows land in protocol_fee_events with UNIQUE (tx_hash, source, ordinal) and ON CONFLICT DO NOTHING. fee_usd stamped at ingest. GET is O(1) rollup / 60s cache — no live SUM.

FACTORY_ADDRESS is required in every RUN_MODE (#451). There is no wrap-style “factory unset” omit path; pin is the existing factory env.

pair_discovery.rs finds pairs via instantiate / factory registry. Audit item 11 still states there is no pair-creation fee parser.

CHECK constraints (20260824120000_ust1_window_protocol_fees.sql) and DeFiLlama daily fields match the seven keys.

Frontend

ProtocolFeeSourceKey and ProtocolFeeStats.tsx SOURCE_LABEL / SOURCE_ORDER have no pair_creation.


Why the new implementation is needed

/protocol and DeFiLlama cannot report project-team pair-creation revenue. Offline LCD reconciliation of factory→treasury uluna is acceptable only as a labeled provisional stopgap. A second fee service in marketing would fork economic truth.

The UST1 window (#614) is the pattern: new FeeSource, pinned contract, explicit amount attr, rollups, Defillama, UI label, verify target.


Constraints / guardrails

  • Count only treasury uluna. Canonical amount is positive creation_fee_uluna. Optional same-tx cross-check vs factory→treasury uluna BankMsg. Ignore instantiate gas, fee-payer burn, sender refunds, and reply_instantiate_pair.
  • One row per create. Do not double-count bank send + attr. Attr wins; mismatch logs a bounded signal and still fail-closed (no second row).
  • Fail closed on amount. amount_raw > 0 required. Zero-fee creates: no fee row. Do not infer config.pair_creation_fee_uluna × create count (fee can change mid-window).
  • Pin factory (#285). Accept wasm only when reserved _contract_address equals pinned FACTORY_ADDRESS. Ignore spoof create_pair and unreserved contract_address (no underscore).
  • Price via uluna catalog identity (PFee / H-series), not free-text symbol. Unpriced: store event, fee_usd NULL; activity + all unpriced → API null.
  • GET stays O(1) rollup / 60s cache. window= remains 24h|7d|30d. Additive JSON.
  • Out of scope: SKU/settings invoices (#1210), cohort (#1211), client analytics (#1202), OpenAPI pack (#1204), changing on-chain fee amount, marketing Postgres.
  • Do not expand this MR into #1210 / #1211.

Relevant files

Path Why
indexer/src/indexer/protocol_fees.rs FeeSource enum / wrap-window parse pattern
indexer/src/indexer/parser.rs ingest_protocol_fee wiring
indexer/src/db/queries/protocol_fees.rs Insert / rollup
indexer/migrations/20260824120000_ust1_window_protocol_fees.sql CHECK widen pattern
indexer/src/api/protocol_fees.rs, protocol_fee_series.rs, api/defillama.rs Public ledger
indexer/tests/indexer_protocol_fees.rs, indexer_protocol_fees_series.rs, indexer_defillama.rs Existing source tests
frontend-dapp/src/types/index.ts ProtocolFeeSourceKey
frontend-dapp/src/components/protocol/ProtocolFeeStats.tsx Labels / hide-idle
smartcontracts/contracts/factory/src/contract.rs creation_fee_uluna (read-only)
docs/indexer-invariants.md, docs/audits/factory-treasury-bank-send.md Item 11 until this ships
skills/AGENTS_INDEXER_UST1_WINDOW_FEES.md, AGENTS_INDEXER_WRAP_FEE_INGEST.md, AGENTS_INDEXER_FEE_LEDGER_HOME.md Pattern / home map

  1. Add FeeSource::PairCreation / pair_creation. Copy wrap/window: per-action scan, reserved _contract_address, fail-closed positive amount.
  2. Parse pinned factory + action=create_pair + positive creation_fee_uluna. Asset = native uluna. Stamp fee_usd from LUNC catalog.
  3. Optional same-tx equality assert vs treasury uluna send. Attr wins; no second row.
  4. Widen CHECKs, FeeSource::ALL, rollups, Defillama additive field, frontend key + label Pair creation.
  5. make verify-issue-1209 (or equivalent) bundled like #614. Playbook skill optional.
  6. Historical backfill only if needed for Phase 0 baseline: idempotent on (tx_hash, source, ordinal); must not count gas.
  7. After ship: marketing snapshots may note the eighth stream; provisional LCD stopgap marked retired.

Reject: counting gas; inferring fee from config × count; mixing invoices into this source.


Acceptance criteria

  • AC1. FeeSource includes pair_creation; CHECK constraints, rollups, Defillama, and UI labels updated.
  • AC2. Positive creation_fee_uluna on pinned factory create_pair inserts exactly one protocol_fee_events row; tx_hash is the create tx.
  • AC3. Instantiate gas, refunds, and reply_instantiate_pair are not ingested as fees.
  • AC4. Zero-fee creates produce no fee row. Spoof / unreserved emitter ignored (#285).
  • AC5. GET /api/v1/protocol/fees and /daily expose pair_creation with idle "0" / unpriced null / window allowlist unchanged (invalid window still 400).
  • AC6. Frontend protocol stats shows Pair creation when event_count > 0. Unknown source strings are not interpolated into JS.
  • AC7. Replay/reorg uniqueness prevents double insert. SKU invoices and S1 client events unchanged.
  • AC8. docs/indexer-invariants.md and factory-treasury audit item 11 updated (parser now exists).

Test plan (functional paths)

# Path Expect
T1 Exact fee create Row amount = creation_fee_uluna; USD stamped or NULL per LUNC catalog
T2 Overpay Fee row = fee, not attached uluna (refund excluded)
T3 Underpay / stray denom No pair, no fee row
T4 Zero fee Pair may exist; no pair_creation row
T5 Instantiate failure Chain reverts fee; no success row
T6 Flattened wasm Factory segment scoped by reserved _contract_address only
T7 Bank vs attr mismatch No double row; fail-closed documented
T8 Fee config change Later creates use emitted attr, not old config × count
T9 API window=24h|7d|30d; bad window 400 by_source includes pair_creation; additive JSON
T10 Idle vs unpriced Same "0" / null rules as wrap/UST1
T11 Defillama + overview New field; old clients ignore unknown keys
T12 Frontend label; unknown source string Safe render
T13 Backfill (if any) Idempotent; gas not counted
T14 Regression make verify-issue-586 / make verify-issue-614 still green

Test plan (attack, hack, and abuse)

# Vector Expect
A1 Spoof wasm action=create_pair from non-factory contract Ignored unless reserved _contract_address = pinned factory
A2 Unreserved contract_address (no underscore) Ignored (#285)
A3 Count gas / full user uluna outflows as fee Rejected
A4 Double-count bank send + attr Single row
A5 Count refund uluna as fee Refund is to sender; not ingested
A6 Count reply_instantiate_pair Not a fee
A7 Replay / reorg double insert (tx_hash, source, ordinal) uniqueness
A8 Infer fee from config × create count Forbidden
A9 Symbol spoof / wrong USD Price via uluna catalog identity
A10 Mix SKU UST1 or swap commission into this source Forbidden
A11 Client analytics as fee truth Out of scope (#1202)
A12 Over-long / non-numeric creation_fee_uluna Parse fail; no panic; no row

Verification criteria

  • Indexer fixtures: positive fee, zero fee, spoof contract, refund, gas-only, flattened wasm.
  • API tests: by_source contains pair_creation with correct event_count / amount_usd semantics.
  • Frontend type/label tests include the new key.
  • Existing protocol-fee, series, and Defillama tests pass.
  • A captured or LocalTerra create_pair txhash matches protocol_fee_events (source=pair_creation) and does not include gas as amount.
  • make verify-issue-1209 (or the issue verify target named in the PR) plus make verify-issue-586 / make verify-issue-614.
## Summary Index factory **pair-creation treasury uluna** on `GET /api/v1/protocol/fees` as `FeeSource::PairCreation` / `pair_creation`. The on-chain fee already exists. The indexer has **seven** sources and no `create_pair` parser. Do **not** count CosmWasm instantiate gas (validator fee, not treasury revenue). Do **not** mix SKU/settings invoices ([#1210](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1210)) or cohort split ([#1211](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1211)). Design/home: [#1213](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1213). Closed marketing tracker: [cl8y-marketing#1](https://git.cl8y.com/PlasticDigits/cl8y-marketing/issues/1). Do not reopen it. Do not implement fee truth in marketing. ### Given / When / Then Given a successful factory `CreatePair` on the pinned `FACTORY_ADDRESS` with `creation_fee_uluna` > 0 When the indexer ingests that tx Then it inserts **one** `protocol_fee_events` row (`source=pair_creation`, amount = the wasm attr) And instantiate gas, overpay refunds, and `reply_instantiate_pair` are not fee rows And `GET /api/v1/protocol/fees` exposes `pair_creation` with the same idle/unpriced/`window` semantics as wrap/window ### Not a duplicate / already implemented | Issue | Why it is not this ticket | | --- | --- | | [#1213](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1213) (closed) | Design/home map only. Adds **no** `FeeSource`. | | [#1210](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1210) | Community SKU/settings **UST1** invoices. Different pin, asset, attrs. Stack after this pattern; do not mix sources. | | [#1211](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1211) | Actor + retail/MM/unjoined split. Include `pair_creation` once this source exists. | | [#586](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/586) / [#614](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/614) | Existing seven-source census / UST1 window. Pattern to copy, not this parser. | | [#276](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/276) | On-chain `pair_creation_fee_uluna` (already shipped). | | [#1204](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1204) | OpenAPI/curl pack. No ingest. | | [#1202](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/1202) | Client analytics. Not fee truth. | **Not implemented:** `FeeSource::ALL` is length **7**. `indexer/src/indexer/` has **no** `create_pair` / `creation_fee_uluna` parser. Pair discovery is not treasury census. --- ## Current codebase ### On-chain (already correct) Factory [`execute_create_pair`](smartcontracts/contracts/factory/src/contract.rs): - Reads `config.pair_creation_fee_uluna` (default `100_000_000` uluna). - Requires attached **uluna** ≥ fee; rejects stray denoms; refunds overpay to sender. - `BankMsg::Send` fee → `config.treasury`. - Same tx instantiates the pair (`SubMsg::reply_on_success`). Instantiate failure reverts the fee. - Wasm attrs: `action=create_pair`, `pair=…`, `creation_fee_uluna=<fee>`. - Reply attrs: `action=reply_instantiate_pair` (registration only — **not** a fee). Gas for instantiate is a separate Cosmos tx fee. ### Indexer ingest (seven sources) [`FeeSource`](indexer/src/indexer/protocol_fees.rs) is `swap_amm`, `book_take`, `limit_place`, `wrap`, `unwrap`, `ust1_mint`, `ust1_redeem`. Wrap/UST1 require pinned addresses and explicit positive fee attrs (fail closed). [`ingest_protocol_fee`](indexer/src/indexer/parser.rs) drops `amount_raw <= 0`. Rows land in `protocol_fee_events` with `UNIQUE (tx_hash, source, ordinal)` and `ON CONFLICT DO NOTHING`. `fee_usd` stamped at ingest. GET is O(1) rollup / 60s cache — **no** live `SUM`. `FACTORY_ADDRESS` is **required** in every `RUN_MODE` ([#451](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/451)). There is no wrap-style “factory unset” omit path; pin is the existing factory env. [`pair_discovery.rs`](indexer/src/indexer/pair_discovery.rs) finds pairs via instantiate / factory registry. Audit [item 11](docs/audits/factory-treasury-bank-send.md) still states there is **no** pair-creation **fee** parser. CHECK constraints ([`20260824120000_ust1_window_protocol_fees.sql`](indexer/migrations/20260824120000_ust1_window_protocol_fees.sql)) and DeFiLlama daily fields match the seven keys. ### Frontend [`ProtocolFeeSourceKey`](frontend-dapp/src/types/index.ts) and [`ProtocolFeeStats.tsx`](frontend-dapp/src/components/protocol/ProtocolFeeStats.tsx) `SOURCE_LABEL` / `SOURCE_ORDER` have no `pair_creation`. --- ## Why the new implementation is needed `/protocol` and DeFiLlama cannot report project-team pair-creation revenue. Offline LCD reconciliation of factory→treasury uluna is acceptable only as a labeled **provisional** stopgap. A second fee service in marketing would fork economic truth. The UST1 window ([#614](https://git.cl8y.com/code/cl8y-dex-terraclassic/issues/614)) is the pattern: new `FeeSource`, pinned contract, explicit amount attr, rollups, Defillama, UI label, verify target. --- ## Constraints / guardrails - **Count only treasury uluna.** Canonical amount is positive `creation_fee_uluna`. Optional same-tx cross-check vs factory→treasury uluna `BankMsg`. Ignore instantiate gas, fee-payer burn, sender refunds, and `reply_instantiate_pair`. - **One row per create.** Do not double-count bank send + attr. Attr wins; mismatch logs a bounded signal and still fail-closed (no second row). - **Fail closed on amount.** `amount_raw > 0` required. Zero-fee creates: no fee row. Do not infer `config.pair_creation_fee_uluna × create count` (fee can change mid-window). - **Pin factory (#285).** Accept wasm only when reserved `_contract_address` equals pinned `FACTORY_ADDRESS`. Ignore spoof `create_pair` and unreserved `contract_address` (no underscore). - **Price via `uluna` catalog identity** (PFee / H-series), not free-text symbol. Unpriced: store event, `fee_usd` NULL; activity + all unpriced → API `null`. - **GET stays O(1) rollup / 60s cache.** `window=` remains `24h|7d|30d`. Additive JSON. - **Out of scope:** SKU/settings invoices (#1210), cohort (#1211), client analytics (#1202), OpenAPI pack (#1204), changing on-chain fee amount, marketing Postgres. - **Do not expand this MR** into #1210 / #1211. --- ## Relevant files | Path | Why | | --- | --- | | `indexer/src/indexer/protocol_fees.rs` | `FeeSource` enum / wrap-window parse pattern | | `indexer/src/indexer/parser.rs` | `ingest_protocol_fee` wiring | | `indexer/src/db/queries/protocol_fees.rs` | Insert / rollup | | `indexer/migrations/20260824120000_ust1_window_protocol_fees.sql` | CHECK widen pattern | | `indexer/src/api/protocol_fees.rs`, `protocol_fee_series.rs`, `api/defillama.rs` | Public ledger | | `indexer/tests/indexer_protocol_fees.rs`, `indexer_protocol_fees_series.rs`, `indexer_defillama.rs` | Existing source tests | | `frontend-dapp/src/types/index.ts` | `ProtocolFeeSourceKey` | | `frontend-dapp/src/components/protocol/ProtocolFeeStats.tsx` | Labels / hide-idle | | `smartcontracts/contracts/factory/src/contract.rs` | `creation_fee_uluna` (read-only) | | `docs/indexer-invariants.md`, `docs/audits/factory-treasury-bank-send.md` | Item 11 until this ships | | `skills/AGENTS_INDEXER_UST1_WINDOW_FEES.md`, `AGENTS_INDEXER_WRAP_FEE_INGEST.md`, `AGENTS_INDEXER_FEE_LEDGER_HOME.md` | Pattern / home map | --- ## Recommended direction 1. Add `FeeSource::PairCreation` / `pair_creation`. Copy wrap/window: per-action scan, reserved `_contract_address`, fail-closed positive amount. 2. Parse pinned factory + `action=create_pair` + positive `creation_fee_uluna`. Asset = native `uluna`. Stamp `fee_usd` from LUNC catalog. 3. Optional same-tx equality assert vs treasury uluna send. Attr wins; no second row. 4. Widen CHECKs, `FeeSource::ALL`, rollups, Defillama additive field, frontend key + label **Pair creation**. 5. `make verify-issue-1209` (or equivalent) bundled like #614. Playbook skill optional. 6. Historical backfill only if needed for Phase 0 baseline: idempotent on `(tx_hash, source, ordinal)`; must not count gas. 7. After ship: marketing snapshots may note the eighth stream; provisional LCD stopgap marked retired. Reject: counting gas; inferring fee from config × count; mixing invoices into this source. --- ## Acceptance criteria - [ ] **AC1.** `FeeSource` includes `pair_creation`; CHECK constraints, rollups, Defillama, and UI labels updated. - [ ] **AC2.** Positive `creation_fee_uluna` on pinned factory `create_pair` inserts exactly one `protocol_fee_events` row; `tx_hash` is the create tx. - [ ] **AC3.** Instantiate gas, refunds, and `reply_instantiate_pair` are not ingested as fees. - [ ] **AC4.** Zero-fee creates produce no fee row. Spoof / unreserved emitter ignored (#285). - [ ] **AC5.** `GET /api/v1/protocol/fees` and `/daily` expose `pair_creation` with idle `"0"` / unpriced `null` / `window` allowlist unchanged (invalid window still 400). - [ ] **AC6.** Frontend protocol stats shows **Pair creation** when `event_count > 0`. Unknown source strings are not interpolated into JS. - [ ] **AC7.** Replay/reorg uniqueness prevents double insert. SKU invoices and S1 client events unchanged. - [ ] **AC8.** `docs/indexer-invariants.md` and factory-treasury audit item 11 updated (parser now exists). --- ## Test plan (functional paths) | # | Path | Expect | | --- | --- | --- | | T1 | Exact fee create | Row amount = `creation_fee_uluna`; USD stamped or NULL per LUNC catalog | | T2 | Overpay | Fee row = fee, not attached uluna (refund excluded) | | T3 | Underpay / stray denom | No pair, no fee row | | T4 | Zero fee | Pair may exist; no `pair_creation` row | | T5 | Instantiate failure | Chain reverts fee; no success row | | T6 | Flattened wasm | Factory segment scoped by reserved `_contract_address` only | | T7 | Bank vs attr mismatch | No double row; fail-closed documented | | T8 | Fee config change | Later creates use emitted attr, not old config × count | | T9 | API `window=24h\|7d\|30d`; bad window 400 | `by_source` includes `pair_creation`; additive JSON | | T10 | Idle vs unpriced | Same `"0"` / `null` rules as wrap/UST1 | | T11 | Defillama + overview | New field; old clients ignore unknown keys | | T12 | Frontend label; unknown source string | Safe render | | T13 | Backfill (if any) | Idempotent; gas not counted | | T14 | Regression | `make verify-issue-586` / `make verify-issue-614` still green | --- ## Test plan (attack, hack, and abuse) | # | Vector | Expect | | --- | --- | --- | | A1 | Spoof wasm `action=create_pair` from non-factory contract | Ignored unless reserved `_contract_address` = pinned factory | | A2 | Unreserved `contract_address` (no underscore) | Ignored (#285) | | A3 | Count gas / full user uluna outflows as fee | Rejected | | A4 | Double-count bank send + attr | Single row | | A5 | Count refund uluna as fee | Refund is to sender; not ingested | | A6 | Count `reply_instantiate_pair` | Not a fee | | A7 | Replay / reorg double insert | `(tx_hash, source, ordinal)` uniqueness | | A8 | Infer fee from config × create count | Forbidden | | A9 | Symbol spoof / wrong USD | Price via `uluna` catalog identity | | A10 | Mix SKU UST1 or swap commission into this source | Forbidden | | A11 | Client analytics as fee truth | Out of scope (#1202) | | A12 | Over-long / non-numeric `creation_fee_uluna` | Parse fail; no panic; no row | --- ## Verification criteria - Indexer fixtures: positive fee, zero fee, spoof contract, refund, gas-only, flattened wasm. - API tests: `by_source` contains `pair_creation` with correct `event_count` / `amount_usd` semantics. - Frontend type/label tests include the new key. - Existing protocol-fee, series, and Defillama tests pass. - A captured or LocalTerra `create_pair` txhash matches `protocol_fee_events` (`source=pair_creation`) and **does not** include gas as `amount`. - `make verify-issue-1209` (or the issue verify target named in the PR) plus `make verify-issue-586` / `make verify-issue-614`.
PlasticDigits changed title from feat: index pair_creation fees on /api/v1/protocol/fees (no instantiate-gas double-count) to feat(indexer): index pair_creation fees on /api/v1/protocol/fees (no instantiate-gas double-count) 2026-09-13 05:37:42 +00:00

Repair: DEX-native DoR. Not implemented (FeeSource still 7; no create_pair fee parser). Left unbundled from #1210/#1211 per #1213 stack. Marketing #1 stays closed tracker.

Repair: DEX-native DoR. Not implemented (`FeeSource` still 7; no create_pair fee parser). Left unbundled from #1210/#1211 per #1213 stack. Marketing #1 stays closed tracker.

/agent implement

/agent implement

/agent implement

/agent implement

/agent implement

/agent implement

Verification on refreshed main (54c4868e): keep #1209 open. FeeSource still has seven values; there is no PairCreation parser or make verify-issue-1209 target.

Remaining:

  1. Parse only positive emitted creation_fee_uluna from pinned factory create_pair; ignore spoof/unreserved emitters, gas, refunds, reply attrs, and duplicate bank-send counting.
  2. Persist as pair_id IS NULL with #1269's non-pair partial unique key; wire rollups, API/daily, DeFiLlama, and the fixed UI label while preserving idle/unpriced/window semantics.
  3. Add parser/API/UI and replay coverage plus make verify-issue-1209; update audit item 11 after ingest ships.

Related: #1213 is the closed home map; #1269 is the closed uniqueness prerequisite; #1210/#1211 are separate later sources; #285 governs reserved emitter identity. None replaces #1209.

Checks: make verify-issue-1213 passed 4/4. #1269 docs/source checks, 34 unit tests, and parser test passed; its integration run passed 25/26 with one Postgres pool timeout, and the isolated case passed on rerun.

Verification on refreshed main (`54c4868e`): keep #1209 open. `FeeSource` still has seven values; there is no `PairCreation` parser or `make verify-issue-1209` target. Remaining: 1. Parse only positive emitted `creation_fee_uluna` from pinned factory `create_pair`; ignore spoof/unreserved emitters, gas, refunds, reply attrs, and duplicate bank-send counting. 2. Persist as `pair_id IS NULL` with #1269's non-pair partial unique key; wire rollups, API/daily, DeFiLlama, and the fixed UI label while preserving idle/unpriced/window semantics. 3. Add parser/API/UI and replay coverage plus `make verify-issue-1209`; update audit item 11 after ingest ships. Related: #1213 is the closed home map; #1269 is the closed uniqueness prerequisite; #1210/#1211 are separate later sources; [#285](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/285) governs reserved emitter identity. None replaces #1209. Checks: `make verify-issue-1213` passed 4/4. #1269 docs/source checks, 34 unit tests, and parser test passed; its integration run passed 25/26 with one Postgres pool timeout, and the isolated case passed on rerun.

Reopening (Market sensor). This was auto-closed when docs-only PR #1348 merged, but the acceptance criterion is not met: live GET /api/v1/protocol/fees?window=24h on 2026-09-25 still returns only 7 by_source values (book_take, limit_place, swap_amm, unwrap, ust1_mint, ust1_redeem, wrap), with no pair_creation source. Close only when the indexer ingests it and it appears on the live endpoint. Labels ready+agent:implement stay.

Reopening (Market sensor). This was auto-closed when docs-only PR #1348 merged, but the acceptance criterion is not met: live `GET /api/v1/protocol/fees?window=24h` on 2026-09-25 still returns only 7 `by_source` values (book_take, limit_place, swap_amm, unwrap, ust1_mint, ust1_redeem, wrap), with no pair_creation source. Close only when the indexer ingests it and it appears on the live endpoint. Labels ready+agent:implement stay.
Sign in to join this conversation.
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#1209
No description provided.