Skip to content

Commit e1377e5

Browse files
authored
[Xc admin cli] add and remove members (#887)
* Checkpoint * Checkpoint * Checkpoint * Checkpoint * Checkpoint * Checkpoint * Checkpoint * Comment * Comment
1 parent 9adc340 commit e1377e5

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,4 +352,68 @@ multisigCommand("activate", "Activate a transaction sitting in the multisig")
352352
await vault.squad.activateTransaction(transaction);
353353
});
354354

355+
multisigCommand("add-and-delete", "Change the roster of the multisig")
356+
.option(
357+
"-a, --add <comma_separated_members>",
358+
"addresses to add to the multisig"
359+
)
360+
.option(
361+
"-r, --remove <comma_separated_members>",
362+
"addresses to remove from the multisig"
363+
)
364+
.requiredOption(
365+
"-t, --target-vaults <comma_separated_vaults>",
366+
"the vault whose roster we want to change"
367+
)
368+
.action(async (options: any) => {
369+
const vault: MultisigVault = await loadVaultFromOptions(options);
370+
371+
const targetVaults: PublicKey[] = options.targetVaults
372+
? options.targetVaults.split(",").map((m: string) => new PublicKey(m))
373+
: [];
374+
375+
let proposalInstructions: TransactionInstruction[] = [];
376+
377+
const membersToAdd: PublicKey[] = options.add
378+
? options.add.split(",").map((m: string) => new PublicKey(m))
379+
: [];
380+
381+
for (const member of membersToAdd) {
382+
for (const targetVault of targetVaults) {
383+
proposalInstructions.push(await vault.addMemberIx(member, targetVault));
384+
}
385+
}
386+
387+
const membersToRemove: PublicKey[] = options.remove
388+
? options.remove.split(",").map((m: string) => new PublicKey(m))
389+
: [];
390+
391+
for (const member of membersToRemove) {
392+
for (const targetVault of targetVaults) {
393+
proposalInstructions.push(
394+
await vault.removeMemberIx(member, targetVault)
395+
);
396+
}
397+
}
398+
399+
vault.proposeInstructions(proposalInstructions, options.cluster);
400+
});
401+
402+
/**
403+
* READ THIS BEFORE USING THIS COMMAND
404+
* This command exists because of a bug in mesh where
405+
* roster change proposals executed through executeInstruction don't work.
406+
* It is equivalent to executing proposals through the mesh UI.
407+
* It might not work for some types of proposals that require the crank to
408+
* execute them.
409+
* https://github.com/Squads-Protocol/squads-mpl/pull/32
410+
*/
411+
multisigCommand("execute-add-and-delete", "Execute a roster change proposal")
412+
.requiredOption("-t, --transaction <pubkey>", "address of the proposal")
413+
.action(async (options: any) => {
414+
const vault: MultisigVault = await loadVaultFromOptions(options);
415+
const proposal = new PublicKey(options.transaction);
416+
await vault.squad.executeTransaction(proposal);
417+
});
418+
355419
program.parse();

governance/xc_admin/packages/xc_admin_common/src/propose.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,28 @@ export class MultisigVault {
147147
);
148148
}
149149

150+
public async addMemberIx(
151+
member: PublicKey,
152+
targetVault: PublicKey
153+
): Promise<TransactionInstruction> {
154+
return await this.squad.buildAddMember(
155+
targetVault,
156+
await this.getAuthorityPDA(),
157+
member
158+
);
159+
}
160+
161+
public async removeMemberIx(
162+
member: PublicKey,
163+
targetVault: PublicKey
164+
): Promise<TransactionInstruction> {
165+
return await this.squad.buildRemoveMember(
166+
targetVault,
167+
await this.getAuthorityPDA(),
168+
member
169+
);
170+
}
171+
150172
// Propose instructions
151173

152174
/**

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)