Skip to content

Commit

Permalink
Showing 9 changed files with 130 additions and 11 deletions.
1 change: 1 addition & 0 deletions governance/xc_admin/packages/xc_admin_cli/package.json
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@
"@pythnetwork/pyth-solana-receiver": "workspace:*",
"@pythnetwork/solana-utils": "workspace:^",
"@pythnetwork/xc-admin-common": "workspace:*",
"@pythnetwork/pyth-lazer-sdk": "workspace:*",
"@solana/spl-token": "^0.3.7",
"@solana/web3.js": "^1.73.0",
"@sqds/mesh": "^1.0.6",
49 changes: 48 additions & 1 deletion governance/xc_admin/packages/xc_admin_cli/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Program } from "@coral-xyz/anchor";
import { Program, BN, Idl } from "@coral-xyz/anchor";
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
import { Wallet } from "@coral-xyz/anchor/dist/cjs/provider";
import { TOKEN_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/utils/token";
@@ -47,13 +47,18 @@ import {
getProposalInstructions,
idlSetBuffer,
isPriceStorePublisherInitialized,
lazerIdl,
} from "@pythnetwork/xc-admin-common";

import {
pythSolanaReceiverIdl,
getConfigPda,
DEFAULT_RECEIVER_PROGRAM_ID,
} from "@pythnetwork/pyth-solana-receiver";
import {
SOLANA_LAZER_PROGRAM_ID,
SOLANA_STORAGE_ID,
} from "@pythnetwork/pyth-lazer-sdk";

import { LedgerNodeWallet } from "./ledger";
import {
@@ -924,4 +929,46 @@ multisigCommand("execute-add-and-delete", "Execute a roster change proposal")
await vault.squad.executeTransaction(proposal);
});

multisigCommand(
"set-trusted-signer",
"Set a trusted signer for the Lazer program"
)
.requiredOption(
"-s, --signer <pubkey>",
"public key of the trusted signer to add/update"
)
.requiredOption(
"-e, --expiry-time <seconds>",
"expiry time in seconds since Unix epoch. Set to 0 to remove the signer."
)
.action(async (options: any) => {
const vault = await loadVaultFromOptions(options);
const targetCluster: PythCluster = options.cluster;

const trustedSigner = new PublicKey(options.signer);
const expiryTime = new BN(options.expiryTime);

// Create Anchor program instance
const lazerProgram = new Program(
lazerIdl as Idl,
SOLANA_LAZER_PROGRAM_ID,
vault.getAnchorProvider()
);

// Use Anchor to create the instruction
const updateInstruction = await lazerProgram.methods
.update(trustedSigner, expiryTime)
.accounts({
authority: await vault.getVaultAuthorityPDA(targetCluster),
storage: SOLANA_STORAGE_ID,
})
.instruction();

await vault.proposeInstructions(
[updateInstruction],
targetCluster,
DEFAULT_PRIORITY_FEE_CONFIG
);
});

program.parse();
1 change: 1 addition & 0 deletions governance/xc_admin/packages/xc_admin_common/package.json
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@
"ethers": "^5.7.2",
"lodash": "^4.17.21",
"message_buffer": "workspace:^",
"@pythnetwork/pyth-lazer-sdk": "workspace:*",
"typescript": "^4.9.4"
},
"devDependencies": {
1 change: 1 addition & 0 deletions governance/xc_admin/packages/xc_admin_common/src/index.ts
Original file line number Diff line number Diff line change
@@ -13,3 +13,4 @@ export * from "./executor";
export * from "./chains";
export * from "./deterministic_stake_accounts";
export * from "./price_store";
export { default as lazerIdl } from "./multisig_transaction/idl/lazer.json";
Original file line number Diff line number Diff line change
@@ -8,10 +8,6 @@ import { PublicKey, TransactionInstruction } from "@solana/web3.js";
import { Idl, BorshInstructionCoder } from "@coral-xyz/anchor";
import lazerIdl from "./idl/lazer.json";

export const LAZER_PROGRAM_ID = new PublicKey(
"pytd2yyk641x7ak7mkaasSJVXh6YYZnC7wTmtgAyxPt"
);

export class LazerMultisigInstruction implements MultisigInstruction {
readonly program = MultisigInstructionProgram.Lazer;
readonly name: string;
Original file line number Diff line number Diff line change
@@ -27,10 +27,8 @@ import {
PRICE_STORE_PROGRAM_ID,
PriceStoreMultisigInstruction,
} from "../price_store";
import {
LazerMultisigInstruction,
LAZER_PROGRAM_ID,
} from "./LazerMultisigInstruction";
import { LazerMultisigInstruction } from "./LazerMultisigInstruction";
import { SOLANA_LAZER_PROGRAM_ID } from "@pythnetwork/pyth-lazer-sdk";

export const UNRECOGNIZED_INSTRUCTION = "unrecognizedInstruction";
export enum MultisigInstructionProgram {
@@ -168,7 +166,7 @@ export class MultisigParser {
return SolanaStakingMultisigInstruction.fromTransactionInstruction(
instruction
);
} else if (instruction.programId.equals(LAZER_PROGRAM_ID)) {
} else if (instruction.programId.equals(SOLANA_LAZER_PROGRAM_ID)) {
return LazerMultisigInstruction.fromInstruction(instruction);
} else {
return UnrecognizedProgram.fromTransactionInstruction(instruction);
3 changes: 2 additions & 1 deletion lazer/contracts/solana/package.json
Original file line number Diff line number Diff line change
@@ -8,7 +8,8 @@
"test:anchor": "CARGO_TARGET_DIR=\"$PWD/target\" anchor test",
"test": "pnpm run test:format && pnpm run test:anchor",
"setup": "anchor build && pnpm ts-node scripts/setup.ts",
"migrate_from_0_1_0": "pnpm ts-node scripts/migrate_from_0_1_0.ts"
"migrate_from_0_1_0": "pnpm ts-node scripts/migrate_from_0_1_0.ts",
"check_trusted_signer": "pnpm ts-node scripts/check_trusted_signer.ts"
},
"dependencies": {
"@coral-xyz/anchor": "^0.30.1"
68 changes: 68 additions & 0 deletions lazer/contracts/solana/scripts/check_trusted_signer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import * as anchor from "@coral-xyz/anchor";
import { PythLazerSolanaContract } from "../target/types/pyth_lazer_solana_contract";
import * as pythLazerSolanaContractIdl from "../target/idl/pyth_lazer_solana_contract.json";
import yargs from "yargs/yargs";
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";

const parser = yargs(process.argv.slice(2)).options({
url: {
type: "string",
demandOption: true,
desc: "RPC URL to use",
},
"storage-id": {
type: "string",
demandOption: true,
desc: "Storage account ID to check",
},
});

async function main() {
const argv = await parser.argv;

// Setup anchor provider
const connection = new anchor.web3.Connection(argv.url);
const provider = new anchor.AnchorProvider(
connection,
new NodeWallet(anchor.web3.Keypair.generate()), // Dummy wallet since we're only reading
{ commitment: "confirmed" }
);
anchor.setProvider(provider);

const program: anchor.Program<PythLazerSolanaContract> = new anchor.Program(
pythLazerSolanaContractIdl as PythLazerSolanaContract,
provider
);

// Fetch and decode storage account
const storageId = new anchor.web3.PublicKey(argv["storage-id"]);
const storage = await program.account.storage.fetch(storageId);

// Print storage info
console.log("Storage Account Info:");
console.log("--------------------");
console.log("Top Authority:", storage.topAuthority.toBase58());
console.log("Treasury:", storage.treasury.toBase58());
console.log("\nTrusted Signers:");
console.log("----------------");

for (const signer of storage.trustedSigners) {
if (signer.pubkey.equals(anchor.web3.PublicKey.default)) continue;
console.log(`\nPublic Key: ${signer.pubkey.toBase58()}`);
console.log(
`Expires At: ${new Date(
signer.expiresAt.toNumber() * 1000
).toISOString()}`
);
console.log(
`Active: ${
signer.expiresAt.toNumber() > Date.now() / 1000 ? "Yes" : "No"
}`
);
}
}

main().catch((err) => {
console.error(err);
process.exit(1);
});
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit afcb132

Please sign in to comment.