fix: add custodian key support to stake instructions

This commit is contained in:
Michael Vines
2021-01-26 09:40:41 -08:00
parent 1d6e9335ff
commit e08d2e6fcc
4 changed files with 132 additions and 25 deletions

3
web3.js/module.d.ts vendored
View File

@ -772,6 +772,7 @@ declare module '@solana/web3.js' {
authorizedPubkey: PublicKey; authorizedPubkey: PublicKey;
newAuthorizedPubkey: PublicKey; newAuthorizedPubkey: PublicKey;
stakeAuthorizationType: StakeAuthorizationType; stakeAuthorizationType: StakeAuthorizationType;
custodianPubkey?: PublicKey;
}; };
export type AuthorizeWithSeedStakeParams = { export type AuthorizeWithSeedStakeParams = {
@ -781,6 +782,7 @@ declare module '@solana/web3.js' {
authorityOwner: PublicKey; authorityOwner: PublicKey;
newAuthorizedPubkey: PublicKey; newAuthorizedPubkey: PublicKey;
stakeAuthorizationType: StakeAuthorizationType; stakeAuthorizationType: StakeAuthorizationType;
custodianPubkey?: PublicKey;
}; };
export type SplitStakeParams = { export type SplitStakeParams = {
@ -795,6 +797,7 @@ declare module '@solana/web3.js' {
authorizedPubkey: PublicKey; authorizedPubkey: PublicKey;
toPubkey: PublicKey; toPubkey: PublicKey;
lamports: number; lamports: number;
custodianPubkey?: PublicKey;
}; };
export type DeactivateStakeParams = { export type DeactivateStakeParams = {

View File

@ -780,6 +780,7 @@ declare module '@solana/web3.js' {
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
newAuthorizedPubkey: PublicKey, newAuthorizedPubkey: PublicKey,
stakeAuthorizationType: StakeAuthorizationType, stakeAuthorizationType: StakeAuthorizationType,
custodianPubkey?: PublicKey,
|}; |};
declare export type AuthorizeWithSeedStakeParams = {| declare export type AuthorizeWithSeedStakeParams = {|
@ -789,6 +790,7 @@ declare module '@solana/web3.js' {
authorityOwner: PublicKey, authorityOwner: PublicKey,
newAuthorizedPubkey: PublicKey, newAuthorizedPubkey: PublicKey,
stakeAuthorizationType: StakeAuthorizationType, stakeAuthorizationType: StakeAuthorizationType,
custodianPubkey?: PublicKey,
|}; |};
declare export type SplitStakeParams = {| declare export type SplitStakeParams = {|
@ -803,6 +805,7 @@ declare module '@solana/web3.js' {
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
toPubkey: PublicKey, toPubkey: PublicKey,
lamports: number, lamports: number,
custodianPubkey?: PublicKey,
|}; |};
declare export type DeactivateStakeParams = {| declare export type DeactivateStakeParams = {|

View File

@ -116,12 +116,14 @@ export type DelegateStakeParams = {|
* @property {PublicKey} authorizedPubkey * @property {PublicKey} authorizedPubkey
* @property {PublicKey} newAuthorizedPubkey * @property {PublicKey} newAuthorizedPubkey
* @property {StakeAuthorizationType} stakeAuthorizationType * @property {StakeAuthorizationType} stakeAuthorizationType
* @property {PublicKey} custodianPubkey
*/ */
export type AuthorizeStakeParams = {| export type AuthorizeStakeParams = {|
stakePubkey: PublicKey, stakePubkey: PublicKey,
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
newAuthorizedPubkey: PublicKey, newAuthorizedPubkey: PublicKey,
stakeAuthorizationType: StakeAuthorizationType, stakeAuthorizationType: StakeAuthorizationType,
custodianPubkey?: PublicKey,
|}; |};
/** /**
@ -133,6 +135,7 @@ export type AuthorizeStakeParams = {|
* @property {PublicKey} authorityOwner * @property {PublicKey} authorityOwner
* @property {PublicKey} newAuthorizedPubkey * @property {PublicKey} newAuthorizedPubkey
* @property {StakeAuthorizationType} stakeAuthorizationType * @property {StakeAuthorizationType} stakeAuthorizationType
* @property {PublicKey} custodianPubkey
*/ */
export type AuthorizeWithSeedStakeParams = {| export type AuthorizeWithSeedStakeParams = {|
stakePubkey: PublicKey, stakePubkey: PublicKey,
@ -141,6 +144,7 @@ export type AuthorizeWithSeedStakeParams = {|
authorityOwner: PublicKey, authorityOwner: PublicKey,
newAuthorizedPubkey: PublicKey, newAuthorizedPubkey: PublicKey,
stakeAuthorizationType: StakeAuthorizationType, stakeAuthorizationType: StakeAuthorizationType,
custodianPubkey?: PublicKey,
|}; |};
/** /**
@ -165,12 +169,14 @@ export type SplitStakeParams = {|
* @property {PublicKey} authorizedPubkey * @property {PublicKey} authorizedPubkey
* @property {PublicKey} toPubkey * @property {PublicKey} toPubkey
* @property {number} lamports * @property {number} lamports
* @property {PublicKey} custodianPubkey
*/ */
export type WithdrawStakeParams = {| export type WithdrawStakeParams = {|
stakePubkey: PublicKey, stakePubkey: PublicKey,
authorizedPubkey: PublicKey, authorizedPubkey: PublicKey,
toPubkey: PublicKey, toPubkey: PublicKey,
lamports: number, lamports: number,
custodianPubkey?: PublicKey,
|}; |};
/** /**
@ -271,7 +277,7 @@ export class StakeInstruction {
instruction.data, instruction.data,
); );
return { const o: AuthorizeStakeParams = {
stakePubkey: instruction.keys[0].pubkey, stakePubkey: instruction.keys[0].pubkey,
authorizedPubkey: instruction.keys[2].pubkey, authorizedPubkey: instruction.keys[2].pubkey,
newAuthorizedPubkey: new PublicKey(newAuthorized), newAuthorizedPubkey: new PublicKey(newAuthorized),
@ -279,6 +285,10 @@ export class StakeInstruction {
index: stakeAuthorizationType, index: stakeAuthorizationType,
}, },
}; };
if (instruction.keys.length > 3) {
o.custodianPubkey = instruction.keys[3].pubkey;
}
return o;
} }
/** /**
@ -289,6 +299,7 @@ export class StakeInstruction {
): AuthorizeWithSeedStakeParams { ): AuthorizeWithSeedStakeParams {
this.checkProgramId(instruction.programId); this.checkProgramId(instruction.programId);
this.checkKeyLength(instruction.keys, 2); this.checkKeyLength(instruction.keys, 2);
const { const {
newAuthorized, newAuthorized,
stakeAuthorizationType, stakeAuthorizationType,
@ -299,7 +310,7 @@ export class StakeInstruction {
instruction.data, instruction.data,
); );
return { const o: AuthorizeWithSeedStakeParams = {
stakePubkey: instruction.keys[0].pubkey, stakePubkey: instruction.keys[0].pubkey,
authorityBase: instruction.keys[1].pubkey, authorityBase: instruction.keys[1].pubkey,
authoritySeed: authoritySeed, authoritySeed: authoritySeed,
@ -309,6 +320,10 @@ export class StakeInstruction {
index: stakeAuthorizationType, index: stakeAuthorizationType,
}, },
}; };
if (instruction.keys.length > 3) {
o.custodianPubkey = instruction.keys[3].pubkey;
}
return o;
} }
/** /**
@ -343,12 +358,16 @@ export class StakeInstruction {
instruction.data, instruction.data,
); );
return { const o: WithdrawStakeParams = {
stakePubkey: instruction.keys[0].pubkey, stakePubkey: instruction.keys[0].pubkey,
toPubkey: instruction.keys[1].pubkey, toPubkey: instruction.keys[1].pubkey,
authorizedPubkey: instruction.keys[4].pubkey, authorizedPubkey: instruction.keys[4].pubkey,
lamports, lamports,
}; };
if (instruction.keys.length > 5) {
o.custodianPubkey = instruction.keys[5].pubkey;
}
return o;
} }
/** /**
@ -601,6 +620,7 @@ export class StakeProgram {
authorizedPubkey, authorizedPubkey,
newAuthorizedPubkey, newAuthorizedPubkey,
stakeAuthorizationType, stakeAuthorizationType,
custodianPubkey,
} = params; } = params;
const type = STAKE_INSTRUCTION_LAYOUTS.Authorize; const type = STAKE_INSTRUCTION_LAYOUTS.Authorize;
@ -609,12 +629,16 @@ export class StakeProgram {
stakeAuthorizationType: stakeAuthorizationType.index, stakeAuthorizationType: stakeAuthorizationType.index,
}); });
return new Transaction().add({ const keys = [
keys: [
{pubkey: stakePubkey, isSigner: false, isWritable: true}, {pubkey: stakePubkey, isSigner: false, isWritable: true},
{pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: true}, {pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: true},
{pubkey: authorizedPubkey, isSigner: true, isWritable: false}, {pubkey: authorizedPubkey, isSigner: true, isWritable: false},
], ];
if (custodianPubkey) {
keys.push({pubkey: custodianPubkey, isSigner: false, isWritable: false});
}
return new Transaction().add({
keys,
programId: this.programId, programId: this.programId,
data, data,
}); });
@ -632,6 +656,7 @@ export class StakeProgram {
authorityOwner, authorityOwner,
newAuthorizedPubkey, newAuthorizedPubkey,
stakeAuthorizationType, stakeAuthorizationType,
custodianPubkey,
} = params; } = params;
const type = STAKE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed; const type = STAKE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed;
@ -642,12 +667,16 @@ export class StakeProgram {
authorityOwner: authorityOwner.toBuffer(), authorityOwner: authorityOwner.toBuffer(),
}); });
return new Transaction().add({ const keys = [
keys: [
{pubkey: stakePubkey, isSigner: false, isWritable: true}, {pubkey: stakePubkey, isSigner: false, isWritable: true},
{pubkey: authorityBase, isSigner: true, isWritable: false}, {pubkey: authorityBase, isSigner: true, isWritable: false},
{pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false}, {pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false},
], ];
if (custodianPubkey) {
keys.push({pubkey: custodianPubkey, isSigner: false, isWritable: false});
}
return new Transaction().add({
keys,
programId: this.programId, programId: this.programId,
data, data,
}); });
@ -687,12 +716,17 @@ export class StakeProgram {
* Generate a Transaction that withdraws deactivated Stake tokens. * Generate a Transaction that withdraws deactivated Stake tokens.
*/ */
static withdraw(params: WithdrawStakeParams): Transaction { static withdraw(params: WithdrawStakeParams): Transaction {
const {stakePubkey, authorizedPubkey, toPubkey, lamports} = params; const {
stakePubkey,
authorizedPubkey,
toPubkey,
lamports,
custodianPubkey,
} = params;
const type = STAKE_INSTRUCTION_LAYOUTS.Withdraw; const type = STAKE_INSTRUCTION_LAYOUTS.Withdraw;
const data = encodeData(type, {lamports}); const data = encodeData(type, {lamports});
return new Transaction().add({ const keys = [
keys: [
{pubkey: stakePubkey, isSigner: false, isWritable: true}, {pubkey: stakePubkey, isSigner: false, isWritable: true},
{pubkey: toPubkey, isSigner: false, isWritable: true}, {pubkey: toPubkey, isSigner: false, isWritable: true},
{pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false}, {pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false},
@ -702,7 +736,12 @@ export class StakeProgram {
isWritable: false, isWritable: false,
}, },
{pubkey: authorizedPubkey, isSigner: true, isWritable: false}, {pubkey: authorizedPubkey, isSigner: true, isWritable: false},
], ];
if (custodianPubkey) {
keys.push({pubkey: custodianPubkey, isSigner: false, isWritable: false});
}
return new Transaction().add({
keys,
programId: this.programId, programId: this.programId,
data, data,
}); });

View File

@ -129,6 +129,25 @@ test('authorize', () => {
expect(params).toEqual(StakeInstruction.decodeAuthorize(stakeInstruction)); expect(params).toEqual(StakeInstruction.decodeAuthorize(stakeInstruction));
}); });
test('authorize with custodian', () => {
const stakePubkey = new Account().publicKey;
const authorizedPubkey = new Account().publicKey;
const newAuthorizedPubkey = new Account().publicKey;
const stakeAuthorizationType = StakeAuthorizationLayout.Withdrawer;
const custodianPubkey = new Account().publicKey;
const params = {
stakePubkey,
authorizedPubkey,
newAuthorizedPubkey,
stakeAuthorizationType,
custodianPubkey,
};
const transaction = StakeProgram.authorize(params);
expect(transaction.instructions).toHaveLength(1);
const [stakeInstruction] = transaction.instructions;
expect(params).toEqual(StakeInstruction.decodeAuthorize(stakeInstruction));
});
test('authorizeWithSeed', () => { test('authorizeWithSeed', () => {
const stakePubkey = new Account().publicKey; const stakePubkey = new Account().publicKey;
const authorityBase = new Account().publicKey; const authorityBase = new Account().publicKey;
@ -152,6 +171,31 @@ test('authorizeWithSeed', () => {
); );
}); });
test('authorizeWithSeed with custodian', () => {
const stakePubkey = new Account().publicKey;
const authorityBase = new Account().publicKey;
const authoritySeed = 'test string';
const authorityOwner = new Account().publicKey;
const newAuthorizedPubkey = new Account().publicKey;
const stakeAuthorizationType = StakeAuthorizationLayout.Staker;
const custodianPubkey = new Account().publicKey;
const params = {
stakePubkey,
authorityBase,
authoritySeed,
authorityOwner,
newAuthorizedPubkey,
stakeAuthorizationType,
custodianPubkey,
};
const transaction = StakeProgram.authorizeWithSeed(params);
expect(transaction.instructions).toHaveLength(1);
const [stakeInstruction] = transaction.instructions;
expect(params).toEqual(
StakeInstruction.decodeAuthorizeWithSeed(stakeInstruction),
);
});
test('split', () => { test('split', () => {
const stakePubkey = new Account().publicKey; const stakePubkey = new Account().publicKey;
const authorizedPubkey = new Account().publicKey; const authorizedPubkey = new Account().publicKey;
@ -194,6 +238,24 @@ test('withdraw', () => {
expect(params).toEqual(StakeInstruction.decodeWithdraw(stakeInstruction)); expect(params).toEqual(StakeInstruction.decodeWithdraw(stakeInstruction));
}); });
test('withdraw with custodian', () => {
const stakePubkey = new Account().publicKey;
const authorizedPubkey = new Account().publicKey;
const toPubkey = new Account().publicKey;
const custodianPubkey = new Account().publicKey;
const params = {
stakePubkey,
authorizedPubkey,
toPubkey,
lamports: 123,
custodianPubkey,
};
const transaction = StakeProgram.withdraw(params);
expect(transaction.instructions).toHaveLength(1);
const [stakeInstruction] = transaction.instructions;
expect(params).toEqual(StakeInstruction.decodeWithdraw(stakeInstruction));
});
test('deactivate', () => { test('deactivate', () => {
const stakePubkey = new Account().publicKey; const stakePubkey = new Account().publicKey;
const authorizedPubkey = new Account().publicKey; const authorizedPubkey = new Account().publicKey;