import {
AuthorizeGovernanceDataSourceTransfer,
CosmosUpgradeContract,
EvmExecute,
EvmSetWormholeAddress,
EvmUpgradeContract,
ExecutePostedVaa,
MultisigParser,
PythGovernanceAction,
RequestGovernanceDataSourceTransfer,
SetDataSources,
SetFee,
SetValidPeriod,
UpgradeContract256Bit,
WormholeMultisigInstruction,
getProgramName,
} from '@pythnetwork/xc-admin-common'
import { AccountMeta, PublicKey } from '@solana/web3.js'
import type { ReactNode } from 'react'
import CopyText from '../common/CopyText'
import { ParsedAccountPubkeyRow, SignerTag, WritableTag } from './AccountUtils'
import { usePythContext } from '../../contexts/PythContext'
import { getMappingCluster, isPubkey } from './utils'
import { PythCluster } from '@pythnetwork/client'
import { lamportsToSol } from '../../utils/lamportsToSol'
import { parseEvmExecuteCallData } from '../../utils/parseEvmExecuteCallData'
const GovernanceInstructionView = ({
instruction,
actionName,
content,
}: {
instruction: PythGovernanceAction
actionName: string
content: ReactNode
}) => {
return (
Action: {actionName}
Chain Id: {instruction.targetChainId}
{content}
Raw payload hex:{' '}
)
}
export const WormholeInstructionView = ({
instruction,
cluster,
}: {
instruction: WormholeMultisigInstruction
cluster: PythCluster
}) => {
const {
priceAccountKeyToSymbolMapping,
productAccountKeyToSymbolMapping,
publisherKeyToNameMapping,
} = usePythContext()
const publisherKeyToNameMappingCluster =
publisherKeyToNameMapping[getMappingCluster(cluster)]
const governanceAction = instruction.governanceAction
return (
Wormhole Instructions
{!governanceAction && (
<>
Unknown message
Raw hex payload:
{(instruction.args.payload as Buffer).toString('hex')}
>
)}
{governanceAction instanceof ExecutePostedVaa &&
governanceAction.instructions.map((innerInstruction, index) => {
const multisigParser = MultisigParser.fromCluster(cluster)
const parsedInstruction = multisigParser.parseInstruction({
programId: innerInstruction.programId,
data: innerInstruction.data as Buffer,
keys: innerInstruction.keys as AccountMeta[],
})
return (
<>
Program
{getProgramName(parsedInstruction.program)}
Instruction Name
{parsedInstruction.name}
Arguments
{Object.keys(parsedInstruction.args).length > 0 ? (
{Object.keys(parsedInstruction.args).map((key, index) => (
<>
{key === 'lamports' &&
typeof parsedInstruction.args[key] === 'bigint' ? (
<>
{'◎'}
{lamportsToSol(parsedInstruction.args[key])}
>
) : (
<>
{key}
{parsedInstruction.args[key] instanceof
PublicKey ? (
) : typeof instruction.args[key] === 'string' &&
isPubkey(instruction.args[key]) ? (
) : (
{typeof parsedInstruction.args[key] ===
'string'
? parsedInstruction.args[key]
: parsedInstruction.args[key] instanceof
Uint8Array
? parsedInstruction.args[key].toString()
: typeof parsedInstruction.args[key] ===
'bigint'
? parsedInstruction.args[key].toString()
: JSON.stringify(
parsedInstruction.args[key]
)}
)}
>
)}
{key === 'pub' &&
parsedInstruction.args[key].toBase58() in
publisherKeyToNameMappingCluster ? (
) : null}
>
))}
) : (
No arguments
)}
{
Accounts
{Object.keys(parsedInstruction.accounts.named).length > 0 ? (
{Object.keys(parsedInstruction.accounts.named).map(
(key, index) => (
<>
{key}
{parsedInstruction.accounts.named[key]
.isSigner ? (
) : null}
{parsedInstruction.accounts.named[key]
.isWritable ? (
) : null}
{key === 'priceAccount' &&
parsedInstruction.accounts.named[
key
].pubkey.toBase58() in
priceAccountKeyToSymbolMapping ? (
) : key === 'productAccount' &&
parsedInstruction.accounts.named[
key
].pubkey.toBase58() in
productAccountKeyToSymbolMapping ? (
) : null}
>
)
)}
{parsedInstruction.accounts.remaining.map(
(accountMeta, index) => (
<>
Remaining {index + 1}
{accountMeta.isSigner ? : null}
{accountMeta.isWritable ? (
) : null}
>
)
)}
) : (
No accounts
)}
}
>
)
})}
{governanceAction instanceof EvmUpgradeContract && (
Address:
}
/>
)}
{governanceAction instanceof CosmosUpgradeContract && (
Code id:{governanceAction.codeId.toString()}}
/>
)}
{governanceAction instanceof UpgradeContract256Bit && (
Package hash:
}
/>
)}
{governanceAction instanceof SetFee && (
New Fee Value: {governanceAction.newFeeValue.toString()}
New Fee Expo: {governanceAction.newFeeExpo.toString()}
>
}
/>
)}
{governanceAction instanceof SetDataSources && (
{governanceAction.dataSources.map((dataSource, idx) => (
Datasource #{idx + 1}:
- Emitter Chain: {dataSource.emitterChain}
-
Emitter Address:{' '}
))}
>
}
/>
)}
{governanceAction instanceof EvmSetWormholeAddress && (
New Wormhole Address:
}
/>
)}
{governanceAction instanceof SetValidPeriod && (
New Valid Period: {governanceAction.newValidPeriod.toString()}
}
/>
)}
{governanceAction instanceof RequestGovernanceDataSourceTransfer && (
Governance Data Source Index:{' '}
{governanceAction.governanceDataSourceIndex}
}
/>
)}
{governanceAction instanceof AuthorizeGovernanceDataSourceTransfer && (
Claim Vaa hex:{' '}
}
/>
)}
{governanceAction instanceof EvmExecute && (
Executor Address:{' '}
Call Address:{' '}
Value: {governanceAction.value.toString()}
}
/>
)}
)
}
function EvmExecuteCallData({ calldata }: { calldata: Buffer }) {
const callDataHex = calldata.toString('hex')
const parsedData = parseEvmExecuteCallData(callDataHex)
if (parsedData === undefined)
return (
Call Data:
)
return (
<>
Call Method: {parsedData.method}
Call Params:
{parsedData.inputs.length > 0 ? (
parsedData.inputs.map(([key, value]) => (
{key}: {value}
))
) : (
No params
)}
>
)
}