Skip to content

Commit c7d5cf0

Browse files
authored
feat(xc_admin_cli): make deactivate stake take in vote accounts (#2036)
* feat: make deactivate stake take in vote accounts * fix node version
1 parent 9973287 commit c7d5cf0

File tree

4 files changed

+62
-15
lines changed

4 files changed

+62
-15
lines changed

.github/workflows/ci-ethereum-contract.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ jobs:
2121
working-directory: target_chains/ethereum/contracts/
2222
steps:
2323
- uses: actions/checkout@v3
24+
- uses: actions/setup-node@v4
25+
with:
26+
node-version-file: "package.json"
2427

2528
- uses: pnpm/action-setup@v4
2629
name: Install pnpm

governance/xc_admin/packages/xc_admin_cli/src/index.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import {
4141
PROGRAM_AUTHORITY_ESCROW,
4242
createDetermisticPriceStoreInitializePublisherInstruction,
4343
createPriceStoreInstruction,
44+
fetchStakeAccounts,
4445
findDetermisticStakeAccountAddress,
4546
getMultisigCluster,
4647
getProposalInstructions,
@@ -59,6 +60,7 @@ import {
5960
DEFAULT_PRIORITY_FEE_CONFIG,
6061
TransactionBuilder,
6162
} from "@pythnetwork/solana-utils";
63+
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";
6264

6365
export async function loadHotWalletOrLedger(
6466
wallet: string,
@@ -389,8 +391,8 @@ multisigCommand(
389391
"Deactivate the delegated stake from the account"
390392
)
391393
.requiredOption(
392-
"-s, --stake-accounts <comma_separated_stake_account>",
393-
"stake accounts to be deactivated"
394+
"-d, --vote-pubkeys <comma_separated_voter_pubkeys>",
395+
"vote account unstake from"
394396
)
395397
.action(async (options: any) => {
396398
const vault = await loadVaultFromOptions(options);
@@ -399,20 +401,25 @@ multisigCommand(
399401
cluster
400402
);
401403

402-
const stakeAccounts = options.stakeAccounts
403-
? options.stakeAccounts.split(",").map((m: string) => new PublicKey(m))
404+
const voteAccounts: PublicKey[] = options.votePubkeys
405+
? options.votePubkeys.split(",").map((m: string) => new PublicKey(m))
404406
: [];
405407

406-
const instructions = stakeAccounts.reduce(
407-
(instructions: TransactionInstruction[], stakeAccount: PublicKey) => {
408-
const transaction = StakeProgram.deactivate({
409-
stakePubkey: stakeAccount,
410-
authorizedPubkey,
411-
});
408+
const stakeAccounts = (
409+
await Promise.all(
410+
voteAccounts.map((voteAccount: PublicKey) =>
411+
fetchStakeAccounts(
412+
new Connection(getPythClusterApiUrl(cluster)),
413+
voteAccount
414+
)
415+
)
416+
)
417+
).flat();
412418

413-
return instructions.concat(transaction.instructions);
414-
},
415-
[]
419+
const instructions = stakeAccounts.flatMap(
420+
(stakeAccount) =>
421+
StakeProgram.deactivate({ stakePubkey: stakeAccount, authorizedPubkey })
422+
.instructions
416423
);
417424

418425
await vault.proposeInstructions(

governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/SolanaStakingMultisigInstruction.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
import { TransactionInstruction } from "@solana/web3.js";
1+
import {
2+
Connection,
3+
PublicKey,
4+
StakeProgram,
5+
TransactionInstruction,
6+
} from "@solana/web3.js";
27
import {
38
MultisigInstruction,
49
MultisigInstructionProgram,
510
UNRECOGNIZED_INSTRUCTION,
611
} from ".";
712
import { AnchorAccounts } from "./anchor";
813
import { StakeInstruction } from "@solana/web3.js";
14+
import { bs58 } from "@coral-xyz/anchor/dist/cjs/utils/bytes";
915

1016
export class SolanaStakingMultisigInstruction implements MultisigInstruction {
1117
readonly program = MultisigInstructionProgram.SolanaStakingProgram;
@@ -115,3 +121,31 @@ export class SolanaStakingMultisigInstruction implements MultisigInstruction {
115121
}
116122
}
117123
}
124+
125+
export async function fetchStakeAccounts(
126+
connection: Connection,
127+
voterAccount: PublicKey
128+
) {
129+
const stakeAccounts = await connection.getProgramAccounts(
130+
StakeProgram.programId,
131+
{
132+
encoding: "base64",
133+
filters: [
134+
{
135+
memcmp: {
136+
offset: 0,
137+
bytes: bs58.encode(Buffer.from([2, 0, 0, 0])),
138+
},
139+
},
140+
{
141+
memcmp: {
142+
offset: 124,
143+
bytes: voterAccount.toBase58(),
144+
},
145+
},
146+
],
147+
}
148+
);
149+
150+
return stakeAccounts.map((account) => account.pubkey);
151+
}

governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,7 @@ export { PythMultisigInstruction } from "./PythMultisigInstruction";
173173
export { AnchorMultisigInstruction } from "./MessageBufferMultisigInstruction";
174174
export { SystemProgramMultisigInstruction } from "./SystemProgramInstruction";
175175
export { BpfUpgradableLoaderInstruction } from "./BpfUpgradableLoaderMultisigInstruction";
176-
export { SolanaStakingMultisigInstruction } from "./SolanaStakingMultisigInstruction";
176+
export {
177+
SolanaStakingMultisigInstruction,
178+
fetchStakeAccounts,
179+
} from "./SolanaStakingMultisigInstruction";

0 commit comments

Comments
 (0)