@@ -12,13 +12,84 @@ export const fetchProposals = async (
1212 includeVoteCount ?: boolean
1313) => {
1414 const result = ( await prisma . $queryRaw `
15- WITH LatestDrepDistr AS (
15+ WITH LatestDrepDistr AS (
16+ SELECT
17+ *,
18+ ROW_NUMBER() OVER (PARTITION BY hash_id ORDER BY epoch_no DESC) AS rn
19+ FROM
20+ drep_distr
21+ ),
22+ CommitteeData AS (
23+ SELECT DISTINCT ON (ch.raw)
24+ encode(ch.raw, 'hex') AS hash,
25+ cm.expiration_epoch,
26+ ch.has_script
27+ FROM
28+ committee_member cm
29+ JOIN committee_hash ch ON cm.committee_hash_id = ch.id
30+ ORDER BY
31+ ch.raw, cm.expiration_epoch DESC
32+ ),
33+ ParsedDescription AS (
34+ SELECT
35+ gov_action_proposal.id,
36+ description->'tag' AS tag,
37+ description->'contents'->1 AS members_to_be_removed,
38+ description->'contents'->2 AS members,
39+ description->'contents'->3 AS threshold
40+ FROM
41+ gov_action_proposal
42+ WHERE
43+ gov_action_proposal.type = 'NewCommittee'
44+ ),
45+ MembersToBeRemoved AS (
1646 SELECT
17- * ,
18- ROW_NUMBER() OVER (PARTITION BY hash_id ORDER BY epoch_no DESC) AS rn
47+ id ,
48+ json_agg(VALUE->>'keyHash') AS members_to_be_removed
1949 FROM
20- drep_distr
21- ),
50+ ParsedDescription pd,
51+ json_array_elements(members_to_be_removed::json) AS value
52+ GROUP BY
53+ id
54+ ),
55+ ProcessedCurrentMembers AS (
56+ SELECT
57+ pd.id,
58+ json_agg(
59+ json_build_object(
60+ 'hash', regexp_replace(kv.key, '^keyHash-', ''),
61+ 'newExpirationEpoch', kv.value::int
62+ )
63+ ) AS current_members
64+ FROM
65+ ParsedDescription pd,
66+ jsonb_each_text(pd.members) AS kv(key, value)
67+ GROUP BY
68+ pd.id
69+ ),
70+ EnrichedCurrentMembers AS (
71+ SELECT
72+ pcm.id,
73+ json_agg(
74+ json_build_object(
75+ 'hash', cm.hash,
76+ 'expirationEpoch', cm.expiration_epoch,
77+ 'hasScript', cm.has_script,
78+ 'newExpirationEpoch', (member->>'newExpirationEpoch')::int
79+ )
80+ ) AS enriched_members
81+ FROM
82+ ProcessedCurrentMembers pcm
83+ LEFT JOIN json_array_elements(pcm.current_members) AS member ON true
84+ LEFT JOIN CommitteeData cm
85+ ON (CASE
86+ WHEN (member->>'hash') ~ '^[0-9a-fA-F]+$'
87+ THEN encode(decode(member->>'hash', 'hex'), 'hex')
88+ ELSE NULL
89+ END) = cm.hash
90+ GROUP BY
91+ pcm.id
92+ ),
2293 EpochUtils AS (
2394 SELECT
2495 (Max(end_time) - Min(end_time)) /(Max(NO) - Min(NO)) AS epoch_duration,
@@ -54,18 +125,51 @@ SELECT
54125 'index', gov_action_proposal.index,
55126 'type', gov_action_proposal.type::text,
56127 'details', CASE
57- when gov_action_proposal.type = 'TreasuryWithdrawals' then
58- json_build_object('Reward Address', stake_address.view, 'Amount', treasury_withdrawal.amount)
59- when gov_action_proposal.type::text = 'InfoAction' then
60- json_build_object()
61- when gov_action_proposal.type::text = 'HardForkInitiation' then
62- json_build_object(
63- 'major', (gov_action_proposal.description->'contents'->1->>'major')::int,
64- 'minor', (gov_action_proposal.description->'contents'->1->>'minor')::int
65- )
66- ELSE
67- null
68- END,
128+ when gov_action_proposal.type = 'TreasuryWithdrawals' then
129+ json_build_object('Reward Address', stake_address.view, 'Amount', treasury_withdrawal.amount)
130+ when gov_action_proposal.type::text = 'InfoAction' then
131+ json_build_object('data', gov_action_proposal.description)
132+ when gov_action_proposal.type::text = 'HardForkInitiation' then
133+ json_build_object(
134+ 'major', (gov_action_proposal.description->'contents'->1->>'major')::int,
135+ 'minor', (gov_action_proposal.description->'contents'->1->>'minor')::int
136+ )
137+ WHEN gov_action_proposal.type::text = 'NoConfidence' THEN
138+ json_build_object('data', gov_action_proposal.description->'contents')
139+ WHEN gov_action_proposal.type::text = 'ParameterChange' THEN
140+ json_build_object('data', gov_action_proposal.description->'contents')
141+ WHEN gov_action_proposal.type::text = 'NewConstitution' THEN
142+ json_build_object(
143+ 'anchor', gov_action_proposal.description->'contents'->1->'anchor',
144+ 'script', gov_action_proposal.description->'contents'->1->'script'
145+ )
146+ WHEN gov_action_proposal.type::text = 'NewCommittee' THEN
147+ (
148+ SELECT
149+ json_build_object(
150+ 'tag', pd.tag,
151+ 'members', em.enriched_members,
152+ 'membersToBeRemoved', mtr.members_to_be_removed,
153+ 'threshold',
154+ CASE
155+ WHEN (pd.threshold->>'numerator') IS NOT NULL
156+ AND (pd.threshold->>'denominator') IS NOT NULL
157+ THEN (pd.threshold->>'numerator')::float / (pd.threshold->>'denominator')::float
158+ ELSE NULL
159+ END
160+ )
161+ FROM
162+ ParsedDescription pd
163+ JOIN
164+ MembersToBeRemoved mtr ON pd.id = mtr.id
165+ JOIN
166+ EnrichedCurrentMembers em ON pd.id = em.id
167+ WHERE
168+ pd.id = gov_action_proposal.id
169+ )
170+ ELSE
171+ null
172+ END,
69173 'status', CASE
70174 when gov_action_proposal.enacted_epoch is not NULL then json_build_object('enactedEpoch', gov_action_proposal.enacted_epoch)
71175 when gov_action_proposal.ratified_epoch is not NULL then json_build_object('ratifiedEpoch', gov_action_proposal.ratified_epoch)
@@ -885,6 +989,77 @@ export const fetchProposalById = async (proposalId: string, proposaIndex: number
885989 FROM
886990 drep_distr
887991 ),
992+ CommitteeData AS (
993+ SELECT DISTINCT ON (ch.raw)
994+ encode(ch.raw, 'hex') AS hash,
995+ cm.expiration_epoch,
996+ ch.has_script
997+ FROM
998+ committee_member cm
999+ JOIN committee_hash ch ON cm.committee_hash_id = ch.id
1000+ ORDER BY
1001+ ch.raw, cm.expiration_epoch DESC
1002+ ),
1003+ ParsedDescription AS (
1004+ SELECT
1005+ gov_action_proposal.id,
1006+ description->'tag' AS tag,
1007+ description->'contents'->1 AS members_to_be_removed,
1008+ description->'contents'->2 AS members,
1009+ description->'contents'->3 AS threshold
1010+ FROM
1011+ gov_action_proposal
1012+ WHERE
1013+ gov_action_proposal.type = 'NewCommittee'
1014+ ),
1015+ MembersToBeRemoved AS (
1016+ SELECT
1017+ id,
1018+ json_agg(VALUE->>'keyHash') AS members_to_be_removed
1019+ FROM
1020+ ParsedDescription pd,
1021+ json_array_elements(members_to_be_removed::json) AS value
1022+ GROUP BY
1023+ id
1024+ ),
1025+ ProcessedCurrentMembers AS (
1026+ SELECT
1027+ pd.id,
1028+ json_agg(
1029+ json_build_object(
1030+ 'hash', regexp_replace(kv.key, '^keyHash-', ''),
1031+ 'newExpirationEpoch', kv.value::int
1032+ )
1033+ ) AS current_members
1034+ FROM
1035+ ParsedDescription pd,
1036+ jsonb_each_text(pd.members) AS kv(key, value)
1037+ GROUP BY
1038+ pd.id
1039+ ),
1040+ EnrichedCurrentMembers AS (
1041+ SELECT
1042+ pcm.id,
1043+ json_agg(
1044+ json_build_object(
1045+ 'hash', cm.hash,
1046+ 'expirationEpoch', cm.expiration_epoch,
1047+ 'hasScript', cm.has_script,
1048+ 'newExpirationEpoch', (member->>'newExpirationEpoch')::int
1049+ )
1050+ ) AS enriched_members
1051+ FROM
1052+ ProcessedCurrentMembers pcm
1053+ LEFT JOIN json_array_elements(pcm.current_members) AS member ON true
1054+ LEFT JOIN CommitteeData cm
1055+ ON (CASE
1056+ WHEN (member->>'hash') ~ '^[0-9a-fA-F]+$'
1057+ THEN encode(decode(member->>'hash', 'hex'), 'hex')
1058+ ELSE NULL
1059+ END) = cm.hash
1060+ GROUP BY
1061+ pcm.id
1062+ ),
8881063 EpochUtils AS (
8891064 SELECT
8901065 (Max(end_time) - Min(end_time)) /(Max(NO) - Min(NO)) AS epoch_duration,
@@ -923,12 +1098,45 @@ export const fetchProposalById = async (proposalId: string, proposaIndex: number
9231098 when gov_action_proposal.type = 'TreasuryWithdrawals' then
9241099 json_build_object('Reward Address', stake_address.view, 'Amount', treasury_withdrawal.amount)
9251100 when gov_action_proposal.type::text = 'InfoAction' then
926- json_build_object()
1101+ json_build_object('data', gov_action_proposal.description )
9271102 when gov_action_proposal.type::text = 'HardForkInitiation' then
9281103 json_build_object(
9291104 'major', (gov_action_proposal.description->'contents'->1->>'major')::int,
9301105 'minor', (gov_action_proposal.description->'contents'->1->>'minor')::int
9311106 )
1107+ WHEN gov_action_proposal.type::text = 'NoConfidence' THEN
1108+ json_build_object('data', gov_action_proposal.description->'contents')
1109+ WHEN gov_action_proposal.type::text = 'ParameterChange' THEN
1110+ json_build_object('data', gov_action_proposal.description->'contents')
1111+ WHEN gov_action_proposal.type::text = 'NewConstitution' THEN
1112+ json_build_object(
1113+ 'anchor', gov_action_proposal.description->'contents'->1->'anchor',
1114+ 'script', gov_action_proposal.description->'contents'->1->'script'
1115+ )
1116+ WHEN gov_action_proposal.type::text = 'NewCommittee' THEN
1117+ (
1118+ SELECT
1119+ json_build_object(
1120+ 'tag', pd.tag,
1121+ 'members', em.enriched_members,
1122+ 'membersToBeRemoved', mtr.members_to_be_removed,
1123+ 'threshold',
1124+ CASE
1125+ WHEN (pd.threshold->>'numerator') IS NOT NULL
1126+ AND (pd.threshold->>'denominator') IS NOT NULL
1127+ THEN (pd.threshold->>'numerator')::float / (pd.threshold->>'denominator')::float
1128+ ELSE NULL
1129+ END
1130+ )
1131+ FROM
1132+ ParsedDescription pd
1133+ JOIN
1134+ MembersToBeRemoved mtr ON pd.id = mtr.id
1135+ JOIN
1136+ EnrichedCurrentMembers em ON pd.id = em.id
1137+ WHERE
1138+ pd.id = gov_action_proposal.id
1139+ )
9321140 ELSE
9331141 null
9341142 END,
0 commit comments