Skip to content
Draft
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
560 changes: 560 additions & 0 deletions docs/dune-analytics.md

Large diffs are not rendered by default.

47 changes: 47 additions & 0 deletions docs/dune-queries/01_tvl_current.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
-- Boundless On-chain: Current TVL
-- Panel type: counter
-- Description: Total escrow balance currently held by the contract.
--
-- Inflows:
-- EventCreated.total_budget (non-Crowdfunding pillars — escrowed at creation)
-- FundsAdded.amount (partner top-ups and crowdfunding contributions)
-- Outflows:
-- WinnerPaid.amount (single-release payout at select_winners)
-- MilestoneClaimed.amount (grant / crowdfunding milestone payout)
-- ContributorRefunded.amount (partner refund during cancel)
-- OwnerResidualRefunded.amount (owner residual at cancel)
--
-- All amounts are net-of-fee (protocol fee is deducted before events are emitted).
-- Divide by 1e7 to convert from stroops to USDC / XLM display units.

WITH inflows AS (
-- Non-crowdfunding events: budget deposited at creation
SELECT CAST(JSON_EXTRACT_SCALAR(data, '$.total_budget') AS DOUBLE) AS amount
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'EventCreated'
AND JSON_EXTRACT_SCALAR(data, '$.pillar') != 'Crowdfunding'

UNION ALL

-- All add_funds deposits (crowdfunding + partner top-ups)
SELECT CAST(JSON_EXTRACT_SCALAR(data, '$.amount') AS DOUBLE) AS amount
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'FundsAdded'
),
outflows AS (
SELECT CAST(JSON_EXTRACT_SCALAR(data, '$.amount') AS DOUBLE) AS amount
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 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
49 changes: 49 additions & 0 deletions docs/dune-queries/02_tvl_over_time.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
-- Boundless On-chain: TVL over time (daily running balance)
-- Panel type: area chart x=day y=tvl_usdc
--
-- Calculates the net daily escrow delta then uses a window function to
-- produce a running sum. Each row shows the TVL at end-of-day.

WITH raw_events AS (
SELECT
DATE_TRUNC('day', closed_at) AS day,
CASE
-- Inflow: non-crowdfunding creation
WHEN topic_1 = 'EventCreated'
AND JSON_EXTRACT_SCALAR(data, '$.pillar') != 'Crowdfunding'
THEN CAST(JSON_EXTRACT_SCALAR(data, '$.total_budget') AS DOUBLE)

-- Inflow: add_funds (crowdfunding + partner top-ups)
WHEN topic_1 = 'FundsAdded'
THEN CAST(JSON_EXTRACT_SCALAR(data, '$.amount') AS DOUBLE)

-- Outflow: winner / milestone payouts and refunds
WHEN topic_1 IN (
'WinnerPaid', 'MilestoneClaimed',
'ContributorRefunded', 'OwnerResidualRefunded'
)
THEN -CAST(JSON_EXTRACT_SCALAR(data, '$.amount') AS DOUBLE)

ELSE 0
END AS delta
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 IN (
'EventCreated', 'FundsAdded',
'WinnerPaid', 'MilestoneClaimed',
'ContributorRefunded', 'OwnerResidualRefunded'
)
),
daily_delta AS (
SELECT
day,
SUM(delta) / 1e7 AS daily_change_usdc
FROM raw_events
GROUP BY 1
)
SELECT
day,
daily_change_usdc,
SUM(daily_change_usdc) OVER (ORDER BY day ROWS UNBOUNDED PRECEDING) AS tvl_usdc
FROM daily_delta
ORDER BY day ASC
14 changes: 14 additions & 0 deletions docs/dune-queries/03_bounties_funded.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- Boundless On-chain: Events created — count and budget by pillar and month
-- Panel type: bar chart (grouped) x=month y=events_created color=pillar
-- or table for detailed view

SELECT
DATE_TRUNC('month', closed_at) AS month,
JSON_EXTRACT_SCALAR(data, '$.pillar') AS pillar,
COUNT(*) AS events_created,
SUM(CAST(JSON_EXTRACT_SCALAR(data, '$.total_budget') AS DOUBLE)) / 1e7 AS total_budget_usdc
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'EventCreated'
GROUP BY 1, 2
ORDER BY 1 DESC, 2 ASC
17 changes: 17 additions & 0 deletions docs/dune-queries/04_total_payouts.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- Boundless On-chain: Total payouts to builders
-- Panel type: bar chart x=month y=total_paid_usdc color=payout_type
--
-- WinnerPaid → Hackathon / Bounty (single-release, paid at select_winners)
-- MilestoneClaimed → Grant / Crowdfunding (multi-release, paid per milestone)

SELECT
DATE_TRUNC('month', closed_at) AS month,
topic_1 AS payout_type,
COUNT(*) AS payout_count,
COUNT(DISTINCT JSON_EXTRACT_SCALAR(data, '$.recipient')) AS unique_recipients,
SUM(CAST(JSON_EXTRACT_SCALAR(data, '$.amount') AS DOUBLE)) / 1e7 AS total_paid_usdc
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 IN ('WinnerPaid', 'MilestoneClaimed')
GROUP BY 1, 2
ORDER BY 1 DESC, 2 ASC
30 changes: 30 additions & 0 deletions docs/dune-queries/05_unique_participants.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-- Boundless On-chain: Unique builder and organizer wallets
-- Panel type: counter (two numbers side-by-side)

-- Unique builders: wallets that applied to or received a payout from any event
SELECT
'builders' AS role,
COUNT(DISTINCT addr) AS unique_wallets
FROM (
SELECT JSON_EXTRACT_SCALAR(data, '$.applicant') AS addr
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'Applied'

UNION

SELECT JSON_EXTRACT_SCALAR(data, '$.recipient') AS addr
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 IN ('WinnerPaid', 'MilestoneClaimed')
) t

UNION ALL

-- Unique organizers: wallets that created at least one event
SELECT
'organizers' AS role,
COUNT(DISTINCT JSON_EXTRACT_SCALAR(data, '$.owner')) AS unique_wallets
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'EventCreated'
40 changes: 40 additions & 0 deletions docs/dune-queries/06_event_outcomes.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-- Boundless On-chain: Event outcome funnel
-- Panel type: bar chart or table
--
-- Buckets every created event into:
-- completed_with_payout — had at least one WinnerPaid or MilestoneClaimed
-- cancelled — received an EventCancelled
-- active_or_pending — neither above (still running or awaiting selection)

WITH created AS (
SELECT
CAST(JSON_EXTRACT_SCALAR(data, '$.id') AS BIGINT) AS event_id,
JSON_EXTRACT_SCALAR(data, '$.pillar') AS pillar,
closed_at AS created_at
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'EventCreated'
),
cancelled AS (
SELECT DISTINCT CAST(JSON_EXTRACT_SCALAR(data, '$.id') AS BIGINT) AS event_id
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'EventCancelled'
),
paid AS (
SELECT DISTINCT CAST(JSON_EXTRACT_SCALAR(data, '$.event_id') AS BIGINT) AS event_id
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 IN ('WinnerPaid', 'MilestoneClaimed')
)
SELECT
c.pillar,
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
FROM created c
LEFT JOIN paid p ON c.event_id = p.event_id
LEFT JOIN cancelled cx ON c.event_id = cx.event_id
GROUP BY 1
ORDER BY total_created DESC
34 changes: 34 additions & 0 deletions docs/dune-queries/07_avg_size_and_ttp.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-- Boundless On-chain: Average event budget and time-to-first-payout
-- Panel type: counter / table

WITH created AS (
SELECT
CAST(JSON_EXTRACT_SCALAR(data, '$.id') AS BIGINT) AS event_id,
JSON_EXTRACT_SCALAR(data, '$.pillar') AS pillar,
CAST(JSON_EXTRACT_SCALAR(data, '$.total_budget') AS DOUBLE) / 1e7
AS budget_usdc,
closed_at AS created_at
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'EventCreated'
),
first_payout AS (
SELECT
CAST(JSON_EXTRACT_SCALAR(data, '$.event_id') AS BIGINT) AS event_id,
MIN(closed_at) AS first_paid_at
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 IN ('WinnerPaid', 'MilestoneClaimed')
GROUP BY 1
)
SELECT
c.pillar,
COUNT(c.event_id) AS events_with_payout,
AVG(c.budget_usdc) AS avg_budget_usdc,
MIN(c.budget_usdc) AS min_budget_usdc,
MAX(c.budget_usdc) AS max_budget_usdc,
AVG(DATE_DIFF('day', c.created_at, fp.first_paid_at)) AS avg_days_to_first_payout
FROM created c
JOIN first_payout fp ON c.event_id = fp.event_id
GROUP BY 1
ORDER BY avg_budget_usdc DESC
32 changes: 32 additions & 0 deletions docs/dune-queries/08_payout_by_token.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
-- Boundless On-chain: Payout volume by payment token
-- Panel type: table or donut chart
--
-- Join on stellar.assets (or a manual symbol map) to resolve token address
-- to a human-readable ticker. For now we report the raw contract address.

WITH payouts AS (
SELECT
CAST(JSON_EXTRACT_SCALAR(data, '$.event_id') AS BIGINT) AS event_id,
CAST(JSON_EXTRACT_SCALAR(data, '$.amount') AS DOUBLE) / 1e7 AS amount_usdc,
topic_1 AS payout_type
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 IN ('WinnerPaid', 'MilestoneClaimed')
),
event_tokens AS (
SELECT
CAST(JSON_EXTRACT_SCALAR(data, '$.id') AS BIGINT) AS event_id,
JSON_EXTRACT_SCALAR(data, '$.token') AS token_address
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'EventCreated'
)
SELECT
t.token_address,
p.payout_type,
COUNT(*) AS payout_count,
SUM(p.amount_usdc) AS total_paid_usdc
FROM payouts p
JOIN event_tokens t ON p.event_id = t.event_id
GROUP BY 1, 2
ORDER BY total_paid_usdc DESC
25 changes: 25 additions & 0 deletions docs/dune-queries/09_crowdfunding_contributions.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-- Boundless On-chain: Crowdfunding daily contribution volume
-- Panel type: line chart x=day y=total_contributed_usdc
--
-- FundsAdded covers both crowdfunding community contributions and partner
-- top-ups on Hackathon/Bounty/Grant events. Filter to Crowdfunding events
-- by joining on EventCreated.pillar.

WITH cf_events AS (
SELECT CAST(JSON_EXTRACT_SCALAR(data, '$.id') AS BIGINT) AS event_id
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'EventCreated'
AND JSON_EXTRACT_SCALAR(data, '$.pillar') = 'Crowdfunding'
)
SELECT
DATE_TRUNC('day', hce.closed_at) AS day,
COUNT(*) AS contribution_count,
COUNT(DISTINCT JSON_EXTRACT_SCALAR(hce.data, '$.contributor')) AS unique_contributors,
SUM(CAST(JSON_EXTRACT_SCALAR(hce.data, '$.amount') AS DOUBLE)) / 1e7 AS total_contributed_usdc
FROM stellar.history_contract_events hce
JOIN cf_events cf ON CAST(JSON_EXTRACT_SCALAR(hce.data, '$.event_id') AS BIGINT) = cf.event_id
WHERE hce.contract_id = '{{CONTRACT_ADDRESS}}'
AND hce.topic_1 = 'FundsAdded'
GROUP BY 1
ORDER BY 1 DESC
33 changes: 33 additions & 0 deletions docs/dune-queries/10_event_created_decode_test.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-- Boundless On-chain: EventCreated decode test
-- Use this query to verify that the Dune pipeline is correctly decoding
-- EventCreated events for the deployed contract address.
--
-- Expected columns and types:
-- event_id BIGINT (u64 from contract)
-- pillar VARCHAR ('Hackathon' | 'Bounty' | 'Grant' | 'Crowdfunding')
-- owner VARCHAR (StrKey address, starts with 'G...')
-- token VARCHAR (StrKey address)
-- total_budget_raw BIGINT (stroops, raw)
-- total_budget_usdc DOUBLE (divide by 1e7)
-- title VARCHAR
-- tx_hash VARCHAR
-- ledger BIGINT
-- closed_at TIMESTAMP

SELECT
CAST(JSON_EXTRACT_SCALAR(data, '$.id') AS BIGINT) AS event_id,
JSON_EXTRACT_SCALAR(data, '$.pillar') AS pillar,
JSON_EXTRACT_SCALAR(data, '$.owner') AS owner,
JSON_EXTRACT_SCALAR(data, '$.token') AS token,
CAST(JSON_EXTRACT_SCALAR(data, '$.total_budget') AS BIGINT) AS total_budget_raw,
CAST(JSON_EXTRACT_SCALAR(data, '$.total_budget') AS DOUBLE) / 1e7
AS total_budget_usdc,
JSON_EXTRACT_SCALAR(data, '$.title') AS title,
transaction_hash AS tx_hash,
ledger_sequence AS ledger,
closed_at
FROM stellar.history_contract_events
WHERE contract_id = '{{CONTRACT_ADDRESS}}'
AND topic_1 = 'EventCreated'
ORDER BY ledger_sequence DESC
LIMIT 50
Loading