11import { BN , Wallet } from '@coral-xyz/anchor'
2- import { PythCluster } from '@pythnetwork/client/lib/cluster '
2+ import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes '
33import { useAnchorWallet } from '@solana/wallet-adapter-react'
4- import { AccountMeta } from '@solana/web3.js'
4+ import { AccountMeta , PublicKey } from '@solana/web3.js'
55import { getIxPDA } from '@sqds/mesh'
66import { MultisigAccount , TransactionAccount } from '@sqds/mesh/lib/types'
77import copy from 'copy-to-clipboard'
@@ -15,9 +15,12 @@ import {
1515 useState ,
1616} from 'react'
1717import {
18+ getMultisigCluster ,
1819 getProposals ,
20+ MultisigInstruction ,
1921 MultisigParser ,
2022 PythMultisigInstruction ,
23+ UnrecognizedProgram ,
2124 WormholeMultisigInstruction ,
2225} from 'xc_admin_common'
2326import { ClusterContext } from '../../contexts/ClusterContext'
@@ -105,15 +108,17 @@ const Proposal = ({
105108 multisig : any
106109} ) => {
107110 const [ proposalInstructions , setProposalInstructions ] = useState <
108- ( PythMultisigInstruction | WormholeMultisigInstruction ) [ ]
111+ MultisigInstruction [ ]
109112 > ( [ ] )
110113 const { cluster } = useContext ( ClusterContext )
111114 const anchorWallet = useAnchorWallet ( )
112115 const { squads } = useMultisig ( anchorWallet as Wallet )
113116
114117 useEffect ( ( ) => {
115118 const fetchProposalInstructions = async ( ) => {
116- const multisigParser = MultisigParser . fromCluster ( cluster as PythCluster )
119+ const multisigParser = MultisigParser . fromCluster (
120+ getMultisigCluster ( cluster )
121+ )
117122 if ( squads ) {
118123 const proposalIxs = [ ]
119124 for ( let i = 1 ; i <= proposal . instructionIndex ; i ++ ) {
@@ -128,12 +133,8 @@ const Proposal = ({
128133 data : instruction . data as Buffer ,
129134 keys : instruction . keys as AccountMeta [ ] ,
130135 } )
131- if (
132- parsedInstruction instanceof PythMultisigInstruction ||
133- parsedInstruction instanceof WormholeMultisigInstruction
134- ) {
135- proposalIxs . push ( parsedInstruction )
136- }
136+
137+ proposalIxs . push ( parsedInstruction )
137138 }
138139 setProposalInstructions ( proposalIxs )
139140 }
@@ -185,89 +186,169 @@ const Proposal = ({
185186 < hr className = "border-gray-700" />
186187 { proposalInstructions ?. map ( ( instruction , index ) => (
187188 < >
188- < div key = { index } className = "flex justify-between" >
189+ < div key = { ` ${ index } _instruction` } className = "flex justify-between" >
189190 < div > Instruction</ div >
190- < div > { instruction . name } </ div >
191+ < div >
192+ { instruction instanceof PythMultisigInstruction ||
193+ instruction instanceof WormholeMultisigInstruction
194+ ? instruction . name
195+ : 'Unknown' }
196+ </ div >
191197 </ div >
192- < div key = { index } className = "grid grid-cols-4 justify-between" >
198+ < div
199+ key = { `${ index } _arguments` }
200+ className = "grid grid-cols-4 justify-between"
201+ >
193202 < div > Arguments</ div >
194- { Object . keys ( instruction . args ) . length > 0 ? (
195- < div className = "col-span-4 mt-2 bg-darkGray2 p-4 lg:col-span-3 lg:mt-0" >
196- < div className = "base16 flex justify-between pt-2 pb-6 font-semibold opacity-60" >
197- < div > Key</ div >
198- < div > Value</ div >
199- </ div >
200- { Object . keys ( instruction . args ) . map ( ( key , index ) => (
201- < div
202- key = { index }
203- className = "flex justify-between border-t border-beige-300 py-3"
204- >
205- < div > { key } </ div >
206- < div > { instruction . args [ key ] } </ div >
203+ { instruction instanceof PythMultisigInstruction ||
204+ instruction instanceof WormholeMultisigInstruction ? (
205+ Object . keys ( instruction . args ) . length > 0 ? (
206+ < div className = "col-span-4 mt-2 bg-darkGray2 p-4 lg:col-span-3 lg:mt-0" >
207+ < div className = "base16 flex justify-between pt-2 pb-6 font-semibold opacity-60" >
208+ < div > Key</ div >
209+ < div > Value</ div >
207210 </ div >
208- ) ) }
209- </ div >
210- ) : (
211- < div className = "col-span-3 text-right" > No arguments</ div >
212- ) }
213- </ div >
214- < div key = { index } className = "grid grid-cols-4 justify-between" >
215- < div > Accounts</ div >
216- { Object . keys ( instruction . accounts . named ) . length > 0 ? (
217- < div className = "col-span-4 mt-2 bg-darkGray2 p-4 lg:col-span-3 lg:mt-0" >
218- < div className = "base16 flex justify-between pt-2 pb-6 font-semibold opacity-60" >
219- < div > Account</ div >
220- < div > Pubkey</ div >
221- </ div >
222- { Object . keys ( instruction . accounts . named ) . map ( ( key , index ) => (
223- < >
211+ { Object . keys ( instruction . args ) . map ( ( key , index ) => (
224212 < div
225213 key = { index }
226214 className = "flex justify-between border-t border-beige-300 py-3"
227215 >
228216 < div > { key } </ div >
229- < div className = "flex space-x-2" >
230- { instruction . accounts . named [ key ] . isSigner ? (
231- < SignerTag />
232- ) : null }
233- { instruction . accounts . named [ key ] . isWritable ? (
234- < WritableTag />
235- ) : null }
236- < div
237- className = "-ml-1 inline-flex cursor-pointer items-center px-1 hover:bg-dark hover:text-white active:bg-darkGray3"
238- onClick = { ( ) => {
239- copy (
240- instruction . accounts . named [
241- key
242- ] . pubkey . toBase58 ( )
243- )
244- } }
245- >
246- < span className = "mr-2 hidden xl:block" >
247- { instruction . accounts . named [
248- key
249- ] . pubkey . toBase58 ( ) }
250- </ span >
251- < span className = "mr-2 xl:hidden" >
252- { instruction . accounts . named [ key ] . pubkey
253- . toBase58 ( )
254- . slice ( 0 , 6 ) +
255- '...' +
256- instruction . accounts . named [ key ] . pubkey
257- . toBase58 ( )
258- . slice ( - 6 ) }
259- </ span > { ' ' }
260- < CopyIcon className = "shrink-0" />
261- </ div >
217+ < div >
218+ { instruction . args [ key ] instanceof PublicKey
219+ ? instruction . args [ key ] . toBase58 ( )
220+ : typeof instruction . args [ key ] === 'string'
221+ ? instruction . args [ key ]
222+ : JSON . stringify ( instruction . args [ key ] ) }
262223 </ div >
263224 </ div >
264- </ >
265- ) ) }
266- </ div >
225+ ) ) }
226+ </ div >
227+ ) : (
228+ < div className = "col-span-3 text-right" > No arguments</ div >
229+ )
267230 ) : (
268- < div > No arguments </ div >
231+ < div className = "col-span-3 text-right" > Unknown </ div >
269232 ) }
270233 </ div >
234+ { instruction instanceof PythMultisigInstruction ||
235+ instruction instanceof WormholeMultisigInstruction ? (
236+ < div
237+ key = { `${ index } _accounts` }
238+ className = "grid grid-cols-4 justify-between"
239+ >
240+ < div > Accounts</ div >
241+ { Object . keys ( instruction . accounts . named ) . length > 0 ? (
242+ < div className = "col-span-4 mt-2 bg-darkGray2 p-4 lg:col-span-3 lg:mt-0" >
243+ < div className = "base16 flex justify-between pt-2 pb-6 font-semibold opacity-60" >
244+ < div > Account</ div >
245+ < div > Pubkey</ div >
246+ </ div >
247+ { Object . keys ( instruction . accounts . named ) . map (
248+ ( key , index ) => (
249+ < >
250+ < div
251+ key = { index }
252+ className = "flex justify-between border-t border-beige-300 py-3"
253+ >
254+ < div > { key } </ div >
255+ < div className = "flex space-x-2" >
256+ { instruction . accounts . named [ key ] . isSigner ? (
257+ < SignerTag />
258+ ) : null }
259+ { instruction . accounts . named [ key ] . isWritable ? (
260+ < WritableTag />
261+ ) : null }
262+ < div
263+ className = "-ml-1 inline-flex cursor-pointer items-center px-1 hover:bg-dark hover:text-white active:bg-darkGray3"
264+ onClick = { ( ) => {
265+ copy (
266+ instruction . accounts . named [
267+ key
268+ ] . pubkey . toBase58 ( )
269+ )
270+ } }
271+ >
272+ < span className = "mr-2 hidden xl:block" >
273+ { instruction . accounts . named [
274+ key
275+ ] . pubkey . toBase58 ( ) }
276+ </ span >
277+ < span className = "mr-2 xl:hidden" >
278+ { instruction . accounts . named [ key ] . pubkey
279+ . toBase58 ( )
280+ . slice ( 0 , 6 ) +
281+ '...' +
282+ instruction . accounts . named [ key ] . pubkey
283+ . toBase58 ( )
284+ . slice ( - 6 ) }
285+ </ span > { ' ' }
286+ < CopyIcon className = "shrink-0" />
287+ </ div >
288+ </ div >
289+ </ div >
290+ </ >
291+ )
292+ ) }
293+ </ div >
294+ ) : (
295+ < div > No arguments</ div >
296+ ) }
297+ </ div >
298+ ) : instruction instanceof UnrecognizedProgram ? (
299+ < >
300+ < div key = { `${ index } _data` } className = "flex justify-between" >
301+ < div > Data</ div >
302+ < div >
303+ { instruction . instruction . data . length > 0
304+ ? bs58 . encode ( instruction . instruction . data )
305+ : 'No data' }
306+ </ div >
307+ </ div >
308+ < div
309+ key = { `${ index } _keys` }
310+ className = "grid grid-cols-4 justify-between"
311+ >
312+ < div > Keys</ div >
313+ < div className = "col-span-4 mt-2 bg-darkGray2 p-4 lg:col-span-3 lg:mt-0" >
314+ < div className = "base16 flex justify-between pt-2 pb-6 font-semibold opacity-60" >
315+ < div > Key #</ div >
316+ < div > Pubkey</ div >
317+ </ div >
318+ { instruction . instruction . keys . map ( ( key , index ) => (
319+ < >
320+ < div
321+ key = { index }
322+ className = "flex justify-between border-t border-beige-300 py-3"
323+ >
324+ < div > Key { index + 1 } </ div >
325+ < div className = "flex space-x-2" >
326+ { key . isSigner ? < SignerTag /> : null }
327+ { key . isWritable ? < WritableTag /> : null }
328+ < div
329+ className = "-ml-1 inline-flex cursor-pointer items-center px-1 hover:bg-dark hover:text-white active:bg-darkGray3"
330+ onClick = { ( ) => {
331+ copy ( key . pubkey . toBase58 ( ) )
332+ } }
333+ >
334+ < span className = "mr-2 hidden xl:block" >
335+ { key . pubkey . toBase58 ( ) }
336+ </ span >
337+ < span className = "mr-2 xl:hidden" >
338+ { key . pubkey . toBase58 ( ) . slice ( 0 , 6 ) +
339+ '...' +
340+ key . pubkey . toBase58 ( ) . slice ( - 6 ) }
341+ </ span > { ' ' }
342+ < CopyIcon className = "shrink-0" />
343+ </ div >
344+ </ div >
345+ </ div >
346+ </ >
347+ ) ) }
348+ </ div >
349+ </ div >
350+ </ >
351+ ) : null }
271352 { index !== proposalInstructions . length - 1 ? (
272353 < hr className = "border-gray-700" />
273354 ) : null }
@@ -325,6 +406,8 @@ const Proposals = () => {
325406 ( a , b ) => b . transactionIndex - a . transactionIndex
326407 )
327408 )
409+ } else {
410+ setProposals ( [ ] )
328411 }
329412 }
330413 setDataIsLoading ( false )
@@ -390,14 +473,14 @@ const Proposals = () => {
390473 className = "max-w-fit cursor-pointer bg-darkGray2 p-3 text-xs font-semibold outline-none transition-colors hover:bg-darkGray3 md:text-base"
391474 onClick = { handleClickBackToPriceFeeds }
392475 >
393- ← back to price feeds
476+ ← back to proposals
394477 </ div >
395478 { currentProposal ? (
396479 < div className = "relative mt-6" >
397480 < Proposal proposal = { currentProposal } multisig = { multisig } />
398481 </ div >
399482 ) : (
400- < div className = "mt-3 " >
483+ < div className = "mt-6 " >
401484 < Loadbar theme = "light" />
402485 </ div >
403486 ) }
0 commit comments