@@ -20,24 +20,71 @@ const client = createPublicClient({
2020 transport : http ( ) ,
2121} ) ;
2222
23- const proof : {
23+ type ProofCase = {
24+ label : string ;
2425 steward : Address ;
2526 governor : Address ;
2627 requestId : bigint ;
2728 proposalId : bigint ;
29+ expectedSupport : number ;
30+ expectedReason : string ;
2831 proposal : string ;
2932 criteria : string ;
33+ proposalTx : `0x${string } `;
3034 requestTx : `0x${string } `;
3135 callbackTx : `0x${string } `;
32- } = {
36+ } ;
37+
38+ const proofCases : ProofCase [ ] = [
39+ {
40+ label : "YES proof" ,
41+ steward : "0x6932C7827E7BFd9f0015Ed93fA120379E0d20541" ,
42+ governor : "0xa3773Ff7B2008bAb2E553E13e1E0ADE08a15f389" ,
43+ requestId : 1698384n ,
44+ proposalId : 1n ,
45+ expectedSupport : 1 ,
46+ expectedReason : "YES" ,
47+ proposal : "Allocate 500K USDC to a Q3 community grants program." ,
48+ criteria : "Vote YES for community grants under 1M, NO for team token unlocks, ABSTAIN if unclear." ,
49+ proposalTx : "0xb31236f41cab27998bbf5593a1fbd8eda3f330eaf1c4b6b34523e5161d30852b" ,
50+ requestTx : "0x63c34767e59cc6988fd2ab5ecef9d1089e9f4445e1b1e18a9b490b0d0efc77ef" ,
51+ callbackTx : "0xb74e25845472a2f591aa91eefe84e5e2828b41ac11acc78b41ceb1015500c52b" ,
52+ } ,
53+ {
54+ label : "NO proof" ,
55+ steward : "0x6932C7827E7BFd9f0015Ed93fA120379E0d20541" ,
56+ governor : "0xa3773Ff7B2008bAb2E553E13e1E0ADE08a15f389" ,
57+ requestId : 1738101n ,
58+ proposalId : 2n ,
59+ expectedSupport : 2 ,
60+ expectedReason : "NO" ,
61+ proposal : "Unlock 10% of foundation team tokens early." ,
62+ criteria : "Vote YES for community grants under 1M, NO for team token unlocks, ABSTAIN if unclear." ,
63+ proposalTx : "0xebc1961f3aa23078bb1d54e99d61fc4e8647caae1bae5e4e9f4ec48f2df53b3d" ,
64+ requestTx : "0x6d32b090d9ebacc6dd1dd46c01e0036bff3e684df4a28d3817823cd3747959fc" ,
65+ callbackTx : "0xe14303e64f6a5db3d74919c94f42d3c14df3183e225f9996cc29cba86cc66dc3" ,
66+ } ,
67+ {
68+ label : "ABSTAIN proof" ,
69+ steward : "0x6932C7827E7BFd9f0015Ed93fA120379E0d20541" ,
70+ governor : "0xa3773Ff7B2008bAb2E553E13e1E0ADE08a15f389" ,
71+ requestId : 1738108n ,
72+ proposalId : 3n ,
73+ expectedSupport : 3 ,
74+ expectedReason : "ABSTAIN" ,
75+ proposal : "Form a working group to explore future ecosystem partnerships without committing funds." ,
76+ criteria : "Vote YES for community grants under 1M, NO for team token unlocks, ABSTAIN if unclear." ,
77+ proposalTx : "0x758f8dbc8cadf4887b301e33ab55c068ad983a4d507bd6cb9c5caa48b7060e53" ,
78+ requestTx : "0xa01f30ee06dbfa66b4a60414469d4f0e6406440f11e625a1197de88d797e851d" ,
79+ callbackTx : "0xa157564585f473503627c801d6fb5992900dab3d5efcb31d4f15383c16487603" ,
80+ } ,
81+ ] ;
82+
83+ const primaryProof = proofCases [ 0 ] ;
84+
85+ const proofAddresses = {
3386 steward : "0x6932C7827E7BFd9f0015Ed93fA120379E0d20541" ,
3487 governor : "0xa3773Ff7B2008bAb2E553E13e1E0ADE08a15f389" ,
35- requestId : 1698384n ,
36- proposalId : 1n ,
37- proposal : "Allocate 500K USDC to a Q3 community grants program." ,
38- criteria : "Vote YES for community grants under 1M, NO for team token unlocks, ABSTAIN if unclear." ,
39- requestTx : "0x63c34767e59cc6988fd2ab5ecef9d1089e9f4445e1b1e18a9b490b0d0efc77ef" ,
40- callbackTx : "0xb74e25845472a2f591aa91eefe84e5e2828b41ac11acc78b41ceb1015500c52b" ,
4188} ;
4289
4390const stewardAbi = [
@@ -73,12 +120,14 @@ const governorAbi = [
73120
74121type ProofState = {
75122 loading : boolean ;
76- state ?: number ;
77- platformStatus ?: number ;
78- support ?: number ;
79- reason ?: string ;
80- receipt ?: bigint ;
81- governorVote ?: number ;
123+ proofs ?: Record < string , {
124+ state : number ;
125+ platformStatus : number ;
126+ support : number ;
127+ reason : string ;
128+ receipt : bigint ;
129+ governorVote : number ;
130+ } > ;
82131 error ?: string ;
83132} ;
84133
@@ -90,6 +139,13 @@ function shortAddress(value: string) {
90139 return `${ value . slice ( 0 , 6 ) } ...${ value . slice ( - 4 ) } ` ;
91140}
92141
142+ function supportLabel ( support ?: number ) {
143+ if ( support === 1 ) return "YES" ;
144+ if ( support === 2 ) return "NO" ;
145+ if ( support === 3 ) return "ABSTAIN" ;
146+ return "PENDING" ;
147+ }
148+
93149function App ( ) {
94150 const [ live , setLive ] = useState < ProofState > ( { loading : true } ) ;
95151
@@ -98,29 +154,39 @@ function App() {
98154
99155 async function load ( ) {
100156 try {
101- const voteRequest = await client . readContract ( {
102- address : proof . steward ,
103- abi : stewardAbi ,
104- functionName : "voteRequests" ,
105- args : [ proof . requestId ] ,
106- } ) ;
107- const governorVote = await client . readContract ( {
108- address : proof . governor ,
109- abi : governorAbi ,
110- functionName : "votes" ,
111- args : [ proof . proposalId , proof . steward ] ,
112- } ) ;
157+ const entries = await Promise . all (
158+ proofCases . map ( async ( proof ) => {
159+ const voteRequest = await client . readContract ( {
160+ address : proof . steward ,
161+ abi : stewardAbi ,
162+ functionName : "voteRequests" ,
163+ args : [ proof . requestId ] ,
164+ } ) ;
165+ const governorVote = await client . readContract ( {
166+ address : proof . governor ,
167+ abi : governorAbi ,
168+ functionName : "votes" ,
169+ args : [ proof . proposalId , proof . steward ] ,
170+ } ) ;
171+ return [
172+ proof . label ,
173+ {
174+ state : voteRequest [ 2 ] ,
175+ platformStatus : voteRequest [ 3 ] ,
176+ support : voteRequest [ 4 ] ,
177+ reason : voteRequest [ 5 ] ,
178+ receipt : voteRequest [ 6 ] ,
179+ governorVote,
180+ } ,
181+ ] as const ;
182+ } ) ,
183+ ) ;
113184
114185 if ( ! active ) return ;
115186
116187 setLive ( {
117188 loading : false ,
118- state : voteRequest [ 2 ] ,
119- platformStatus : voteRequest [ 3 ] ,
120- support : voteRequest [ 4 ] ,
121- reason : voteRequest [ 5 ] ,
122- receipt : voteRequest [ 6 ] ,
123- governorVote,
189+ proofs : Object . fromEntries ( entries ) ,
124190 } ) ;
125191 } catch ( error ) {
126192 if ( ! active ) return ;
@@ -139,7 +205,10 @@ function App() {
139205 } ;
140206 } , [ ] ) ;
141207
142- const cast = live . state === 2 && live . support === 1 && live . governorVote === 1 ;
208+ const allCast = proofCases . every ( ( proof ) => {
209+ const state = live . proofs ?. [ proof . label ] ;
210+ return state ?. state === 2 && state . support === proof . expectedSupport && state . governorVote === proof . expectedSupport ;
211+ } ) ;
143212
144213 return (
145214 < main >
@@ -161,31 +230,51 @@ function App() {
161230 reasons against the mandate, and casts a DAO vote onchain through an async callback.
162231 </ p >
163232 < div className = "actions" >
164- < a href = { explorerTx ( proof . callbackTx ) } target = "_blank" rel = "noreferrer" >
165- Open vote tx
233+ < a href = { explorerTx ( primaryProof . callbackTx ) } target = "_blank" rel = "noreferrer" >
234+ Open YES vote tx
166235 </ a >
167- < a className = "secondary" href = { explorerTx ( proof . requestTx ) } target = "_blank" rel = "noreferrer ">
168- Open request tx
236+ < a className = "secondary" href = "#proof ">
237+ View all outcomes
169238 </ a >
170239 </ div >
171240 </ div >
172241
173242 < div className = "receipt" id = "proof" >
174243 < div className = "receiptTop" >
175244 < span > Onchain vote proof</ span >
176- < strong > { live . loading ? "reading..." : cast ? "VOTED YES" : "CHECK STATE" } </ strong >
245+ < strong > { live . loading ? "reading..." : allCast ? "YES · NO · ABSTAIN " : "CHECK STATE" } </ strong >
177246 </ div >
178- < div className = "proposal" >
179- < span > Proposal</ span >
180- < p > { proof . proposal } </ p >
247+ < div className = "decisionDeck" >
248+ { proofCases . map ( ( proof ) => {
249+ const state = live . proofs ?. [ proof . label ] ;
250+ const label = supportLabel ( state ?. support ) ;
251+ const verified = state ?. state === 2 && state . support === proof . expectedSupport ;
252+ return (
253+ < article className = { `voteCard ${ label . toLowerCase ( ) } ` } key = { proof . label } >
254+ < div >
255+ < span > { proof . label } </ span >
256+ < strong > { live . loading ? "..." : label } </ strong >
257+ </ div >
258+ < p > { proof . proposal } </ p >
259+ < small > { verified ? "Cast by Steward" : "Waiting for matching proof" } </ small >
260+ < div className = "txLinks" >
261+ < a href = { explorerTx ( proof . proposalTx ) } target = "_blank" rel = "noreferrer" >
262+ Proposal
263+ </ a >
264+ < a href = { explorerTx ( proof . requestTx ) } target = "_blank" rel = "noreferrer" >
265+ Request
266+ </ a >
267+ < a href = { explorerTx ( proof . callbackTx ) } target = "_blank" rel = "noreferrer" >
268+ Vote
269+ </ a >
270+ </ div >
271+ </ article >
272+ ) ;
273+ } ) }
181274 </ div >
182275 < div className = "criteria" >
183276 < span > Delegated criteria</ span >
184- < p > { proof . criteria } </ p >
185- </ div >
186- < div className = "decision" >
187- < span > Somnia Agent output</ span >
188- < strong > { live . loading ? "..." : live . reason ?? "unavailable" } </ strong >
277+ < p > { primaryProof . criteria } </ p >
189278 </ div >
190279 </ div >
191280 </ section >
@@ -216,19 +305,19 @@ function App() {
216305 < section className = "live" >
217306 < div >
218307 < span > Steward</ span >
219- < strong > { shortAddress ( proof . steward ) } </ strong >
308+ < strong > { shortAddress ( proofAddresses . steward ) } </ strong >
220309 </ div >
221310 < div >
222- < span > Request ID </ span >
223- < strong > { proof . requestId . toString ( ) } </ strong >
311+ < span > Request IDs </ span >
312+ < strong > 1698384 / 1738101 / 1738108 </ strong >
224313 </ div >
225314 < div >
226- < span > Request state </ span >
227- < strong > { live . loading ? "..." : live . state } </ strong >
315+ < span > Request states </ span >
316+ < strong > { live . loading ? "..." : allCast ? "Cast x3" : "Check" } </ strong >
228317 </ div >
229318 < div >
230- < span > Governor vote </ span >
231- < strong > { live . loading ? "..." : live . governorVote } </ strong >
319+ < span > Governor votes </ span >
320+ < strong > { live . loading ? "..." : allCast ? "1 / 2 / 3" : "Check" } </ strong >
232321 </ div >
233322 </ section >
234323
0 commit comments