Skip to content

docs: add event schema and Dune analytics guide - #80

Merged
0xdevcollins merged 4 commits into
boundlessfi:testnetfrom
ryzen-xp:feat/dune-analytics-docs
Jul 23, 2026
Merged

docs: add event schema and Dune analytics guide#80
0xdevcollins merged 4 commits into
boundlessfi:testnetfrom
ryzen-xp:feat/dune-analytics-docs

Conversation

@ryzen-xp

@ryzen-xp ryzen-xp commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the event-emission documentation and Dune analytics guide called for in
the on-chain analytics task. No contract code is changed — this is docs-only.


What's in this PR

docs/dune-analytics.md (new, 560 lines)

Complete reference for anyone building analytics on the Boundless contract:

  • §1 — How Dune indexes Soroban events. Relevant tables
    (stellar.history_contract_events, stellar.contract_data, etc.), column
    layout, ScVal auto-decoding rules.
  • §2 — Complete event schema. Every one of the 27 emitted events documented
    with topic name, per-field ScVal type, and analytics notes:
    • Core lifecycle: EventCreated, EventCancelled, FundsAdded,
      ContributorRefunded, OwnerResidualRefunded
    • Participation: Applied, ApplicationWithdrawn, Submitted,
      SubmissionWithdrawn
    • Payouts: WinnersSelected, WinnerPaid, MilestoneClaimed
    • Admin/config: AdminUpdated, PendingAdminSet, FeeAccountUpdated,
      FeeBpsUpdated, ProfileContractUpdated, TokenRegistered,
      TokenDeregistered, Paused, Unpaused
    • Upgrade/migration: PendingUpgradeProposed, PendingUpgradeCancelled,
      UpgradeApplied, Upgraded (legacy alias), Migrated
  • §3 — TVL accounting model. Exact inflow/outflow events, net-of-fee
    semantics, Crowdfunding vs other pillars distinction.
  • §4 — 10 Dune SQL query skeletons (also in standalone .sql files).
  • §5 — Dashboard layout. Suggested panel arrangement for the public
    Boundless On-chain Dune dashboard.
  • §6 — Acceptance checklist.
  • §7 — Maintenance notes (upgrades, new tokens, fee changes).

docs/dune-queries/ (new, 10 .sql files)

Each file is a standalone, paste-ready Dune query. All use {{CONTRACT_ADDRESS}}
as a Dune parameter so the same queries work on testnet and mainnet.

File Panel Type
01_tvl_current.sql Current TVL Counter
02_tvl_over_time.sql TVL over time Area chart
03_bounties_funded.sql Events by pillar + budget Bar chart
04_total_payouts.sql Total payouts over time Bar chart
05_unique_participants.sql Unique builders + organizers Counter
06_event_outcomes.sql Funded / completed / cancelled funnel Bar chart
07_avg_size_and_ttp.sql Avg budget + time-to-payout Table
08_payout_by_token.sql Payout volume by token Table
09_crowdfunding_contributions.sql Crowdfunding daily inflows Line chart
10_event_created_decode_test.sql EventCreated decode verification Table

Analytics correctness notes

Every analytics-relevant event carries decodable id / amount / asset /
address fields:

Requirement Covered by
Event identifier id on EventCreated; event_id on all subsequent events
Amount total_budget (create), amount (FundsAdded, WinnerPaid, MilestoneClaimed, refunds)
Asset / token token on EventCreated; join via event_id for payout events
Address owner, contributor, recipient, applicant on relevant events

All amount fields in events are net-of-fee — the protocol fee is deducted
before remaining_escrow is credited. No fee adjustment is needed in SQL if the
rate changes.

Crowdfunding vs other pillars: EventCreated.total_budget is a funding goal
for Crowdfunding (escrow starts at 0). The TVL queries exclude it from creation
inflows and rely solely on FundsAdded for crowdfunding inflows.


Stale field removed from docs

The Applied event documentation previously listed a credit_cost: U32 field
carried over from the pre-1.1.0 schema. Credits moved off-chain in the 1.1.0
upgrade; the field was dropped from the Applied struct. This PR fixes the doc
to match the live contract: Applied carries only { event_id, applicant }.


Acceptance criteria status

  • Event schema documented — every analytics-relevant event confirmed
    decodable (id, amount, asset, address, topic)
  • 10_event_created_decode_test.sql decodes EventCreated filtered to the
    contract address and returns id, pillar, owner, token,
    total_budget, title
  • Dune query skeletons cover TVL + total payouts + bounties funded
  • Dashboard live at dune.com (pending manual creation — queries are ready
    to paste; dashboard URL will be added to dune-analytics.md once published)

Summary by CodeRabbit

  • Documentation
    • Added a comprehensive guide for integrating Boundless analytics with Dune, including event schema explanations and TVL accounting rules.
    • Published ready-to-use query templates for TVL (current and over time), funding, payouts, participant counts, outcome funnels, average bounty size and time-to-payout, token-wise payouts, and crowdfunding contributions.
    • Added an event decoding validation query to help verify deployed contract event parsing.
  • Chores
    • Updated the build verification workflow to also run when documentation files change.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0801e4d3-ced9-4841-ba19-9eb174d75372

📥 Commits

Reviewing files that changed from the base of the PR and between e491bef and 6e29636.

📒 Files selected for processing (1)
  • .github/workflows/verify-build.yml

📝 Walkthrough

Walkthrough

Adds comprehensive Boundless Soroban event documentation and Dune SQL templates for TVL, funding, payouts, participation, outcomes, token volumes, crowdfunding contributions, decoding validation, dashboard layout, maintenance, and documentation workflow triggers.

Changes

Dune analytics integration

Layer / File(s) Summary
Event schema and accounting model
docs/dune-analytics.md
Documents decoded Soroban events across lifecycle, participation, payouts, administration, and upgrades, and defines inflow, outflow, fee, and Crowdfunding accounting rules.
TVL query flows
docs/dune-analytics.md, docs/dune-queries/01_tvl_current.sql, docs/dune-queries/02_tvl_over_time.sql
Adds current TVL and daily running-balance queries based on decoded escrow inflows and outflows.
Contract metric queries
docs/dune-analytics.md, docs/dune-queries/03_bounties_funded.sql09_crowdfunding_contributions.sql
Adds queries for funding, payouts, participant counts, outcomes, timing, token volumes, and crowdfunding contributions.
Decode validation and dashboard support
docs/dune-analytics.md, docs/dune-queries/10_event_created_decode_test.sql, .github/workflows/verify-build.yml
Adds an EventCreated decoding test, dashboard panel guidance, acceptance checks, maintenance notes, and workflow triggers for documentation changes.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Poem

I’m a rabbit with queries, my whiskers now gleam,
Events hop through Dune in a data-filled stream.
TVL climbs, payouts take flight,
Bounties are counted from morning till night.
Decoded fields nest safely in burrows,
Dashboards sparkle as analytics purr.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Most analytics docs and queries are present, but #66 also asked for a public Dune dashboard, which this PR says has not been created yet. Create and link the Dune dashboard with the prepared TVL, payouts, and bounties panels, then update the PR once the dashboard exists.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed It clearly summarizes the main change: adding a Dune analytics guide and event schema docs.
Out of Scope Changes check ✅ Passed The CI path filter tweak is ancillary to the docs-only analytics work and supports verification for the new docs files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@0xdevcollins

Copy link
Copy Markdown
Collaborator

Hi @ryzen-xp trust you are doing great?
Are you still working on this PR?

@ryzen-xp

Copy link
Copy Markdown
Contributor Author

Hi @ryzen-xp trust you are doing great? Are you still working on this PR?

yeah !! ,

topic_1/data do not exist in stellar.history_contract_events.
The real columns are:
  topics_decoded  VARCHAR  JSON array — index 0 is the event-name symbol
  data_decoded    VARCHAR  JSON object — keyed by field name

Replace all topic_1 references with:
  JSON_EXTRACT_SCALAR(topics_decoded, '$[0]')

Replace all data references with:
  JSON_EXTRACT_SCALAR(data_decoded, '$.field')

Fix applied to all 10 .sql files and the matching code blocks in
docs/dune-analytics.md. Also add correct column table to §1.
@ryzen-xp
ryzen-xp marked this pull request as ready for review July 21, 2026 16:35
coderabbitai[bot]
coderabbitai Bot previously requested changes Jul 21, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
docs/dune-queries/05_unique_participants.sql (1)

17-17: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Prefer UNION ALL when deduplication is handled by the outer query. Using UNION forces the database engine to perform an unnecessary deduplication step on the combined result set. Since the outer query is doing COUNT(DISTINCT ...), UNION ALL is faster and more idiomatic.

  • docs/dune-queries/05_unique_participants.sql#L17-L17: Change UNION to UNION ALL.
  • docs/dune-analytics.md#L376-L376: Change UNION to UNION ALL.
♻️ Proposed fix (apply to both sites)
-    UNION
+    UNION ALL
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/dune-queries/05_unique_participants.sql` at line 17, Replace UNION with
UNION ALL at docs/dune-queries/05_unique_participants.sql:17 and
docs/dune-analytics.md:376, preserving the outer COUNT(DISTINCT ...)
deduplication behavior.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/dune-queries/01_tvl_current.sql`:
- Around line 21-51: Replace the unaggregated inflows/outflows CTEs and FULL
OUTER JOIN in docs/dune-queries/01_tvl_current.sql lines 21-51 with a
single-pass SUM(CASE ...) aggregation, mirroring 02_tvl_over_time.sql; apply the
identical correction to the markdown query in docs/dune-analytics.md lines
262-286 so both calculate TVL without Cartesian multiplication.

In `@docs/dune-queries/06_event_outcomes.sql`:
- Line 37: Replace the subtraction-based active_or_pending calculation in
docs/dune-queries/06_event_outcomes.sql at lines 37-37 with an explicit count of
rows where both paid and cancelled event IDs are null. Apply the same explicit
null-check count in docs/dune-analytics.md at lines 425-425, preserving the
active_or_pending alias.

---

Nitpick comments:
In `@docs/dune-queries/05_unique_participants.sql`:
- Line 17: Replace UNION with UNION ALL at
docs/dune-queries/05_unique_participants.sql:17 and docs/dune-analytics.md:376,
preserving the outer COUNT(DISTINCT ...) deduplication behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9e1de45d-f97e-4353-8bb8-e9126b56adee

📥 Commits

Reviewing files that changed from the base of the PR and between e1f1793 and e491bef.

📒 Files selected for processing (11)
  • docs/dune-analytics.md
  • docs/dune-queries/01_tvl_current.sql
  • docs/dune-queries/02_tvl_over_time.sql
  • docs/dune-queries/03_bounties_funded.sql
  • docs/dune-queries/04_total_payouts.sql
  • docs/dune-queries/05_unique_participants.sql
  • docs/dune-queries/06_event_outcomes.sql
  • docs/dune-queries/07_avg_size_and_ttp.sql
  • docs/dune-queries/08_payout_by_token.sql
  • docs/dune-queries/09_crowdfunding_contributions.sql
  • docs/dune-queries/10_event_created_decode_test.sql

Comment on lines +21 to +51
WITH inflows AS (
-- Non-crowdfunding events: budget deposited at creation
SELECT CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.total_budget') AS DOUBLE) AS amount
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'EventCreated'
AND JSON_EXTRACT_SCALAR(data_decoded, '$.pillar') != 'Crowdfunding'

UNION ALL

-- All add_funds deposits (crowdfunding contributions + partner top-ups)
SELECT CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE) AS amount
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'FundsAdded'
),
outflows AS (
SELECT CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE) AS amount
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') IN (
'WinnerPaid',
'MilestoneClaimed',
'ContributorRefunded',
'OwnerResidualRefunded'
)
)
SELECT
(COALESCE(SUM(i.amount), 0) - COALESCE(SUM(o.amount), 0)) / 1e7 AS tvl_usdc
FROM inflows i
FULL OUTER JOIN outflows o ON 1 = 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Cartesian product logic error in TVL calculation. Performing a FULL OUTER JOIN ... ON 1=1 on unaggregated CTEs creates a Cartesian product, multiplying every inflow row by the total count of outflow rows. This drastically inflates the tvl_usdc total. You can safely fix this by replacing the CTEs and the join with a single-pass SUM(CASE ...) query, mirroring the elegant logic already used in 02_tvl_over_time.sql.

  • docs/dune-queries/01_tvl_current.sql#L21-L51: Replace the inflows and outflows CTEs and the join with the single-pass snippet below.
  • docs/dune-analytics.md#L262-L286: Replace the markdown snippet identically so the documentation matches the query correctly.
🐛 Proposed fix (apply to both sites)
-WITH inflows AS (
-    -- Non-crowdfunding events: budget deposited at creation
-    SELECT CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.total_budget') AS DOUBLE) AS amount
-    FROM stellar.history_contract_events
-    WHERE contract_id = '{{CONTRACT_ADDRESS}}'
-      AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'EventCreated'
-      AND JSON_EXTRACT_SCALAR(data_decoded, '$.pillar') != 'Crowdfunding'
-
-    UNION ALL
-
-    -- All add_funds deposits (crowdfunding contributions + partner top-ups)
-    SELECT CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE) AS amount
-    FROM stellar.history_contract_events
-    WHERE contract_id = '{{CONTRACT_ADDRESS}}'
-      AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'FundsAdded'
-),
-outflows AS (
-    SELECT CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE) AS amount
-    FROM stellar.history_contract_events
-    WHERE contract_id = '{{CONTRACT_ADDRESS}}'
-      AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') IN (
-          'WinnerPaid',
-          'MilestoneClaimed',
-          'ContributorRefunded',
-          'OwnerResidualRefunded'
-      )
-)
-SELECT
-    (COALESCE(SUM(i.amount), 0) - COALESCE(SUM(o.amount), 0)) / 1e7 AS tvl_usdc
-FROM inflows i
-FULL OUTER JOIN outflows o ON 1 = 1
+SELECT
+    COALESCE(SUM(
+        CASE
+            WHEN JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'EventCreated'
+              AND JSON_EXTRACT_SCALAR(data_decoded, '$.pillar') != 'Crowdfunding'
+            THEN CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.total_budget') AS DOUBLE)
+            WHEN JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'FundsAdded'
+            THEN CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE)
+            WHEN JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') IN (
+                'WinnerPaid', 'MilestoneClaimed',
+                'ContributorRefunded', 'OwnerResidualRefunded'
+            )
+            THEN -CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE)
+            ELSE 0
+        END
+    ), 0) / 1e7 AS tvl_usdc
+FROM stellar.history_contract_events
+WHERE contract_id = '{{CONTRACT_ADDRESS}}'
+  AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') IN (
+      'EventCreated', 'FundsAdded',
+      'WinnerPaid', 'MilestoneClaimed',
+      'ContributorRefunded', 'OwnerResidualRefunded'
+  )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
WITH inflows AS (
-- Non-crowdfunding events: budget deposited at creation
SELECT CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.total_budget') AS DOUBLE) AS amount
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'EventCreated'
AND JSON_EXTRACT_SCALAR(data_decoded, '$.pillar') != 'Crowdfunding'
UNION ALL
-- All add_funds deposits (crowdfunding contributions + partner top-ups)
SELECT CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE) AS amount
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'FundsAdded'
),
outflows AS (
SELECT CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE) AS amount
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') IN (
'WinnerPaid',
'MilestoneClaimed',
'ContributorRefunded',
'OwnerResidualRefunded'
)
)
SELECT
(COALESCE(SUM(i.amount), 0) - COALESCE(SUM(o.amount), 0)) / 1e7 AS tvl_usdc
FROM inflows i
FULL OUTER JOIN outflows o ON 1 = 1
SELECT
COALESCE(SUM(
CASE
WHEN JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'EventCreated'
AND JSON_EXTRACT_SCALAR(data_decoded, '$.pillar') != 'Crowdfunding'
THEN CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.total_budget') AS DOUBLE)
WHEN JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') = 'FundsAdded'
THEN CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE)
WHEN JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') IN (
'WinnerPaid', 'MilestoneClaimed',
'ContributorRefunded', 'OwnerResidualRefunded'
)
THEN -CAST(JSON_EXTRACT_SCALAR(data_decoded, '$.amount') AS DOUBLE)
ELSE 0
END
), 0) / 1e7 AS tvl_usdc
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND JSON_EXTRACT_SCALAR(topics_decoded, '$[0]') IN (
'EventCreated', 'FundsAdded',
'WinnerPaid', 'MilestoneClaimed',
'ContributorRefunded', 'OwnerResidualRefunded'
)
📍 Affects 2 files
  • docs/dune-queries/01_tvl_current.sql#L21-L51 (this comment)
  • docs/dune-analytics.md#L262-L286
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/dune-queries/01_tvl_current.sql` around lines 21 - 51, Replace the
unaggregated inflows/outflows CTEs and FULL OUTER JOIN in
docs/dune-queries/01_tvl_current.sql lines 21-51 with a single-pass SUM(CASE
...) aggregation, mirroring 02_tvl_over_time.sql; apply the identical correction
to the markdown query in docs/dune-analytics.md lines 262-286 so both calculate
TVL without Cartesian multiplication.

COUNT(c.event_id) AS total_created,
COUNT(p.event_id) AS completed_with_payout,
COUNT(cx.event_id) AS cancelled,
COUNT(c.event_id) - COUNT(p.event_id) - COUNT(cx.event_id) AS active_or_pending

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Avoid subtraction for active counts. The subtraction formula assumes an event is exclusively paid or cancelled. If an event is cancelled after a milestone was claimed, it falls into both the paid and cancelled sets. Subtracting both from the total will result in a negative count for active_or_pending. Use an explicit null check instead.

  • docs/dune-queries/06_event_outcomes.sql#L37-L37: Update the subtraction logic to count rows that have neither outcome.
  • docs/dune-analytics.md#L425-L425: Apply the same explicit count.
💡 Proposed fix (apply to both sites)
-    COUNT(c.event_id) - COUNT(p.event_id) - COUNT(cx.event_id)          AS active_or_pending
+    SUM(CASE WHEN p.event_id IS NULL AND cx.event_id IS NULL THEN 1 ELSE 0 END) AS active_or_pending
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
COUNT(c.event_id) - COUNT(p.event_id) - COUNT(cx.event_id) AS active_or_pending
SUM(CASE WHEN p.event_id IS NULL AND cx.event_id IS NULL THEN 1 ELSE 0 END) AS active_or_pending
📍 Affects 2 files
  • docs/dune-queries/06_event_outcomes.sql#L37-L37 (this comment)
  • docs/dune-analytics.md#L425-L425
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/dune-queries/06_event_outcomes.sql` at line 37, Replace the
subtraction-based active_or_pending calculation in
docs/dune-queries/06_event_outcomes.sql at lines 37-37 with an explicit count of
rows where both paid and cancelled event IDs are null. Apply the same explicit
null-check count in docs/dune-analytics.md at lines 425-425, preserving the
active_or_pending alias.

…uired check

The build job only triggered on contracts/** and toolchain paths, so a
docs-only PR never ran it — and since build is a required status check,
those PRs were unmergeable (BLOCKED with 'build expected', not even
admin-overridable). Add docs/** to the triggers: build recompiles the
contract (a no-op pass for docs) and the required check is satisfied.

Also brings this branch up to current testnet.
@almanax-ai

almanax-ai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Quota reached

Your plan allows 300 CI/CD file units per month. You've used 297 and this scan would add 60 more (total: 357).

@0xdevcollins
0xdevcollins merged commit 02153d4 into boundlessfi:testnet Jul 23, 2026
3 of 4 checks passed
0xdevcollins added a commit that referenced this pull request Jul 23, 2026
…n) (#97)

The queries merged in #80 return zero rows against Dune: they filtered on
JSON_EXTRACT_SCALAR(topics_decoded,'$[0]') (an ScVal object, never the
event name) and read data_decoded as flat $.field (it's a type-wrapped
ScVal map). Both silently yield null, so every dashboard panel is empty.

Verified the real stellar.history_contract_events shapes on live Dune data
and rewrote all 10 dune-queries/*.sql to:
- filter the event name via topics_decoded '$[0].symbol'
- decode fields by rebuilding data_decoded '$.map' into
  MAP(field -> ScVal JSON) with map_from_entries(), then reading each by
  ScVal type ($.u64, $.i128, $.address, $.string, $.vec[0].symbol)
- add the closed_at_date partition filter (avoids full-table scans)
- to_hex(transaction_hash) (it is varbinary)

Every primitive was executed against live Soroban events on Dune. The one
field that can't be checked without a real Boundless event — pillar's unit-
enum encoding — is emitted as pillar_raw in the decode test for confirmation.

Doc fixes: rewrote the §1 decoding reference; corrected the fee accounting
(escrow holds the full budget, fee charged on top; fee revenue is not in the
events); added the ManagerProposed/ManagerChanged/PendingManagerCancelled
events (#88); pointed §4 at the canonical .sql files instead of duplicating
now-corrected SQL inline.
@coderabbitai coderabbitai Bot mentioned this pull request Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Connect Dune Analytics to the escrow contract for on-chain analytics

2 participants