Skip to content

Commit

Permalink
feat(xc-admin): add price store instructions and executor support (#1900
Browse files Browse the repository at this point in the history
)

* feat(xc-admin): add price store instructions and executor support

* refactor(governance/xc_admin): use switch, verify data and accounts
  • Loading branch information
Riateche authored Sep 16, 2024
1 parent 29aa1b7 commit 5527782
Show file tree
Hide file tree
Showing 4 changed files with 364 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { PublicKey } from "@solana/web3.js";
import {
createPriceStoreInstruction,
parsePriceStoreInstruction,
PriceStoreInstruction,
} from "../price_store";

test("Price store instruction parse: roundtrip", (done) => {
const items: PriceStoreInstruction[] = [
{
type: "Initialize",
data: {
payerKey: new PublicKey("Fe9vtgwRhbMSUsAjwUzupzRoJKofyyk1Rz8ZUrPmGHMr"),
authorityKey: new PublicKey(
"D9rnZSLjdYboFGDGHk5Qre2yBS8HYbc6374Zm6AeC1PB"
),
},
},
{
type: "InitializePublisher",
data: {
authorityKey: new PublicKey(
"D9rnZSLjdYboFGDGHk5Qre2yBS8HYbc6374Zm6AeC1PB"
),
publisherKey: new PublicKey(
"EXAyN9UVu1x163PQkVzyNm4YunNkMGu5Ry7ntoyyQGTe"
),
bufferKey: new PublicKey(
"7q6SS575jGDjE8bWsx4PiLVqS7cHJhjJBhysvRoP53WJ"
),
},
},
];
for (const data of items) {
const instruction = createPriceStoreInstruction(data);
const parsed = parsePriceStoreInstruction(instruction);
expect(parsed).toStrictEqual(data);
}
done();
});
27 changes: 27 additions & 0 deletions governance/xc_admin/packages/xc_admin_common/src/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ import {
TransactionBuilder,
PriorityFeeConfig,
} from "@pythnetwork/solana-utils";
import {
findDetermisticPublisherBufferAddress,
PRICE_STORE_BUFFER_SPACE,
PRICE_STORE_PROGRAM_ID,
PriceStoreMultisigInstruction,
} from "./price_store";

/**
* Returns the instruction to pay the fee for a wormhole postMessage instruction
Expand Down Expand Up @@ -134,6 +140,27 @@ export async function executeProposal(
} else {
throw Error("Product account not found");
}
} else if (
parsedInstruction instanceof PriceStoreMultisigInstruction &&
parsedInstruction.name == "InitializePublisher"
) {
const [bufferKey, bufferSeed] =
await findDetermisticPublisherBufferAddress(
parsedInstruction.args.publisherKey
);
transaction.add(
SystemProgram.createAccountWithSeed({
fromPubkey: squad.wallet.publicKey,
basePubkey: squad.wallet.publicKey,
newAccountPubkey: bufferKey,
seed: bufferSeed,
space: PRICE_STORE_BUFFER_SPACE,
lamports: await squad.connection.getMinimumBalanceForRentExemption(
PRICE_STORE_BUFFER_SPACE
),
programId: PRICE_STORE_PROGRAM_ID,
})
);
}

TransactionBuilder.addPriorityFee(transaction, priorityFeeConfig);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import { BPF_UPGRADABLE_LOADER } from "../bpf_upgradable_loader";
import { AnchorAccounts } from "./anchor";
import { SolanaStakingMultisigInstruction } from "./SolanaStakingMultisigInstruction";
import { DEFAULT_RECEIVER_PROGRAM_ID } from "@pythnetwork/pyth-solana-receiver";
import {
PRICE_STORE_PROGRAM_ID,
PriceStoreMultisigInstruction,
} from "../price_store";

export const UNRECOGNIZED_INSTRUCTION = "unrecognizedInstruction";
export enum MultisigInstructionProgram {
Expand All @@ -36,6 +40,7 @@ export enum MultisigInstructionProgram {
SolanaStakingProgram,
SolanaReceiver,
UnrecognizedProgram,
PythPriceStore,
}

export function getProgramName(program: MultisigInstructionProgram) {
Expand All @@ -58,6 +63,8 @@ export function getProgramName(program: MultisigInstructionProgram) {
return "Pyth Staking Program";
case MultisigInstructionProgram.SolanaReceiver:
return "Pyth Solana Receiver";
case MultisigInstructionProgram.PythPriceStore:
return "Pyth Price Store";
case MultisigInstructionProgram.UnrecognizedProgram:
return "Unknown";
}
Expand Down Expand Up @@ -99,18 +106,22 @@ export class UnrecognizedProgram implements MultisigInstruction {
export class MultisigParser {
readonly pythOracleAddress: PublicKey;
readonly wormholeBridgeAddress: PublicKey | undefined;
readonly pythPriceStoreAddress: PublicKey | undefined;

constructor(
pythOracleAddress: PublicKey,
wormholeBridgeAddress: PublicKey | undefined
wormholeBridgeAddress: PublicKey | undefined,
pythPriceStoreAddress: PublicKey | undefined
) {
this.pythOracleAddress = pythOracleAddress;
this.wormholeBridgeAddress = wormholeBridgeAddress;
this.pythPriceStoreAddress = pythPriceStoreAddress;
}
static fromCluster(cluster: PythCluster): MultisigParser {
return new MultisigParser(
getPythProgramKeyForCluster(cluster),
WORMHOLE_ADDRESS[cluster]
WORMHOLE_ADDRESS[cluster],
PRICE_STORE_PROGRAM_ID
);
}

Expand All @@ -124,6 +135,13 @@ export class MultisigParser {
);
} else if (instruction.programId.equals(this.pythOracleAddress)) {
return PythMultisigInstruction.fromTransactionInstruction(instruction);
} else if (
this.pythPriceStoreAddress &&
instruction.programId.equals(this.pythPriceStoreAddress)
) {
return PriceStoreMultisigInstruction.fromTransactionInstruction(
instruction
);
} else if (
instruction.programId.equals(MESSAGE_BUFFER_PROGRAM_ID) ||
instruction.programId.equals(MESH_PROGRAM_ID) ||
Expand Down
Loading

0 comments on commit 5527782

Please sign in to comment.