feat(stake-program): support `splitWithSeed` (#23213)
This commit is contained in:
parent
ae7fedf0b1
commit
5726f42a7c
|
@ -147,6 +147,18 @@ export type SplitStakeParams = {
|
||||||
lamports: number;
|
lamports: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split with seed transaction params
|
||||||
|
*/
|
||||||
|
export type SplitStakeWithSeedParams = {
|
||||||
|
stakePubkey: PublicKey;
|
||||||
|
authorizedPubkey: PublicKey;
|
||||||
|
splitStakePubkey: PublicKey;
|
||||||
|
basePubkey: PublicKey;
|
||||||
|
seed: string;
|
||||||
|
lamports: number;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Withdraw stake instruction params
|
* Withdraw stake instruction params
|
||||||
*/
|
*/
|
||||||
|
@ -706,25 +718,13 @@ export class StakeProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a Transaction that splits Stake tokens into another stake account
|
* @internal
|
||||||
*/
|
*/
|
||||||
static split(params: SplitStakeParams): Transaction {
|
static splitInstruction(params: SplitStakeParams): TransactionInstruction {
|
||||||
const {stakePubkey, authorizedPubkey, splitStakePubkey, lamports} = params;
|
const {stakePubkey, authorizedPubkey, splitStakePubkey, lamports} = params;
|
||||||
|
|
||||||
const transaction = new Transaction();
|
|
||||||
transaction.add(
|
|
||||||
SystemProgram.createAccount({
|
|
||||||
fromPubkey: authorizedPubkey,
|
|
||||||
newAccountPubkey: splitStakePubkey,
|
|
||||||
lamports: 0,
|
|
||||||
space: this.space,
|
|
||||||
programId: this.programId,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
const type = STAKE_INSTRUCTION_LAYOUTS.Split;
|
const type = STAKE_INSTRUCTION_LAYOUTS.Split;
|
||||||
const data = encodeData(type, {lamports});
|
const data = encodeData(type, {lamports});
|
||||||
|
return new TransactionInstruction({
|
||||||
return transaction.add({
|
|
||||||
keys: [
|
keys: [
|
||||||
{pubkey: stakePubkey, isSigner: false, isWritable: true},
|
{pubkey: stakePubkey, isSigner: false, isWritable: true},
|
||||||
{pubkey: splitStakePubkey, isSigner: false, isWritable: true},
|
{pubkey: splitStakePubkey, isSigner: false, isWritable: true},
|
||||||
|
@ -735,6 +735,56 @@ export class StakeProgram {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a Transaction that splits Stake tokens into another stake account
|
||||||
|
*/
|
||||||
|
static split(params: SplitStakeParams): Transaction {
|
||||||
|
const transaction = new Transaction();
|
||||||
|
transaction.add(
|
||||||
|
SystemProgram.createAccount({
|
||||||
|
fromPubkey: params.authorizedPubkey,
|
||||||
|
newAccountPubkey: params.splitStakePubkey,
|
||||||
|
lamports: 0,
|
||||||
|
space: this.space,
|
||||||
|
programId: this.programId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return transaction.add(this.splitInstruction(params));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a Transaction that splits Stake tokens into another account
|
||||||
|
* derived from a base public key and seed
|
||||||
|
*/
|
||||||
|
static splitWithSeed(params: SplitStakeWithSeedParams): Transaction {
|
||||||
|
const {
|
||||||
|
stakePubkey,
|
||||||
|
authorizedPubkey,
|
||||||
|
splitStakePubkey,
|
||||||
|
basePubkey,
|
||||||
|
seed,
|
||||||
|
lamports,
|
||||||
|
} = params;
|
||||||
|
const transaction = new Transaction();
|
||||||
|
transaction.add(
|
||||||
|
SystemProgram.allocate({
|
||||||
|
accountPubkey: splitStakePubkey,
|
||||||
|
basePubkey,
|
||||||
|
seed,
|
||||||
|
space: this.space,
|
||||||
|
programId: this.programId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return transaction.add(
|
||||||
|
this.splitInstruction({
|
||||||
|
stakePubkey,
|
||||||
|
authorizedPubkey,
|
||||||
|
splitStakePubkey,
|
||||||
|
lamports,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a Transaction that merges Stake accounts.
|
* Generate a Transaction that merges Stake accounts.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -220,6 +220,46 @@ describe('StakeProgram', () => {
|
||||||
expect(params).to.eql(StakeInstruction.decodeSplit(stakeInstruction));
|
expect(params).to.eql(StakeInstruction.decodeSplit(stakeInstruction));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('splitWithSeed', async () => {
|
||||||
|
const stakePubkey = Keypair.generate().publicKey;
|
||||||
|
const authorizedPubkey = Keypair.generate().publicKey;
|
||||||
|
const lamports = 123;
|
||||||
|
const seed = 'test string';
|
||||||
|
const basePubkey = Keypair.generate().publicKey;
|
||||||
|
const splitStakePubkey = await PublicKey.createWithSeed(
|
||||||
|
basePubkey,
|
||||||
|
seed,
|
||||||
|
StakeProgram.programId,
|
||||||
|
);
|
||||||
|
const transaction = StakeProgram.splitWithSeed({
|
||||||
|
stakePubkey,
|
||||||
|
authorizedPubkey,
|
||||||
|
lamports,
|
||||||
|
splitStakePubkey,
|
||||||
|
basePubkey,
|
||||||
|
seed,
|
||||||
|
});
|
||||||
|
expect(transaction.instructions).to.have.length(2);
|
||||||
|
const [systemInstruction, stakeInstruction] = transaction.instructions;
|
||||||
|
const systemParams = {
|
||||||
|
accountPubkey: splitStakePubkey,
|
||||||
|
basePubkey,
|
||||||
|
seed,
|
||||||
|
space: StakeProgram.space,
|
||||||
|
programId: StakeProgram.programId,
|
||||||
|
};
|
||||||
|
expect(systemParams).to.eql(
|
||||||
|
SystemInstruction.decodeAllocateWithSeed(systemInstruction),
|
||||||
|
);
|
||||||
|
const splitParams = {
|
||||||
|
stakePubkey,
|
||||||
|
authorizedPubkey,
|
||||||
|
splitStakePubkey,
|
||||||
|
lamports,
|
||||||
|
};
|
||||||
|
expect(splitParams).to.eql(StakeInstruction.decodeSplit(stakeInstruction));
|
||||||
|
});
|
||||||
|
|
||||||
it('merge', () => {
|
it('merge', () => {
|
||||||
const stakePubkey = Keypair.generate().publicKey;
|
const stakePubkey = Keypair.generate().publicKey;
|
||||||
const sourceStakePubKey = Keypair.generate().publicKey;
|
const sourceStakePubKey = Keypair.generate().publicKey;
|
||||||
|
@ -420,7 +460,7 @@ describe('StakeProgram', () => {
|
||||||
seed,
|
seed,
|
||||||
authorized: new Authorized(authorized.publicKey, authorized.publicKey),
|
authorized: new Authorized(authorized.publicKey, authorized.publicKey),
|
||||||
lockup: new Lockup(0, 0, new PublicKey(0)),
|
lockup: new Lockup(0, 0, new PublicKey(0)),
|
||||||
lamports: 3 * minimumAmount + 42,
|
lamports: 4 * minimumAmount + 62,
|
||||||
});
|
});
|
||||||
|
|
||||||
await sendAndConfirmTransaction(
|
await sendAndConfirmTransaction(
|
||||||
|
@ -430,7 +470,7 @@ describe('StakeProgram', () => {
|
||||||
{preflightCommitment: 'confirmed'},
|
{preflightCommitment: 'confirmed'},
|
||||||
);
|
);
|
||||||
let originalStakeBalance = await connection.getBalance(newAccountPubkey);
|
let originalStakeBalance = await connection.getBalance(newAccountPubkey);
|
||||||
expect(originalStakeBalance).to.eq(3 * minimumAmount + 42);
|
expect(originalStakeBalance).to.eq(4 * minimumAmount + 62);
|
||||||
|
|
||||||
let delegation = StakeProgram.delegate({
|
let delegation = StakeProgram.delegate({
|
||||||
stakePubkey: newAccountPubkey,
|
stakePubkey: newAccountPubkey,
|
||||||
|
@ -502,7 +542,34 @@ describe('StakeProgram', () => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const balance = await connection.getBalance(newAccountPubkey);
|
const balance = await connection.getBalance(newAccountPubkey);
|
||||||
expect(balance).to.eq(minimumAmount + 2);
|
expect(balance).to.eq(2 * minimumAmount + 22);
|
||||||
|
|
||||||
|
// Split stake with seed
|
||||||
|
const seed2 = 'test string 2';
|
||||||
|
const newStake2 = await PublicKey.createWithSeed(
|
||||||
|
payer.publicKey,
|
||||||
|
seed2,
|
||||||
|
StakeProgram.programId,
|
||||||
|
);
|
||||||
|
let splitWithSeed = StakeProgram.splitWithSeed({
|
||||||
|
stakePubkey: newAccountPubkey,
|
||||||
|
authorizedPubkey: authorized.publicKey,
|
||||||
|
lamports: minimumAmount + 20,
|
||||||
|
splitStakePubkey: newStake2,
|
||||||
|
basePubkey: payer.publicKey,
|
||||||
|
seed: seed2,
|
||||||
|
});
|
||||||
|
await sendAndConfirmTransaction(
|
||||||
|
connection,
|
||||||
|
splitWithSeed,
|
||||||
|
[payer, authorized],
|
||||||
|
{
|
||||||
|
preflightCommitment: 'confirmed',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(await connection.getBalance(newAccountPubkey)).to.eq(
|
||||||
|
minimumAmount + 2,
|
||||||
|
);
|
||||||
|
|
||||||
// Merge stake
|
// Merge stake
|
||||||
let merge = StakeProgram.merge({
|
let merge = StakeProgram.merge({
|
||||||
|
|
Loading…
Reference in New Issue