Skip to content

Commit 57b1367

Browse files
guibescosthmzlt
andauthored
Add staking instructions to xc-admin (#1160)
* Do it * Add xc-admin-cli command for proposing deactivate-stake instructions * Cleanup --------- Co-authored-by: Thomaz Leite <[email protected]>
1 parent 97bbc8c commit 57b1367

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
SYSVAR_RENT_PUBKEY,
66
SYSVAR_CLOCK_PUBKEY,
77
AccountMeta,
8+
StakeProgram,
89
SystemProgram,
910
LAMPORTS_PER_SOL,
1011
Connection,
@@ -226,6 +227,35 @@ multisigCommand(
226227
await vault.proposeInstructions([proposalInstruction], cluster);
227228
});
228229

230+
multisigCommand(
231+
"deactivate-stake",
232+
"Deactivate the delegated stake from the account"
233+
)
234+
.requiredOption(
235+
"-s, --stake-accounts <accounts...>",
236+
"stake accounts to be deactivated"
237+
)
238+
.action(async (options: any) => {
239+
const vault = await loadVaultFromOptions(options);
240+
const cluster: PythCluster = options.cluster;
241+
const authorizedPubkey: PublicKey = await vault.getVaultAuthorityPDA(
242+
cluster
243+
);
244+
const instructions = options.stakeAccounts.reduce(
245+
(instructions: TransactionInstruction[], stakeAccount: string) => {
246+
const transaction = StakeProgram.deactivate({
247+
stakePubkey: new PublicKey(stakeAccount),
248+
authorizedPubkey,
249+
});
250+
251+
return instructions.concat(transaction.instructions);
252+
},
253+
[]
254+
);
255+
256+
await vault.proposeInstructions(instructions, cluster);
257+
});
258+
229259
multisigCommand(
230260
"init-price",
231261
"Init price (useful for changing the exponent), only to be used on unused price feeds"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { TransactionInstruction } from "@solana/web3.js";
2+
import {
3+
MultisigInstruction,
4+
MultisigInstructionProgram,
5+
UNRECOGNIZED_INSTRUCTION,
6+
} from ".";
7+
import { AnchorAccounts } from "./anchor";
8+
import { StakeInstruction } from "@solana/web3.js";
9+
10+
export class SolanaStakingMultisigInstruction implements MultisigInstruction {
11+
readonly program = MultisigInstructionProgram.SolanaStakingProgram;
12+
readonly name: string;
13+
readonly args: { [key: string]: any };
14+
readonly accounts: AnchorAccounts;
15+
16+
constructor(
17+
name: string,
18+
args: { [key: string]: any },
19+
accounts: AnchorAccounts
20+
) {
21+
this.name = name;
22+
this.args = args;
23+
this.accounts = accounts;
24+
}
25+
26+
static fromTransactionInstruction(
27+
instruction: TransactionInstruction
28+
): SolanaStakingMultisigInstruction {
29+
try {
30+
const type = StakeInstruction.decodeInstructionType(instruction);
31+
switch (type) {
32+
case "Deactivate":
33+
const decoded = StakeInstruction.decodeDeactivate(instruction);
34+
return new SolanaStakingMultisigInstruction(
35+
"Deactivate",
36+
{},
37+
{
38+
named: {
39+
stakePubkey: {
40+
pubkey: decoded.stakePubkey,
41+
isSigner: false,
42+
isWritable: true,
43+
},
44+
authorizedPubkey: {
45+
pubkey: decoded.authorizedPubkey,
46+
isSigner: true,
47+
isWritable: false,
48+
},
49+
},
50+
remaining: [],
51+
}
52+
);
53+
54+
case "Authorize":
55+
case "AuthorizeWithSeed":
56+
case "Delegate":
57+
case "Initialize":
58+
case "Merge":
59+
case "Split":
60+
case "Withdraw":
61+
case "Authorize":
62+
throw Error("Unsupported instruction type");
63+
}
64+
} catch {
65+
return new SolanaStakingMultisigInstruction(
66+
UNRECOGNIZED_INSTRUCTION,
67+
{ data: instruction.data },
68+
{ named: {}, remaining: instruction.keys }
69+
);
70+
}
71+
}
72+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
} from "@pythnetwork/client/lib/cluster";
55
import {
66
PublicKey,
7+
StakeProgram,
78
SystemProgram,
89
TransactionInstruction,
910
} from "@solana/web3.js";
@@ -16,6 +17,7 @@ import { SystemProgramMultisigInstruction } from "./SystemProgramInstruction";
1617
import { BpfUpgradableLoaderInstruction } from "./BpfUpgradableLoaderMultisigInstruction";
1718
import { BPF_UPGRADABLE_LOADER } from "../bpf_upgradable_loader";
1819
import { AnchorAccounts } from "./anchor";
20+
import { SolanaStakingMultisigInstruction } from "./SolanaStakingMultisigInstruction";
1921

2022
export const UNRECOGNIZED_INSTRUCTION = "unrecognizedInstruction";
2123
export enum MultisigInstructionProgram {
@@ -24,6 +26,7 @@ export enum MultisigInstructionProgram {
2426
MessageBuffer,
2527
SystemProgram,
2628
BpfUpgradableLoader,
29+
SolanaStakingProgram,
2730
UnrecognizedProgram,
2831
}
2932

@@ -39,6 +42,8 @@ export function getProgramName(program: MultisigInstructionProgram) {
3942
return "System Program";
4043
case MultisigInstructionProgram.BpfUpgradableLoader:
4144
return "BPF Upgradable Loader";
45+
case MultisigInstructionProgram.SolanaStakingProgram:
46+
return "Solana Staking Program";
4247
case MultisigInstructionProgram.UnrecognizedProgram:
4348
return "Unknown";
4449
}
@@ -117,6 +122,10 @@ export class MultisigParser {
117122
return BpfUpgradableLoaderInstruction.fromTransactionInstruction(
118123
instruction
119124
);
125+
} else if (instruction.programId.equals(StakeProgram.programId)) {
126+
return SolanaStakingMultisigInstruction.fromTransactionInstruction(
127+
instruction
128+
);
120129
} else {
121130
return UnrecognizedProgram.fromTransactionInstruction(instruction);
122131
}
@@ -128,3 +137,4 @@ export { PythMultisigInstruction } from "./PythMultisigInstruction";
128137
export { MessageBufferMultisigInstruction } from "./MessageBufferMultisigInstruction";
129138
export { SystemProgramMultisigInstruction } from "./SystemProgramInstruction";
130139
export { BpfUpgradableLoaderInstruction } from "./BpfUpgradableLoaderMultisigInstruction";
140+
export { SolanaStakingMultisigInstruction } from "./SolanaStakingMultisigInstruction";

0 commit comments

Comments
 (0)