Skip to content

Commit

Permalink
update xc-admin-frontend to show eclipse_mainnet proposals
Browse files Browse the repository at this point in the history
  • Loading branch information
cctdaniel committed Aug 6, 2024
1 parent e73fff2 commit 0fc9148
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pythnet = []
pythtest = []
eclipse_devnet = []
eclipse_testnet = []
eclipse_mainnet = []

[dependencies]
anchor-lang = {version = "0.25.0", features = ["init-if-needed"]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub const CHAIN_ID_ARRAY: &[(&str, u16)] = &[
("pythtest", 26),
("eclipse_devnet", 40001),
("eclipse_testnet", 40002),
("eclipse_mainnet", 40003),
];

#[cfg(any(feature = "pythnet", feature = "pythtest"))]
Expand All @@ -30,6 +31,9 @@ pub const CHAIN_ID: u16 = 40001;
#[cfg(feature = "eclipse_testnet")]
pub const CHAIN_ID: u16 = 40002;

#[cfg(feature = "eclipse_mainnet")]
pub const CHAIN_ID: u16 = 40003;

#[derive(AnchorDeserialize, AnchorSerialize, Debug, PartialEq, Eq)]
pub struct ExecutorPayload {
pub header: GovernanceHeader,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl Owner for AnchorVaa {
Pubkey::from_str("EUrRARh92Cdc54xrDn6qzaqjA77NRrCcfbr8kPwoTL4z").unwrap()
}

#[cfg(any(feature = "eclipse_devnet", feature = "eclipse_testnet"))]
#[cfg(any(feature = "eclipse_devnet", feature = "eclipse_testnet", feature = "eclipse_mainnet"))]
fn owner() -> Pubkey {
Pubkey::from_str("HDwcJBJXjL9FpJ7UBsYBtaDjsBUhuLCUYoz3zr8SWWaQ").unwrap()
}
Expand Down
5 changes: 3 additions & 2 deletions governance/xc_admin/packages/xc_admin_cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
MultisigParser,
MultisigVault,
PROGRAM_AUTHORITY_ESCROW,
SvmCluster,
getMultisigCluster,
getProposalInstructions,
} from "@pythnetwork/xc-admin-common";
Expand Down Expand Up @@ -69,7 +70,7 @@ async function loadVaultFromOptions(options: any): Promise<MultisigVault> {
options.ledgerDerivationChange
);
// This is the cluster where we want to perform the action
const cluster: PythCluster = options.cluster;
const cluster: SvmCluster = options.cluster;
// This is the cluster where the multisig lives that can perform actions on ^
const multisigCluster = getMultisigCluster(cluster);
const vault: PublicKey = new PublicKey(options.vault);
Expand Down Expand Up @@ -171,7 +172,7 @@ multisigCommand(
"Accept governance authority transfer for the solana receiver program"
).action(async (options: any) => {
const vault = await loadVaultFromOptions(options);
const targetCluster: PythCluster = options.cluster;
const targetCluster: SvmCluster = options.cluster;

const programSolanaReceiver = new Program(
pythSolanaReceiverIdl,
Expand Down
5 changes: 5 additions & 0 deletions governance/xc_admin/packages/xc_admin_common/src/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ export const RECEIVER_CHAINS = {
arbitrum: 23,
optimism: 24,

// SVM chains
eclipse_devnet: 40001,
eclipse_testnet: 40002,
eclipse_mainnet: 40003,

cronos: 60001,
kcc: 60002,
zksync: 60003,
Expand Down
6 changes: 5 additions & 1 deletion governance/xc_admin/packages/xc_admin_common/src/cluster.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { PythCluster } from "@pythnetwork/client/lib/cluster";
import { Cluster } from "@solana/web3.js";

export type NonPythnetSvmCluster = "eclipse_mainnet";
export type SvmCluster = PythCluster | NonPythnetSvmCluster;

/**
* Return whether the cluster is governed remotely or not. For example Pythnet is governed remotely by a mainnet multisig.
*/
Expand All @@ -15,9 +18,10 @@ export function isRemoteCluster(cluster: PythCluster) {
/**
* For cluster that are governed remotely (ex : Pythnet from Mainnet) return the network where the multisig lives
*/
export function getMultisigCluster(cluster: PythCluster): Cluster | "localnet" {
export function getMultisigCluster(cluster: SvmCluster): Cluster | "localnet" {
switch (cluster) {
case "pythnet":
case "eclipse_mainnet":
return "mainnet-beta";
case "pythtest-conformance":
return "devnet";
Expand Down
19 changes: 13 additions & 6 deletions governance/xc_admin/packages/xc_admin_common/src/propose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import {
PriorityFeeConfig,
} from "@pythnetwork/solana-utils";
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
import { SvmCluster } from "./cluster";
import { ChainName } from "./chains";

export const MAX_EXECUTOR_PAYLOAD_SIZE =
PACKET_DATA_SIZE_WITH_ROOM_FOR_COMPUTE_BUDGET - 687; // Bigger payloads won't fit in one addInstruction call when adding to the proposal
Expand Down Expand Up @@ -84,9 +86,9 @@ export class MultisigVault {
* is the PDA of the remote executor program representing the vault's Wormhole emitter address.
* @param cluster
*/
public async getVaultAuthorityPDA(cluster?: PythCluster): Promise<PublicKey> {
public async getVaultAuthorityPDA(cluster?: SvmCluster): Promise<PublicKey> {
const msAccount = await this.getMultisigAccount();
const localAuthorityPDA = await this.squad.getAuthorityPDA(
const localAuthorityPDA = this.squad.getAuthorityPDA(
msAccount.publicKey,
msAccount.authorityIndex
);
Expand Down Expand Up @@ -288,7 +290,7 @@ export class MultisigVault {
*/
public async proposeInstructions(
instructions: TransactionInstruction[],
targetCluster: PythCluster,
targetCluster: SvmCluster,
priorityFeeConfig: PriorityFeeConfig = {}
): Promise<PublicKey[]> {
const msAccount = await this.getMultisigAccount();
Expand Down Expand Up @@ -321,7 +323,8 @@ export class MultisigVault {
newProposalAddress,
batch,
i + 1,
this.wormholeAddress()!
this.wormholeAddress()!,
targetCluster
);
ixToSend.push(
await this.squad.buildAddInstruction(
Expand Down Expand Up @@ -473,9 +476,13 @@ export async function wrapAsRemoteInstruction(
proposalAddress: PublicKey,
instructions: TransactionInstruction[],
instructionIndex: number,
wormholeAddress: PublicKey
wormholeAddress: PublicKey,
targetCluster: SvmCluster
): Promise<SquadInstruction> {
const buffer: Buffer = new ExecutePostedVaa("pythnet", instructions).encode();
const buffer: Buffer = new ExecutePostedVaa(
targetCluster as ChainName,
instructions
).encode();
return await getPostMessageInstruction(
squad,
vault,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
MultisigInstruction,
MultisigParser,
PythMultisigInstruction,
SvmCluster,
WormholeMultisigInstruction,
getManyProposalsInstructions,
getMultisigCluster,
Expand All @@ -37,11 +38,16 @@ import Spinner from '../../common/Spinner'
import Loadbar from '../../loaders/Loadbar'

import { Wallet } from '@coral-xyz/anchor'
import { PythCluster, getPythProgramKeyForCluster } from '@pythnetwork/client'
import { getPythProgramKeyForCluster } from '@pythnetwork/client'
import { TransactionBuilder, sendTransactions } from '@pythnetwork/solana-utils'
import { getMappingCluster, isPubkey } from '../../InstructionViews/utils'
import { StatusTag } from './StatusTag'
import { getProposalStatus } from './utils'
import {
getProposalStatus,
getPythnetCluster,
isSolanaPullProgram,
isSvmChainId,
} from './utils'

import VerifiedIcon from '@images/icons/verified.inline.svg'
import VotedIcon from '@images/icons/voted.inline.svg'
Expand Down Expand Up @@ -140,25 +146,30 @@ export const Proposal = ({
const [isTransactionLoading, setIsTransactionLoading] = useState(false)
const { cluster: contextCluster } = useContext(ClusterContext)
const multisigCluster = getMultisigCluster(contextCluster)
const targetClusters: (PythCluster | 'unknown')[] = []
const targetClusters: (SvmCluster | 'unknown')[] = []
instructions.map((ix) => {
if (!(ix instanceof WormholeMultisigInstruction)) {
targetClusters.push(multisigCluster)
} else if (
ix instanceof WormholeMultisigInstruction &&
ix.governanceAction instanceof ExecutePostedVaa
) {
ix.governanceAction.instructions.map((ix) => {
const remoteClusters: PythCluster[] = [
ix.governanceAction.instructions.map((innerIx) => {
const remoteClusters: SvmCluster[] = [
'pythnet',
'pythtest-conformance',
'pythtest-crosschain',
'eclipse_mainnet',
]
for (const remoteCluster of remoteClusters) {
if (
multisigCluster === getMultisigCluster(remoteCluster) &&
(ix.programId.equals(getPythProgramKeyForCluster(remoteCluster)) ||
ix.programId.equals(SystemProgram.programId))
ix.governanceAction?.targetChainId === remoteCluster &&
(innerIx.programId.equals(
getPythProgramKeyForCluster(getPythnetCluster(remoteCluster))
) ||
innerIx.programId.equals(SystemProgram.programId) ||
isSolanaPullProgram(innerIx.programId))
) {
targetClusters.push(remoteCluster)
}
Expand Down Expand Up @@ -203,7 +214,10 @@ export const Proposal = ({
ix.name === 'postMessage' &&
ix.governanceAction instanceof ExecutePostedVaa &&
ix.governanceAction.instructions.every((remoteIx) => {
const innerMultisigParser = MultisigParser.fromCluster(cluster)
console.log(getPythnetCluster(cluster))
const innerMultisigParser = MultisigParser.fromCluster(
getPythnetCluster(cluster)
)
const parsedRemoteInstruction =
innerMultisigParser.parseInstruction({
programId: remoteIx.programId,
Expand All @@ -215,7 +229,7 @@ export const Proposal = ({
parsedRemoteInstruction instanceof AnchorMultisigInstruction
)
}) &&
ix.governanceAction.targetChainId === 'pythnet')
isSvmChainId(ix.governanceAction.targetChainId))
)

const voted =
Expand Down Expand Up @@ -300,7 +314,7 @@ export const Proposal = ({

if (refreshData) await refreshData().fetchData()
toast.success(msg)
} catch (e: any) {
} catch (e) {
toast.error(capitalizeFirstLetter(e.message))
} finally {
setIsTransactionLoading(false)
Expand Down Expand Up @@ -488,7 +502,10 @@ export const Proposal = ({
</h4>
<hr className="border-gray-700" />
<h4 className="h4 text-[20px] font-semibold">Summary</h4>
<InstructionsSummary instructions={instructions} cluster={cluster} />
<InstructionsSummary
instructions={instructions}
cluster={getPythnetCluster(cluster)}
/>
<hr className="border-gray-700" />
{instructions?.map((instruction, index) => (
<Fragment key={index}>
Expand Down Expand Up @@ -549,7 +566,7 @@ export const Proposal = ({
{typeof instruction.args[key] === 'string'
? instruction.args[key]
: instruction.args[key] instanceof Uint8Array
? instruction.args[key].toString('hex')
? instruction.args[key].toString()
: typeof instruction.args[key] === 'bigint'
? instruction.args[key].toString()
: JSON.stringify(instruction.args[key])}
Expand All @@ -576,7 +593,7 @@ export const Proposal = ({
)}
{instruction instanceof WormholeMultisigInstruction && (
<WormholeInstructionView
cluster={cluster}
cluster={getPythnetCluster(cluster)}
instruction={instruction}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
MultisigParser,
PythGovernanceActionImpl,
SetDataSources,
SvmCluster,
WormholeMultisigInstruction,
} from '@pythnetwork/xc-admin-common'

Expand Down Expand Up @@ -117,3 +118,24 @@ const getTransactionSummary = (instruction: MultisigInstruction) => {
} as const
}
}

export const isSolanaPullProgram = (programId: PublicKey) => {
const solanaPullProgramIds = [
new PublicKey('rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ'),
new PublicKey('HDwcJBJXjL9FpJ7UBsYBtaDjsBUhuLCUYoz3zr8SWWaQ'),
new PublicKey('pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT'),
]
return solanaPullProgramIds.some((id) => programId.equals(id))
}

export const isSvmChainId = (chainId: string) => {
const svmChainIds = ['pythnet', 'eclipse_mainnet']
return svmChainIds.includes(chainId)
}

export const getPythnetCluster = (cluster: SvmCluster): PythCluster => {
if (isSvmChainId(cluster)) {
return 'pythnet'
}
return cluster as PythCluster
}

0 comments on commit 0fc9148

Please sign in to comment.